From fd0330e8e72ddcfe5e67ff3968ceb88b16f78872 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 11 2023 14:25:15 +0000 Subject: import grub2-2.06-46.el9_1.5 --- diff --git a/.gitignore b/.gitignore index 4acae17..dca6c5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -SOURCES/gnulib-fixes.tar.gz +SOURCES/gnulib-9f48fb992a3d7e96610c4ce8be969cff2d61a01b.tar.gz SOURCES/grub-2.06.tar.xz SOURCES/theme.tar.bz2 SOURCES/unifont-13.0.06.pcf.gz diff --git a/.grub2.metadata b/.grub2.metadata index 88b5cc8..3b87954 100644 --- a/.grub2.metadata +++ b/.grub2.metadata @@ -1,4 +1,4 @@ -1a07692dfaa916675a92b1383885141f490f98d2 SOURCES/gnulib-fixes.tar.gz +d08376d97163f99ce0d61fce160d6f7667c5c944 SOURCES/gnulib-9f48fb992a3d7e96610c4ce8be969cff2d61a01b.tar.gz c9f93f1e195ec7a5a21d36a13b469788c0b29f0f SOURCES/grub-2.06.tar.xz cf0b7763c528902da7e8b05cfa248f20c8825ce5 SOURCES/theme.tar.bz2 3b39cb0830367171760ec536cab805abdbe08bc5 SOURCES/unifont-13.0.06.pcf.gz diff --git a/README.debrand b/README.debrand deleted file mode 100644 index 01c46d2..0000000 --- a/README.debrand +++ /dev/null @@ -1,2 +0,0 @@ -Warning: This package was configured for automatic debranding, but the changes -failed to apply. diff --git a/SOURCES/0007-Add-secureboot-support-on-efi-chainloader.patch b/SOURCES/0007-Add-secureboot-support-on-efi-chainloader.patch index bfb5a9b..34ead63 100644 --- a/SOURCES/0007-Add-secureboot-support-on-efi-chainloader.patch +++ b/SOURCES/0007-Add-secureboot-support-on-efi-chainloader.patch @@ -164,18 +164,33 @@ following branches: Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1347291 Signed-off-by: Laszlo Ersek + +Also: + +commit cc06f149fbd2d8c1da1e83173d21629ba97e0d92 +Author: Raymund Will + +chainloader: Define machine types for RISC-V + +The commit "Add secureboot support on efi chainloader" didn't add machine +types for RISC-V, so this patch adds them. + +Note, that grub-core/loader/riscv/linux.c is skipped because Linux is not +supported yet. This patch might need a new revision once that's the case. + +Signed-off-by: David Abdurachmanov --- grub-core/kern/efi/efi.c | 14 +- grub-core/loader/arm64/linux.c | 4 +- - grub-core/loader/efi/chainloader.c | 816 +++++++++++++++++++++++++++++++++---- + grub-core/loader/efi/chainloader.c | 820 +++++++++++++++++++++++++++++++++---- grub-core/loader/efi/linux.c | 25 +- grub-core/loader/i386/efi/linux.c | 17 +- include/grub/efi/linux.h | 2 +- include/grub/efi/pe32.h | 52 ++- - 7 files changed, 840 insertions(+), 90 deletions(-) + 7 files changed, 844 insertions(+), 90 deletions(-) diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index 35b8f670602..4a2259aa1c7 100644 +index 35b8f67060..4a2259aa1c 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -296,14 +296,20 @@ grub_efi_secure_boot (void) @@ -204,7 +219,7 @@ index 35b8f670602..4a2259aa1c7 100644 if (*secure_boot && !*setup_mode) ret = 1; diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index a312c668685..04994d5c67d 100644 +index a312c66868..04994d5c67 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -284,6 +284,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), @@ -226,7 +241,7 @@ index a312c668685..04994d5c67d 100644 grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); goto fail; diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 2bd80f4db3d..b54cf6986fc 100644 +index 2bd80f4db3..e6a8d4ad0e 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -32,6 +32,8 @@ @@ -261,7 +276,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 grub_dl_unref (my_mod); return GRUB_ERR_NONE; -@@ -213,20 +221,690 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) +@@ -213,20 +221,694 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) return file_path; } @@ -376,6 +391,10 @@ index 2bd80f4db3d..b54cf6986fc 100644 + GRUB_PE32_MACHINE_I386; +#elif defined(__ia64__) + GRUB_PE32_MACHINE_IA64; ++#elif defined(__riscv) && (__riscv_xlen == 32) ++ GRUB_PE32_MACHINE_RISCV32; ++#elif defined(__riscv) && (__riscv_xlen == 64) ++ GRUB_PE32_MACHINE_RISCV64; +#else +#error this architecture is not supported by grub2 +#endif @@ -955,7 +974,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -@@ -238,15 +916,45 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), +@@ -238,15 +920,45 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), address = 0; image_handle = 0; file_path = 0; @@ -1003,7 +1022,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 if (! dev) goto fail; -@@ -283,17 +991,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), +@@ -283,17 +995,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), if (! file_path) goto fail; @@ -1024,7 +1043,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, GRUB_EFI_LOADER_CODE, -@@ -307,7 +1012,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), +@@ -307,7 +1016,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), } boot_image = (void *) ((grub_addr_t) address); @@ -1033,7 +1052,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 { if (grub_errno == GRUB_ERR_NONE) grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), -@@ -317,7 +1022,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), +@@ -317,7 +1026,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), } #if defined (__i386__) || defined (__x86_64__) @@ -1042,7 +1061,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 { struct grub_macho_fat_header *head = boot_image; if (head->magic -@@ -326,6 +1031,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), +@@ -326,6 +1035,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), grub_uint32_t i; struct grub_macho_fat_arch *archs = (struct grub_macho_fat_arch *) (head + 1); @@ -1057,7 +1076,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 for (i = 0; i < grub_cpu_to_le32 (head->nfat_arch); i++) { if (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT (archs[i].cputype)) -@@ -340,79 +1053,39 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), +@@ -340,79 +1057,39 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), > ~grub_cpu_to_le32 (archs[i].size) || grub_cpu_to_le32 (archs[i].offset) + grub_cpu_to_le32 (archs[i].size) @@ -1154,7 +1173,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 if (dev) grub_device_close (dev); -@@ -424,6 +1097,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), +@@ -424,6 +1101,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), if (address) efi_call_2 (b->free_pages, address, pages); @@ -1165,7 +1184,7 @@ index 2bd80f4db3d..b54cf6986fc 100644 return grub_errno; diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c -index c24202a5dd1..c8ecce6dfd0 100644 +index c24202a5dd..c8ecce6dfd 100644 --- a/grub-core/loader/efi/linux.c +++ b/grub-core/loader/efi/linux.c @@ -33,21 +33,34 @@ struct grub_efi_shim_lock @@ -1210,7 +1229,7 @@ index c24202a5dd1..c8ecce6dfd0 100644 #pragma GCC diagnostic push diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index bb2616a8092..6b24cbb9483 100644 +index bb2616a809..6b24cbb948 100644 --- a/grub-core/loader/i386/efi/linux.c +++ b/grub-core/loader/i386/efi/linux.c @@ -117,6 +117,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), @@ -1278,7 +1297,7 @@ index bb2616a8092..6b24cbb9483 100644 grub_file_close (file); diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h -index d9ede36773b..0033d9305a9 100644 +index d9ede36773..0033d9305a 100644 --- a/include/grub/efi/linux.h +++ b/include/grub/efi/linux.h @@ -22,7 +22,7 @@ @@ -1291,7 +1310,7 @@ index d9ede36773b..0033d9305a9 100644 grub_err_t EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h -index 0ed8781f037..a43adf27464 100644 +index 0ed8781f03..a43adf2746 100644 --- a/include/grub/efi/pe32.h +++ b/include/grub/efi/pe32.h @@ -223,7 +223,11 @@ struct grub_pe64_optional_header diff --git a/SOURCES/0010-re-write-.gitignore.patch b/SOURCES/0010-re-write-.gitignore.patch index 74cb0da..b6fa0be 100644 --- a/SOURCES/0010-re-write-.gitignore.patch +++ b/SOURCES/0010-re-write-.gitignore.patch @@ -4,14 +4,14 @@ Date: Mon, 8 Jul 2019 12:55:29 +0200 Subject: [PATCH] re-write .gitignore --- - .gitignore | 152 ++++++++++++++++++++++++++++++++++++++ + .gitignore | 150 ++++++++++++++++++++++++++++++++++++++ docs/.gitignore | 5 ++ grub-core/.gitignore | 16 ++++ grub-core/lib/.gitignore | 1 + include/grub/gcrypt/.gitignore | 2 + po/.gitignore | 5 ++ util/bash-completion.d/.gitignore | 2 + - 7 files changed, 183 insertions(+) + 7 files changed, 181 insertions(+) create mode 100644 docs/.gitignore create mode 100644 grub-core/.gitignore create mode 100644 grub-core/lib/.gitignore @@ -20,10 +20,10 @@ Subject: [PATCH] re-write .gitignore create mode 100644 util/bash-completion.d/.gitignore diff --git a/.gitignore b/.gitignore -index f6a1bd05175..594d0134d33 100644 +index f6a1bd0517..208d1d2325 100644 --- a/.gitignore +++ b/.gitignore -@@ -275,3 +275,155 @@ widthspec.bin +@@ -275,3 +275,153 @@ widthspec.bin /xfs_test /xzcompress_test /zfs_test @@ -152,8 +152,6 @@ index f6a1bd05175..594d0134d33 100644 +/grub*-reboot.8 +/grub*-render-label +/grub*-render-label.1 -+/grub*-rpm-sort -+/grub*-rpm-sort.8 +/grub*-script-check +/grub*-script-check.1 +/grub*-set-bootflag @@ -181,7 +179,7 @@ index f6a1bd05175..594d0134d33 100644 +/widthspec.h diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 -index 00000000000..e1d849ef95b +index 0000000000..e1d849ef95 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,5 @@ @@ -192,7 +190,7 @@ index 00000000000..e1d849ef95b +/version*.texi diff --git a/grub-core/.gitignore b/grub-core/.gitignore new file mode 100644 -index 00000000000..2acce281159 +index 0000000000..2acce28115 --- /dev/null +++ b/grub-core/.gitignore @@ -0,0 +1,16 @@ @@ -214,14 +212,14 @@ index 00000000000..2acce281159 +/trigtables.c diff --git a/grub-core/lib/.gitignore b/grub-core/lib/.gitignore new file mode 100644 -index 00000000000..68154591404 +index 0000000000..6815459140 --- /dev/null +++ b/grub-core/lib/.gitignore @@ -0,0 +1 @@ +/libgcrypt-grub/ diff --git a/include/grub/gcrypt/.gitignore b/include/grub/gcrypt/.gitignore new file mode 100644 -index 00000000000..8fbf5646246 +index 0000000000..8fbf564624 --- /dev/null +++ b/include/grub/gcrypt/.gitignore @@ -0,0 +1,2 @@ @@ -229,7 +227,7 @@ index 00000000000..8fbf5646246 +gcrypt.h diff --git a/po/.gitignore b/po/.gitignore new file mode 100644 -index 00000000000..f507e7741e3 +index 0000000000..f507e7741e --- /dev/null +++ b/po/.gitignore @@ -0,0 +1,5 @@ @@ -240,7 +238,7 @@ index 00000000000..f507e7741e3 +/stamp-po diff --git a/util/bash-completion.d/.gitignore b/util/bash-completion.d/.gitignore new file mode 100644 -index 00000000000..6813a527ad3 +index 0000000000..6813a527ad --- /dev/null +++ b/util/bash-completion.d/.gitignore @@ -0,0 +1,2 @@ diff --git a/SOURCES/0011-IBM-client-architecture-CAS-reboot-support.patch b/SOURCES/0011-IBM-client-architecture-CAS-reboot-support.patch index eaaf9a4..316b9eb 100644 --- a/SOURCES/0011-IBM-client-architecture-CAS-reboot-support.patch +++ b/SOURCES/0011-IBM-client-architecture-CAS-reboot-support.patch @@ -7,16 +7,20 @@ This is an implementation of IBM client architecture (CAS) reboot for GRUB. There are cases where the POWER firmware must reboot in order to support specific features requested by a kernel. The kernel calls -ibm,client-architecture-support and it may either return or reboot with the new -feature set. eg: +ibm,client-architecture-support and it may either return or reboot with +the new feature set. eg: Calling ibm,client-architecture-support.../ Elapsed time since release of system processors: 70959 mins 50 secs Welcome to GRUB! -Instead of return to the GRUB menu, it will check if the flag for CAS reboot is -set. If so, grub will automatically boot the last booted kernel using the same -parameters +Instead of return to the GRUB menu, it will check if the flag for CAS +reboot is set. If so, grub will automatically boot the last booted +kernel using the same parameters + +Signed-off-by: Paulo Flabiano Smorigo +[rharwood@redhat.com: commit message rewrap] +Signed-off-by: Robbie Harwood --- grub-core/kern/ieee1275/openfw.c | 63 ++++++++++++++++++++++++++++++++++++++++ grub-core/normal/main.c | 19 ++++++++++++ @@ -25,7 +29,7 @@ parameters 4 files changed, 91 insertions(+) diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c -index 4d493ab7661..3a6689abb11 100644 +index 4d493ab766..3a6689abb1 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -591,3 +591,66 @@ grub_ieee1275_get_boot_dev (void) @@ -96,7 +100,7 @@ index 4d493ab7661..3a6689abb11 100644 + return 0; +} diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index c4ebe9e22ad..70614de1565 100644 +index c4ebe9e22a..70614de156 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -34,6 +34,9 @@ @@ -133,7 +137,7 @@ index c4ebe9e22ad..70614de1565 100644 grub_errno = GRUB_ERR_NONE; } diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c -index 25158407dd8..ad80399246a 100644 +index 25158407dd..ad80399246 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -28,6 +28,9 @@ @@ -158,7 +162,7 @@ index 25158407dd8..ad80399246a 100644 { char *line; diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h -index 73e2f464475..0a599607f31 100644 +index 73e2f46447..0a599607f3 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -254,6 +254,8 @@ int EXPORT_FUNC(grub_ieee1275_devalias_next) (struct grub_ieee1275_devalias *ali diff --git a/SOURCES/0012-for-ppc-reset-console-display-attr-when-clear-screen.patch b/SOURCES/0012-for-ppc-reset-console-display-attr-when-clear-screen.patch index c8bb9d3..121af84 100644 --- a/SOURCES/0012-for-ppc-reset-console-display-attr-when-clear-screen.patch +++ b/SOURCES/0012-for-ppc-reset-console-display-attr-when-clear-screen.patch @@ -10,12 +10,14 @@ This should fix this bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=908519 Signed-off-by: Peter Jones +Signed-off-by: Paulo Flabiano Smorigo +Signed-off-by: Robbie Harwood --- grub-core/term/terminfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c -index 85ecf06b4df..05c88dcf49e 100644 +index 85ecf06b4d..05c88dcf49 100644 --- a/grub-core/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -151,7 +151,7 @@ grub_terminfo_set_current (struct grub_term_output *term, diff --git a/SOURCES/0013-Disable-GRUB-video-support-for-IBM-power-machines.patch b/SOURCES/0013-Disable-GRUB-video-support-for-IBM-power-machines.patch index 430f600..917943f 100644 --- a/SOURCES/0013-Disable-GRUB-video-support-for-IBM-power-machines.patch +++ b/SOURCES/0013-Disable-GRUB-video-support-for-IBM-power-machines.patch @@ -5,6 +5,9 @@ Subject: [PATCH] Disable GRUB video support for IBM power machines Should fix the problem in bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=973205 + +Signed-off-by: Paulo Flabiano Smorigo +Signed-off-by: Robbie Harwood --- grub-core/kern/ieee1275/cmain.c | 5 ++++- grub-core/video/ieee1275.c | 9 ++++++--- @@ -12,7 +15,7 @@ https://bugzilla.redhat.com/show_bug.cgi?id=973205 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c -index 20cbbd761ec..04df9d2c667 100644 +index 20cbbd761e..04df9d2c66 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -90,7 +90,10 @@ grub_ieee1275_find_options (void) @@ -28,7 +31,7 @@ index 20cbbd761ec..04df9d2c667 100644 /* Old Macs have no key repeat, newer ones have fully working one. The ones inbetween when repeated key generates an escaoe sequence diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c -index 17a3dbbb575..b8e4b3feb32 100644 +index 17a3dbbb57..b8e4b3feb3 100644 --- a/grub-core/video/ieee1275.c +++ b/grub-core/video/ieee1275.c @@ -352,9 +352,12 @@ static struct grub_video_adapter grub_video_ieee1275_adapter = @@ -48,7 +51,7 @@ index 17a3dbbb575..b8e4b3feb32 100644 GRUB_MOD_FINI(ieee1275_fb) diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h -index 0a599607f31..b5a1d49bbc3 100644 +index 0a599607f3..b5a1d49bbc 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -148,6 +148,8 @@ enum grub_ieee1275_flag diff --git a/SOURCES/0018-Migrate-PPC-from-Yaboot-to-Grub2.patch b/SOURCES/0018-Migrate-PPC-from-Yaboot-to-Grub2.patch index ee8c7ab..1e310e9 100644 --- a/SOURCES/0018-Migrate-PPC-from-Yaboot-to-Grub2.patch +++ b/SOURCES/0018-Migrate-PPC-from-Yaboot-to-Grub2.patch @@ -3,8 +3,11 @@ From: Mark Hamzy Date: Wed, 28 Mar 2012 14:46:41 -0500 Subject: [PATCH] Migrate PPC from Yaboot to Grub2 -Add configuration support for serial terminal consoles. This will set the -maximum screen size so that text is not overwritten. +Add configuration support for serial terminal consoles. This will set +the maximum screen size so that text is not overwritten. + +Signed-off-by: Mark Hamzy +Signed-off-by: Robbie Harwood --- Makefile.util.def | 7 +++ util/grub.d/20_ppc_terminfo.in | 114 +++++++++++++++++++++++++++++++++++++++++ @@ -12,7 +15,7 @@ maximum screen size so that text is not overwritten. create mode 100644 util/grub.d/20_ppc_terminfo.in diff --git a/Makefile.util.def b/Makefile.util.def -index f8b356cc1fa..2c9b283a230 100644 +index f8b356cc1f..2c9b283a23 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -508,6 +508,13 @@ script = { @@ -31,7 +34,7 @@ index f8b356cc1fa..2c9b283a230 100644 common = util/grub.d/30_os-prober.in; diff --git a/util/grub.d/20_ppc_terminfo.in b/util/grub.d/20_ppc_terminfo.in new file mode 100644 -index 00000000000..10d66586820 +index 0000000000..10d6658682 --- /dev/null +++ b/util/grub.d/20_ppc_terminfo.in @@ -0,0 +1,114 @@ diff --git a/SOURCES/0019-Add-fw_path-variable-revised.patch b/SOURCES/0019-Add-fw_path-variable-revised.patch index df9ef83..804938b 100644 --- a/SOURCES/0019-Add-fw_path-variable-revised.patch +++ b/SOURCES/0019-Add-fw_path-variable-revised.patch @@ -8,13 +8,16 @@ found. It was originally written by Matthew Garrett, and adapted to fix the "No modules are loaded on grub2 network boot" issue: https://bugzilla.redhat.com/show_bug.cgi?id=857936 + +Signed-off-by: Paulo Flabiano Smorigo +Signed-off-by: Robbie Harwood --- grub-core/kern/main.c | 13 ++++++------- grub-core/normal/main.c | 25 ++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index 73967e2f5b0..d1de9fa6873 100644 +index 73967e2f5b..d1de9fa687 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -128,16 +128,15 @@ grub_set_prefix_and_root (void) @@ -41,7 +44,7 @@ index 73967e2f5b0..d1de9fa6873 100644 } diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 70614de1565..62571e6dfcc 100644 +index 70614de156..62571e6dfc 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -339,7 +339,30 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), diff --git a/SOURCES/0023-Don-t-write-messages-to-the-screen.patch b/SOURCES/0023-Don-t-write-messages-to-the-screen.patch deleted file mode 100644 index 01d0264..0000000 --- a/SOURCES/0023-Don-t-write-messages-to-the-screen.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Wed, 15 May 2013 13:30:20 -0400 -Subject: [PATCH] Don't write messages to the screen - -Writing messages to the screen before the menus or boot splash -happens so quickly it looks like something is wrong and isn't -very appealing. ---- - grub-core/gettext/gettext.c | 25 +++++-------------------- - grub-core/kern/main.c | 5 ----- - grub-core/boot/i386/pc/boot.S | 3 --- - grub-core/boot/i386/pc/diskboot.S | 5 ----- - util/grub.d/10_linux.in | 7 ------- - 5 files changed, 5 insertions(+), 40 deletions(-) - -diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c -index 4d02e62c109..84d520cd494 100644 ---- a/grub-core/gettext/gettext.c -+++ b/grub-core/gettext/gettext.c -@@ -434,16 +434,12 @@ static char * - grub_gettext_env_write_lang (struct grub_env_var *var - __attribute__ ((unused)), const char *val) - { -- grub_err_t err; -+ grub_err_t __attribute__((__unused__)) err; - err = grub_gettext_init_ext (&main_context, val, grub_env_get ("locale_dir"), - grub_env_get ("prefix")); -- if (err) -- grub_print_error (); - - err = grub_gettext_init_ext (&secondary_context, val, - grub_env_get ("secondary_locale_dir"), 0); -- if (err) -- grub_print_error (); - - return grub_strdup (val); - } -@@ -451,23 +447,19 @@ grub_gettext_env_write_lang (struct grub_env_var *var - void - grub_gettext_reread_prefix (const char *val) - { -- grub_err_t err; -+ grub_err_t __attribute__((__unused__)) err; - err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), - grub_env_get ("locale_dir"), - val); -- if (err) -- grub_print_error (); - } - - static char * - read_main (struct grub_env_var *var - __attribute__ ((unused)), const char *val) - { -- grub_err_t err; -+ grub_err_t __attribute__((__unused__)) err; - err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), val, - grub_env_get ("prefix")); -- if (err) -- grub_print_error (); - return grub_strdup (val); - } - -@@ -475,12 +467,9 @@ static char * - read_secondary (struct grub_env_var *var - __attribute__ ((unused)), const char *val) - { -- grub_err_t err; -+ grub_err_t __attribute__((__unused__)) err; - err = grub_gettext_init_ext (&secondary_context, grub_env_get ("lang"), val, - 0); -- if (err) -- grub_print_error (); -- - return grub_strdup (val); - } - -@@ -500,18 +489,14 @@ grub_cmd_translate (grub_command_t cmd __attribute__ ((unused)), - GRUB_MOD_INIT (gettext) - { - const char *lang; -- grub_err_t err; -+ grub_err_t __attribute__((__unused__)) err; - - lang = grub_env_get ("lang"); - - err = grub_gettext_init_ext (&main_context, lang, grub_env_get ("locale_dir"), - grub_env_get ("prefix")); -- if (err) -- grub_print_error (); - err = grub_gettext_init_ext (&secondary_context, lang, - grub_env_get ("secondary_locale_dir"), 0); -- if (err) -- grub_print_error (); - - grub_register_variable_hook ("locale_dir", NULL, read_main); - grub_register_variable_hook ("secondary_locale_dir", NULL, read_secondary); -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index d1de9fa6873..48058d983ce 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -269,11 +269,6 @@ grub_main (void) - - grub_boot_time ("After machine init."); - -- /* Hello. */ -- grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); -- grub_printf ("Welcome to GRUB!\n\n"); -- grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); -- - /* Init verifiers API. */ - grub_verifiers_init (); - -diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S -index 2bd0b2d2866..ea167fe1206 100644 ---- a/grub-core/boot/i386/pc/boot.S -+++ b/grub-core/boot/i386/pc/boot.S -@@ -249,9 +249,6 @@ real_start: - /* save drive reference first thing! */ - pushw %dx - -- /* print a notification message on the screen */ -- MSG(notification_string) -- - /* set %si to the disk address packet */ - movw $disk_address_packet, %si - -diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S -index c1addc0df29..68d31de0c4c 100644 ---- a/grub-core/boot/i386/pc/diskboot.S -+++ b/grub-core/boot/i386/pc/diskboot.S -@@ -50,11 +50,6 @@ _start: - /* save drive reference first thing! */ - pushw %dx - -- /* print a notification message on the screen */ -- pushw %si -- MSG(notification_string) -- popw %si -- - /* this sets up for the first run through "bootloop" */ - movw $LOCAL(firstlist), %di - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index dc75a1c30bf..ad2ac4b078d 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -138,27 +138,20 @@ linux_entry () - fi - printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" - fi -- message="$(gettext_printf "Loading Linux %s ..." ${version})" - sed "s/^/$submenu_indentation/" << EOF -- echo '$(echo "$message" | grub_quote)' - linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} - EOF - if test -n "${initrd}" ; then -- # TRANSLATORS: ramdisk isn't identifier. Should be translated. -- message="$(gettext_printf "Loading initial ramdisk ...")" - initrd_path= - for i in ${initrd}; do - initrd_path="${initrd_path} ${rel_dirname}/${i}" - done - sed "s/^/$submenu_indentation/" << EOF -- echo '$(echo "$message" | grub_quote)' - initrd $(echo $initrd_path) - EOF - fi - if test -n "${fdt}" ; then -- message="$(gettext_printf "Loading fdt ...")" - sed "s/^/$submenu_indentation/" << EOF -- echo '$(echo "$message" | grub_quote)' - devicetree ${rel_dirname}/${fdt} - EOF - fi diff --git a/SOURCES/0023-Enable-pager-by-default.-985860.patch b/SOURCES/0023-Enable-pager-by-default.-985860.patch new file mode 100644 index 0000000..63cf787 --- /dev/null +++ b/SOURCES/0023-Enable-pager-by-default.-985860.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 28 Oct 2013 10:09:27 -0400 +Subject: [PATCH] Enable pager by default. (#985860) + +Signed-off-by: Peter Jones +--- + util/grub.d/00_header.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in +index 93a90233ea..858b526c92 100644 +--- a/util/grub.d/00_header.in ++++ b/util/grub.d/00_header.in +@@ -43,6 +43,8 @@ if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_ + if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT" ; fi + + cat << EOF ++set pager=1 ++ + if [ -s \$prefix/grubenv ]; then + load_env + fi diff --git a/SOURCES/0024-Don-t-print-GNU-GRUB-header.patch b/SOURCES/0024-Don-t-print-GNU-GRUB-header.patch deleted file mode 100644 index c903fd4..0000000 --- a/SOURCES/0024-Don-t-print-GNU-GRUB-header.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Wed, 15 May 2013 13:53:48 -0400 -Subject: [PATCH] Don't print GNU GRUB header - -No one cares. ---- - grub-core/normal/main.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 7ca2e5400b1..5d5f7b539f5 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -208,15 +208,16 @@ read_config_file (const char *config) - /* Initialize the screen. */ - void - grub_normal_init_page (struct grub_term_output *term, -- int y) -+ int y __attribute__((__unused__))) - { -+ grub_term_cls (term); -+ -+#if 0 - grub_ssize_t msg_len; - int posx; - char *msg_formatted; - grub_uint32_t *unicode_msg; - grub_uint32_t *last_position; -- -- grub_term_cls (term); - - msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION); - if (!msg_formatted) -@@ -241,6 +242,7 @@ grub_normal_init_page (struct grub_term_output *term, - grub_putcode ('\n', term); - grub_putcode ('\n', term); - grub_free (unicode_msg); -+#endif - } - - static void diff --git a/SOURCES/0024-Don-t-say-GNU-Linux-in-generated-menus.patch b/SOURCES/0024-Don-t-say-GNU-Linux-in-generated-menus.patch new file mode 100644 index 0000000..5b96784 --- /dev/null +++ b/SOURCES/0024-Don-t-say-GNU-Linux-in-generated-menus.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 14 Mar 2011 14:27:42 -0400 +Subject: [PATCH] Don't say "GNU/Linux" in generated menus. + +[rharwood: say it even less] +--- + grub-core/normal/main.c | 2 +- + tests/util/grub-shell-tester.in | 2 +- + tests/util/grub-shell.in | 2 +- + util/grub.d/10_linux.in | 4 ++-- + util/grub.d/20_linux_xen.in | 4 ++-- + 5 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 7ca2e5400b..98372217ad 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -218,7 +218,7 @@ grub_normal_init_page (struct grub_term_output *term, + + grub_term_cls (term); + +- msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION); ++ msg_formatted = grub_xasprintf (_("GRUB version %s"), PACKAGE_VERSION); + if (!msg_formatted) + return; + +diff --git a/tests/util/grub-shell-tester.in b/tests/util/grub-shell-tester.in +index 8a87109b15..9a4319d4f4 100644 +--- a/tests/util/grub-shell-tester.in ++++ b/tests/util/grub-shell-tester.in +@@ -56,7 +56,7 @@ for option in "$@"; do + usage + exit 0 ;; + -v | --version) +- echo "$0 (GNU GRUB ${PACKAGE_VERSION})" ++ echo "$0 (GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --modules=*) + ms=`echo "$option" | sed -e 's/--modules=//'` +diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in +index 93e9f51484..ec1182bf93 100644 +--- a/tests/util/grub-shell.in ++++ b/tests/util/grub-shell.in +@@ -209,7 +209,7 @@ for option in "$@"; do + usage + exit 0 ;; + -v | --version) +- echo "$0 (GNU GRUB ${PACKAGE_VERSION})" ++ echo "$0 (GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --trim) + trim=1 +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index dc75a1c30b..4a499c53a6 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@" + CLASS="--class gnu-linux --class gnu --class os" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then +- OS=GNU/Linux ++ OS="$(sed 's, release .*$,,g' /etc/system-release)" + else +- OS="${GRUB_DISTRIBUTOR} GNU/Linux" ++ OS="${GRUB_DISTRIBUTOR}" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" + fi + +diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in +index 3b1f470492..ada20775a1 100644 +--- a/util/grub.d/20_linux_xen.in ++++ b/util/grub.d/20_linux_xen.in +@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@" + CLASS="--class gnu-linux --class gnu --class os --class xen" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then +- OS=GNU/Linux ++ OS="$(sed 's, release .*$,,g' /etc/system-release)" + else +- OS="${GRUB_DISTRIBUTOR} GNU/Linux" ++ OS="${GRUB_DISTRIBUTOR}" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" + fi + diff --git a/SOURCES/0025-Add-.eh_frame-to-list-of-relocations-stripped.patch b/SOURCES/0025-Add-.eh_frame-to-list-of-relocations-stripped.patch new file mode 100644 index 0000000..0532a04 --- /dev/null +++ b/SOURCES/0025-Add-.eh_frame-to-list-of-relocations-stripped.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Mon, 13 Jan 2014 21:50:59 -0500 +Subject: [PATCH] Add .eh_frame to list of relocations stripped + +--- + conf/Makefile.common | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 2a1a886f6d..191b1a70c6 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -38,7 +38,7 @@ CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) + CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 + CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) +-STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx ++STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx + + CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d diff --git a/SOURCES/0025-Don-t-add-to-highlighted-row.patch b/SOURCES/0025-Don-t-add-to-highlighted-row.patch deleted file mode 100644 index b83f543..0000000 --- a/SOURCES/0025-Don-t-add-to-highlighted-row.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Wed, 15 May 2013 17:49:45 -0400 -Subject: [PATCH] Don't add '*' to highlighted row - -It is already highlighted. ---- - grub-core/normal/menu_text.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index 18240e76cea..65deafda531 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -242,7 +242,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, - unicode_title[i] = ' '; - - if (data->geo.num_entries > 1) -- grub_putcode (highlight ? '*' : ' ', data->term); -+ grub_putcode (' ', data->term); - - grub_print_ucs4_menu (unicode_title, - unicode_title + len, diff --git a/SOURCES/0026-Don-t-require-a-password-to-boot-entries-generated-b.patch b/SOURCES/0026-Don-t-require-a-password-to-boot-entries-generated-b.patch new file mode 100644 index 0000000..89887c1 --- /dev/null +++ b/SOURCES/0026-Don-t-require-a-password-to-boot-entries-generated-b.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 11 Feb 2014 11:14:50 -0500 +Subject: [PATCH] Don't require a password to boot entries generated by + grub-mkconfig. + +When we set a password, we just want that to mean you can't /edit/ an entry. + +Resolves: rhbz#1030176 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 4a499c53a6..cf8d118698 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -26,7 +26,7 @@ datarootdir="@datarootdir@" + export TEXTDOMAIN=@PACKAGE@ + export TEXTDOMAINDIR="@localedir@" + +-CLASS="--class gnu-linux --class gnu --class os" ++CLASS="--class gnu-linux --class gnu --class os --unrestricted" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then + OS="$(sed 's, release .*$,,g' /etc/system-release)" diff --git a/SOURCES/0026-Message-string-cleanups.patch b/SOURCES/0026-Message-string-cleanups.patch deleted file mode 100644 index e23ee1a..0000000 --- a/SOURCES/0026-Message-string-cleanups.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Fri, 7 Jun 2013 11:09:04 -0400 -Subject: [PATCH] Message string cleanups - -Make use of terminology consistent. Remove jargon. ---- - grub-core/normal/menu_text.c | 21 +++++++++------------ - 1 file changed, 9 insertions(+), 12 deletions(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index 65deafda531..cc5837ed2b8 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -157,9 +157,8 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run) - - if (edit) - { -- ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \ --supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \ --command-line or ESC to discard edits and return to the GRUB menu."), -+ ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \ -+command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."), - STANDARD_MARGIN, STANDARD_MARGIN, - term, dry_run); - } -@@ -167,8 +166,8 @@ command-line or ESC to discard edits and return to the GRUB menu."), - { - char *msg_translated; - -- msg_translated = grub_xasprintf (_("Use the %C and %C keys to select which " -- "entry is highlighted."), -+ msg_translated = grub_xasprintf (_("Use the %C and %C keys to change the " -+ "selection."), - GRUB_UNICODE_UPARROW, - GRUB_UNICODE_DOWNARROW); - if (!msg_translated) -@@ -181,17 +180,15 @@ command-line or ESC to discard edits and return to the GRUB menu."), - if (nested) - { - ret += grub_print_message_indented_real -- (_("Press enter to boot the selected OS, " -- "`e' to edit the commands before booting " -- "or `c' for a command-line. ESC to return previous menu."), -+ (_("Press 'e' to edit the selected item, " -+ "or 'c' for a command prompt. Press Escape to return to the previous menu."), - STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); - } - else - { - ret += grub_print_message_indented_real -- (_("Press enter to boot the selected OS, " -- "`e' to edit the commands before booting " -- "or `c' for a command-line."), -+ (_("Press 'e' to edit the selected item, " -+ "or 'c' for a command prompt."), - STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); - } - } -@@ -443,7 +440,7 @@ menu_text_print_timeout (int timeout, void *dataptr) - || data->timeout_msg == TIMEOUT_TERSE_NO_MARGIN) - msg_translated = grub_xasprintf (_("%ds"), timeout); - else -- msg_translated = grub_xasprintf (_("The highlighted entry will be executed automatically in %ds."), timeout); -+ msg_translated = grub_xasprintf (_("The selected entry will be started automatically in %ds."), timeout); - if (!msg_translated) - { - grub_print_error (); diff --git a/SOURCES/0027-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch b/SOURCES/0027-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch deleted file mode 100644 index 920ef79..0000000 --- a/SOURCES/0027-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Fri, 7 Jun 2013 14:08:23 -0400 -Subject: [PATCH] Fix border spacing now that we aren't displaying it - ---- - grub-core/normal/menu_text.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index cc5837ed2b8..b49835a9af7 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -331,12 +331,12 @@ grub_menu_init_page (int nested, int edit, - int empty_lines = 1; - int version_msg = 1; - -- geo->border = 1; -- geo->first_entry_x = 1 /* margin */ + 1 /* border */; -+ geo->border = 0; -+ geo->first_entry_x = 0 /* margin */ + 0 /* border */; - geo->entry_width = grub_term_width (term) - 5; - - geo->first_entry_y = 2 /* two empty lines*/ -- + 1 /* GNU GRUB version text */ + 1 /* top border */; -+ + 0 /* GNU GRUB version text */ + 1 /* top border */; - - geo->timeout_lines = 2; - diff --git a/SOURCES/0027-use-fw_path-prefix-when-fallback-searching-for-grub-.patch b/SOURCES/0027-use-fw_path-prefix-when-fallback-searching-for-grub-.patch new file mode 100644 index 0000000..1da91e1 --- /dev/null +++ b/SOURCES/0027-use-fw_path-prefix-when-fallback-searching-for-grub-.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Wed, 19 Feb 2014 15:58:43 -0500 +Subject: [PATCH] use fw_path prefix when fallback searching for grub config + +When PXE booting via UEFI firmware, grub was searching for grub.cfg +in the fw_path directory where the grub application was found. If +that didn't exist, a fallback search would look for config file names +based on MAC and IP address. However, the search would look in the +prefix directory which may not be the same fw_path. This patch +changes that behavior to use the fw_path directory for the fallback +search. Only if fw_path is NULL will the prefix directory be searched. + +Signed-off-by: Mark Salter +--- + grub-core/normal/main.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 98372217ad..bf24e65713 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -347,7 +347,7 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + char *config; + const char *prefix, *fw_path; + +- fw_path = grub_env_get ("fw_path"); ++ prefix = fw_path = grub_env_get ("fw_path"); + if (fw_path) + { + config = grub_xasprintf ("%s/grub.cfg", fw_path); +@@ -370,7 +370,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + } + } + +- prefix = grub_env_get ("prefix"); ++ if (! prefix) ++ prefix = grub_env_get ("prefix"); + if (prefix) + { + grub_size_t config_len; diff --git a/SOURCES/0028-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch b/SOURCES/0028-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch new file mode 100644 index 0000000..0d77281 --- /dev/null +++ b/SOURCES/0028-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 8 Jul 2019 17:33:22 +0200 +Subject: [PATCH] Try mac/guid/etc before grub.cfg on tftp config files. + +Signed-off-by: Peter Jones +--- + grub-core/normal/main.c | 97 ++++++++++++++++++++++++++----------------------- + 1 file changed, 51 insertions(+), 46 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index bf24e65713..0a99768f75 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -345,61 +345,66 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + /* Guess the config filename. It is necessary to make CONFIG static, + so that it won't get broken by longjmp. */ + char *config; +- const char *prefix, *fw_path; +- +- prefix = fw_path = grub_env_get ("fw_path"); +- if (fw_path) +- { +- config = grub_xasprintf ("%s/grub.cfg", fw_path); +- if (config) +- { +- grub_file_t file; +- +- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); +- if (file) +- { +- grub_file_close (file); +- grub_enter_normal_mode (config); +- } +- else +- { +- /* Ignore all errors. */ +- grub_errno = 0; +- } +- grub_free (config); +- } +- } ++ const char *prefix; ++ const char *net_search_cfg; ++ int disable_net_search = 0; + ++ prefix = grub_env_get ("fw_path"); + if (! prefix) + prefix = grub_env_get ("prefix"); ++ ++ net_search_cfg = grub_env_get ("feature_net_search_cfg"); ++ if (net_search_cfg && net_search_cfg[0] == 'n') ++ disable_net_search = 1; ++ + if (prefix) + { +- grub_size_t config_len; +- int disable_net_search = 0; +- const char *net_search_cfg; +- +- config_len = grub_strlen (prefix) + +- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); +- config = grub_malloc (config_len); +- +- if (!config) +- goto quit; +- +- grub_snprintf (config, config_len, "%s/grub.cfg", prefix); +- +- net_search_cfg = grub_env_get ("feature_net_search_cfg"); +- if (net_search_cfg && net_search_cfg[0] == 'n') +- disable_net_search = 1; +- + if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 && + !disable_net_search) +- grub_net_search_config_file (config); ++ { ++ grub_size_t config_len; ++ config_len = grub_strlen (prefix) + ++ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); ++ config = grub_malloc (config_len); + +- grub_enter_normal_mode (config); +- grub_free (config); +- } ++ if (! config) ++ goto quit; ++ ++ grub_snprintf (config, config_len, "%s/grub.cfg", prefix); ++ ++ grub_net_search_configfile (config); ++ ++ grub_enter_normal_mode (config); ++ grub_free (config); ++ config = NULL; ++ } ++ ++ if (!config) ++ { ++ config = grub_xasprintf ("%s/grub.cfg", prefix); ++ if (config) ++ { ++ grub_file_t file; ++ ++ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); ++ if (file) ++ { ++ grub_file_close (file); ++ grub_enter_normal_mode (config); ++ } ++ else ++ { ++ /* Ignore all errors. */ ++ grub_errno = 0; ++ } ++ grub_free (config); ++ } ++ } ++ } + else +- grub_enter_normal_mode (0); ++ { ++ grub_enter_normal_mode (0); ++ } + } + else + grub_enter_normal_mode (argv[0]); diff --git a/SOURCES/0028-Use-the-correct-indentation-for-the-term-help-text.patch b/SOURCES/0028-Use-the-correct-indentation-for-the-term-help-text.patch deleted file mode 100644 index 0ce3b04..0000000 --- a/SOURCES/0028-Use-the-correct-indentation-for-the-term-help-text.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Fri, 7 Jun 2013 14:08:49 -0400 -Subject: [PATCH] Use the correct indentation for the term help text - -That is consistent with the menu help text ---- - grub-core/normal/main.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 5d5f7b539f5..ec1cd257397 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -440,8 +440,8 @@ grub_normal_reader_init (int nested) - grub_normal_init_page (term, 1); - grub_term_setcursor (term, 1); - -- if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20) -- grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term); -+ if (grub_term_width (term) > 2 * STANDARD_MARGIN + 20) -+ grub_print_message_indented (msg_formatted, STANDARD_MARGIN, STANDARD_MARGIN, term); - else - grub_print_message_indented (msg_formatted, 0, 0, term); - grub_putcode ('\n', term); diff --git a/SOURCES/0029-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch b/SOURCES/0029-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch new file mode 100644 index 0000000..f22e6f9 --- /dev/null +++ b/SOURCES/0029-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 4 Sep 2014 14:23:23 -0400 +Subject: [PATCH] Generate OS and CLASS in 10_linux from /etc/os-release + +This makes us use pretty names in the titles we generate in +grub2-mkconfig when GRUB_DISTRIBUTOR isn't set. + +Resolves: rhbz#996794 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index cf8d118698..5f6d3c8d52 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -29,7 +29,8 @@ export TEXTDOMAINDIR="@localedir@" + CLASS="--class gnu-linux --class gnu --class os --unrestricted" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then +- OS="$(sed 's, release .*$,,g' /etc/system-release)" ++ OS="$(eval $(grep PRETTY_NAME /etc/os-release) ; echo ${PRETTY_NAME})" ++ CLASS="--class $(eval $(grep '^ID_LIKE=\|^ID=' /etc/os-release) ; [ -n "${ID_LIKE}" ] && echo ${ID_LIKE} || echo ${ID}) ${CLASS}" + else + OS="${GRUB_DISTRIBUTOR}" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" diff --git a/SOURCES/0029-Indent-menu-entries.patch b/SOURCES/0029-Indent-menu-entries.patch deleted file mode 100644 index 7e588fd..0000000 --- a/SOURCES/0029-Indent-menu-entries.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Fri, 7 Jun 2013 14:30:55 -0400 -Subject: [PATCH] Indent menu entries - ---- - grub-core/normal/menu_text.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index b49835a9af7..6a57376fa80 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -239,7 +239,8 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, - unicode_title[i] = ' '; - - if (data->geo.num_entries > 1) -- grub_putcode (' ', data->term); -+ for (i = 0; i < STANDARD_MARGIN; i++) -+ grub_putcode (' ', data->term); - - grub_print_ucs4_menu (unicode_title, - unicode_title + len, diff --git a/SOURCES/0030-Fix-margins.patch b/SOURCES/0030-Fix-margins.patch deleted file mode 100644 index baa10ed..0000000 --- a/SOURCES/0030-Fix-margins.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Fri, 7 Jun 2013 14:59:36 -0400 -Subject: [PATCH] Fix margins - ---- - grub-core/normal/menu_text.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index 6a57376fa80..cbd62f714cb 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -333,17 +333,15 @@ grub_menu_init_page (int nested, int edit, - int version_msg = 1; - - geo->border = 0; -- geo->first_entry_x = 0 /* margin */ + 0 /* border */; -- geo->entry_width = grub_term_width (term) - 5; -+ geo->first_entry_x = 0; /* no margin */ -+ geo->entry_width = grub_term_width (term) - 1; - -- geo->first_entry_y = 2 /* two empty lines*/ -- + 0 /* GNU GRUB version text */ + 1 /* top border */; -+ geo->first_entry_y = 3; /* three empty lines*/ - - geo->timeout_lines = 2; - - /* 3 lines for timeout message and bottom margin. 2 lines for the border. */ - geo->num_entries = grub_term_height (term) - geo->first_entry_y -- - 1 /* bottom border */ - - 1 /* empty line before info message*/ - - geo->timeout_lines /* timeout */ - - 1 /* empty final line */; diff --git a/SOURCES/0030-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch b/SOURCES/0030-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch new file mode 100644 index 0000000..f4d83da --- /dev/null +++ b/SOURCES/0030-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 4 Sep 2014 15:52:08 -0400 +Subject: [PATCH] Minimize the sort ordering for .debug and -rescue- kernels. + +Resolves: rhbz#1065360 +Signed-off-by: Peter Jones +--- + util/grub-mkconfig_lib.in | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in +index 301d1ac229..0f6505bf3b 100644 +--- a/util/grub-mkconfig_lib.in ++++ b/util/grub-mkconfig_lib.in +@@ -253,6 +253,14 @@ version_test_gt () + *.old:*.old) ;; + *.old:*) version_test_gt_a="`echo "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;; + *:*.old) version_test_gt_b="`echo "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;; ++ *-rescue*:*-rescue*) ;; ++ *?debug:*?debug) ;; ++ *-rescue*:*?debug) return 1 ;; ++ *?debug:*-rescue*) return 0 ;; ++ *-rescue*:*) return 1 ;; ++ *:*-rescue*) return 0 ;; ++ *?debug:*) return 1 ;; ++ *:*?debug) return 0 ;; + esac + version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b" + return "$?" diff --git a/SOURCES/0031-Try-prefix-if-fw_path-doesn-t-work.patch b/SOURCES/0031-Try-prefix-if-fw_path-doesn-t-work.patch new file mode 100644 index 0000000..a1c0d9e --- /dev/null +++ b/SOURCES/0031-Try-prefix-if-fw_path-doesn-t-work.patch @@ -0,0 +1,222 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 9 Jul 2019 10:35:16 +0200 +Subject: [PATCH] Try $prefix if $fw_path doesn't work. + +Related: rhbz#1148652 + +Signed-off-by: Peter Jones +--- + grub-core/kern/ieee1275/init.c | 28 +++++---- + grub-core/net/net.c | 2 +- + grub-core/normal/main.c | 134 ++++++++++++++++++++--------------------- + 3 files changed, 82 insertions(+), 82 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index e71d158416..0cd2a62723 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -127,23 +127,25 @@ grub_machine_get_bootlocation (char **device, char **path) + grub_free (canon); + } + else +- *device = grub_ieee1275_encode_devname (bootpath); +- grub_free (type); +- +- filename = grub_ieee1275_get_filename (bootpath); +- if (filename) + { +- char *lastslash = grub_strrchr (filename, '\\'); +- +- /* Truncate at last directory. */ +- if (lastslash) ++ filename = grub_ieee1275_get_filename (bootpath); ++ if (filename) + { +- *lastslash = '\0'; +- grub_translate_ieee1275_path (filename); ++ char *lastslash = grub_strrchr (filename, '\\'); + +- *path = filename; +- } ++ /* Truncate at last directory. */ ++ if (lastslash) ++ { ++ *lastslash = '\0'; ++ grub_translate_ieee1275_path (filename); ++ ++ *path = filename; ++ } ++ } ++ *device = grub_ieee1275_encode_devname (bootpath); + } ++ ++ grub_free (type); + grub_free (bootpath); + } + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 4d3eb5c1a5..0ef148f4ad 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1869,7 +1869,7 @@ grub_net_search_config_file (char *config) + /* Remove the remaining minus sign at the end. */ + config[config_len] = '\0'; + +- return GRUB_ERR_NONE; ++ return GRUB_ERR_FILE_NOT_FOUND; + } + + static struct grub_preboot *fini_hnd; +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 0a99768f75..55558cc0b9 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -335,81 +335,79 @@ grub_enter_normal_mode (const char *config) + grub_boot_time ("Exiting normal mode"); + } + ++static grub_err_t ++grub_try_normal (const char *variable) ++{ ++ char *config; ++ const char *prefix; ++ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; ++ const char *net_search_cfg; ++ int disable_net_search = 0; ++ ++ prefix = grub_env_get (variable); ++ if (!prefix) ++ return GRUB_ERR_FILE_NOT_FOUND; ++ ++ net_search_cfg = grub_env_get ("feature_net_search_cfg"); ++ if (net_search_cfg && net_search_cfg[0] == 'n') ++ disable_net_search = 1; ++ ++ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 && ++ !disable_net_search) ++ { ++ grub_size_t config_len; ++ config_len = grub_strlen (prefix) + ++ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); ++ config = grub_malloc (config_len); ++ ++ if (! config) ++ return GRUB_ERR_FILE_NOT_FOUND; ++ ++ grub_snprintf (config, config_len, "%s/grub.cfg", prefix); ++ err = grub_net_search_config_file (config); ++ } ++ ++ if (err != GRUB_ERR_NONE) ++ { ++ config = grub_xasprintf ("%s/grub.cfg", prefix); ++ if (config) ++ { ++ grub_file_t file; ++ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); ++ if (file) ++ { ++ grub_file_close (file); ++ err = GRUB_ERR_NONE; ++ } ++ } ++ } ++ ++ if (err == GRUB_ERR_NONE) ++ grub_enter_normal_mode (config); ++ ++ grub_errno = 0; ++ grub_free (config); ++ return err; ++} ++ + /* Enter normal mode from rescue mode. */ + static grub_err_t + grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- if (argc == 0) +- { +- /* Guess the config filename. It is necessary to make CONFIG static, +- so that it won't get broken by longjmp. */ +- char *config; +- const char *prefix; +- const char *net_search_cfg; +- int disable_net_search = 0; +- +- prefix = grub_env_get ("fw_path"); +- if (! prefix) +- prefix = grub_env_get ("prefix"); +- +- net_search_cfg = grub_env_get ("feature_net_search_cfg"); +- if (net_search_cfg && net_search_cfg[0] == 'n') +- disable_net_search = 1; +- +- if (prefix) +- { +- if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 && +- !disable_net_search) +- { +- grub_size_t config_len; +- config_len = grub_strlen (prefix) + +- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); +- config = grub_malloc (config_len); +- +- if (! config) +- goto quit; +- +- grub_snprintf (config, config_len, "%s/grub.cfg", prefix); +- +- grub_net_search_configfile (config); +- +- grub_enter_normal_mode (config); +- grub_free (config); +- config = NULL; +- } +- +- if (!config) +- { +- config = grub_xasprintf ("%s/grub.cfg", prefix); +- if (config) +- { +- grub_file_t file; +- +- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); +- if (file) +- { +- grub_file_close (file); +- grub_enter_normal_mode (config); +- } +- else +- { +- /* Ignore all errors. */ +- grub_errno = 0; +- } +- grub_free (config); +- } +- } +- } +- else +- { +- grub_enter_normal_mode (0); +- } +- } +- else ++ if (argc) + grub_enter_normal_mode (argv[0]); ++ else ++ { ++ /* Guess the config filename. */ ++ grub_err_t err; ++ err = grub_try_normal ("fw_path"); ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ err = grub_try_normal ("prefix"); ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ grub_enter_normal_mode (0); ++ } + +-quit: + return 0; + } + diff --git a/SOURCES/0031-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch b/SOURCES/0031-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch deleted file mode 100644 index 7932180..0000000 --- a/SOURCES/0031-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 21 Jun 2013 14:44:08 -0400 -Subject: [PATCH] Use -2 instead of -1 for our right-hand margin, so - linewrapping works (#976643). - -Signed-off-by: Peter Jones ---- - grub-core/normal/menu_text.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index cbd62f714cb..26e9e82042a 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -334,7 +334,7 @@ grub_menu_init_page (int nested, int edit, - - geo->border = 0; - geo->first_entry_x = 0; /* no margin */ -- geo->entry_width = grub_term_width (term) - 1; -+ geo->entry_width = grub_term_width (term) - 2; - - geo->first_entry_y = 3; /* three empty lines*/ - diff --git a/SOURCES/0032-Enable-pager-by-default.-985860.patch b/SOURCES/0032-Enable-pager-by-default.-985860.patch deleted file mode 100644 index d92fbcc..0000000 --- a/SOURCES/0032-Enable-pager-by-default.-985860.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 28 Oct 2013 10:09:27 -0400 -Subject: [PATCH] Enable pager by default. (#985860) - -Signed-off-by: Peter Jones ---- - util/grub.d/00_header.in | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in -index 93a90233ead..858b526c925 100644 ---- a/util/grub.d/00_header.in -+++ b/util/grub.d/00_header.in -@@ -43,6 +43,8 @@ if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_ - if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT" ; fi - - cat << EOF -+set pager=1 -+ - if [ -s \$prefix/grubenv ]; then - load_env - fi diff --git a/SOURCES/0032-Make-grub2-mkconfig-construct-titles-that-look-like-.patch b/SOURCES/0032-Make-grub2-mkconfig-construct-titles-that-look-like-.patch new file mode 100644 index 0000000..db101c0 --- /dev/null +++ b/SOURCES/0032-Make-grub2-mkconfig-construct-titles-that-look-like-.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 28 Apr 2015 11:15:03 -0400 +Subject: [PATCH] Make grub2-mkconfig construct titles that look like the ones + we want elsewhere. + +Resolves: rhbz#1215839 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 5f6d3c8d52..786dbabb4a 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -78,6 +78,32 @@ case x"$GRUB_FS" in + ;; + esac + ++mktitle () ++{ ++ local title_type ++ local version ++ local OS_NAME ++ local OS_VERS ++ ++ title_type=$1 && shift ++ version=$1 && shift ++ ++ OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})" ++ OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})" ++ ++ case $title_type in ++ recovery) ++ title=$(printf '%s (%s) %s (recovery mode)' \ ++ "${OS_NAME}" "${version}" "${OS_VERS}") ++ ;; ++ *) ++ title=$(printf '%s (%s) %s' \ ++ "${OS_NAME}" "${version}" "${OS_VERS}") ++ ;; ++ esac ++ echo -n ${title} ++} ++ + title_correction_code= + + linux_entry () +@@ -91,17 +117,11 @@ linux_entry () + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" + fi + if [ x$type != xsimple ] ; then +- case $type in +- recovery) +- title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;; +- *) +- title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;; +- esac ++ title=$(mktitle "$type" "$version") + if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then + replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')" + quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)" + title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" +- grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")" + fi + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + else diff --git a/SOURCES/0033-Add-friendly-grub2-password-config-tool-985962.patch b/SOURCES/0033-Add-friendly-grub2-password-config-tool-985962.patch new file mode 100644 index 0000000..f430e96 --- /dev/null +++ b/SOURCES/0033-Add-friendly-grub2-password-config-tool-985962.patch @@ -0,0 +1,245 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Thu, 25 Jun 2015 11:13:11 -0400 +Subject: [PATCH] Add friendly grub2 password config tool (#985962) + +Provided a tool for users to reset the grub2 root user password +without having to alter the grub.cfg. The hashed password now +lives in a root-only-readable configuration file. + +Resolves: rhbz#985962 + +Signed-off-by: Robert Marshall +[pjones: fix the efidir in grub-setpassword and rename tool] +Signed-off-by: Peter Jones +[luto: fix grub-setpassword -o's output path] +Signed-off-by: Andy Lutomirski +[rharwood: migrate man page to h2m, context] +Signed-off-by: Robbie Harwood +--- + configure.ac | 1 + + Makefile.util.def | 13 +++++ + docs/man/grub-set-password.h2m | 2 + + util/grub-mkconfig.in | 2 + + util/grub-set-password.in | 128 +++++++++++++++++++++++++++++++++++++++++ + util/grub.d/01_users.in | 11 ++++ + 6 files changed, 157 insertions(+) + create mode 100644 docs/man/grub-set-password.h2m + create mode 100644 util/grub-set-password.in + create mode 100644 util/grub.d/01_users.in + +diff --git a/configure.ac b/configure.ac +index 8331f95b64..7f59ad788f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -72,6 +72,7 @@ grub_TRANSFORM([grub-mkrelpath]) + grub_TRANSFORM([grub-mkrescue]) + grub_TRANSFORM([grub-probe]) + grub_TRANSFORM([grub-reboot]) ++grub_TRANSFORM([grub-set-password]) + grub_TRANSFORM([grub-script-check]) + grub_TRANSFORM([grub-set-default]) + grub_TRANSFORM([grub-sparc64-setup]) +diff --git a/Makefile.util.def b/Makefile.util.def +index 2c9b283a23..4ee22c5daa 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -452,6 +452,12 @@ script = { + installdir = grubconf; + }; + ++script = { ++ name = '01_users'; ++ common = util/grub.d/01_users.in; ++ installdir = grubconf; ++}; ++ + script = { + name = '10_windows'; + common = util/grub.d/10_windows.in; +@@ -724,6 +730,13 @@ script = { + installdir = sbin; + }; + ++script = { ++ name = grub-set-password; ++ common = util/grub-set-password.in; ++ mansection = 8; ++ installdir = sbin; ++}; ++ + script = { + name = grub-mkconfig_lib; + common = util/grub-mkconfig_lib.in; +diff --git a/docs/man/grub-set-password.h2m b/docs/man/grub-set-password.h2m +new file mode 100644 +index 0000000000..10ee82f4d5 +--- /dev/null ++++ b/docs/man/grub-set-password.h2m +@@ -0,0 +1,2 @@ ++[NAME] ++grub-set-password \- generate the user.cfg file containing the hashed grub bootloader password +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index 8ea2315ebc..ba14cf6261 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -276,6 +276,8 @@ for i in "${grub_mkconfig_dir}"/* ; do + *~) ;; + # emacsen autosave files. FIXME: support other editors + */\#*\#) ;; ++ # rpm config files of yore. ++ *.rpmsave|*.rpmnew|*.rpmorig) ;; + *) + if grub_file_is_not_garbage "$i" && test -x "$i" ; then + echo +diff --git a/util/grub-set-password.in b/util/grub-set-password.in +new file mode 100644 +index 0000000000..5ebf50576d +--- /dev/null ++++ b/util/grub-set-password.in +@@ -0,0 +1,128 @@ ++#!/bin/sh -e ++ ++EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/') ++if [ -d /sys/firmware/efi/efivars/ ]; then ++ grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` ++else ++ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` ++fi ++ ++PACKAGE_VERSION="@PACKAGE_VERSION@" ++PACKAGE_NAME="@PACKAGE_NAME@" ++self=`basename $0` ++bindir="@bindir@" ++grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@" ++ ++# Usage: usage ++# Print the usage. ++usage () { ++ cat < put user.cfg in a user-selected directory ++ ++Report bugs at https://bugzilla.redhat.com. ++EOF ++} ++ ++argument () { ++ opt=$1 ++ shift ++ ++ if test $# -eq 0; then ++ gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2 ++ exit 1 ++ fi ++ echo $1 ++} ++ ++# Ensure that it's the root user running this script ++if [ "${EUID}" -ne 0 ]; then ++ echo "The grub bootloader password may only be set by root." ++ usage ++ exit 2 ++fi ++ ++# Check the arguments. ++while test $# -gt 0 ++do ++ option=$1 ++ shift ++ ++ case "$option" in ++ -h | --help) ++ usage ++ exit 0 ;; ++ -v | --version) ++ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" ++ exit 0 ;; ++ -o | --output) ++ OUTPUT_PATH=`argument $option "$@"`; shift ;; ++ --output=*) ++ OUTPUT_PATH=`echo "$option" | sed 's/--output=//'` ;; ++ -o=*) ++ OUTPUT_PATH=`echo "$option" | sed 's/-o=//'` ;; ++ esac ++done ++ ++# set user input or default path for user.cfg file ++if [ -z "${OUTPUT_PATH}" ]; then ++ OUTPUT_PATH="${grubdir}" ++fi ++ ++if [ ! -d "${OUTPUT_PATH}" ]; then ++ echo "${OUTPUT_PATH} does not exist." ++ usage ++ exit 2; ++fi ++ ++ttyopt=$(stty -g) ++fixtty() { ++ stty ${ttyopt} ++} ++ ++trap fixtty EXIT ++stty -echo ++ ++# prompt & confirm new grub2 root user password ++echo -n "Enter password: " ++read PASSWORD ++echo ++echo -n "Confirm password: " ++read PASSWORD_CONFIRM ++echo ++stty ${ttyopt} ++ ++getpass() { ++ local P0 ++ local P1 ++ P0="$1" && shift ++ P1="$1" && shift ++ ++ ( echo ${P0} ; echo ${P1} ) | \ ++ LC_ALL=C ${grub_mkpasswd} | \ ++ grep -v '[eE]nter password:' | \ ++ sed -e "s/PBKDF2 hash of your password is //" ++} ++ ++MYPASS="$(getpass "${PASSWORD}" "${PASSWORD_CONFIRM}")" ++if [ -z "${MYPASS}" ]; then ++ echo "${self}: error: empty password" 1>&2 ++ exit 1 ++fi ++ ++# on the ESP, these will fail to set the permissions, but it's okay because ++# the directory is protected. ++install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : ++chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : ++echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" ++ ++if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${OUTPUT_PATH}/grub.cfg"; then ++ echo "WARNING: The current configuration lacks password support!" ++ echo "Update your configuration with @grub_mkconfig@ to support this feature." ++fi +diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in +new file mode 100644 +index 0000000000..db2f44bfb7 +--- /dev/null ++++ b/util/grub.d/01_users.in +@@ -0,0 +1,11 @@ ++#!/bin/sh -e ++cat << EOF ++if [ -f \${prefix}/user.cfg ]; then ++ source \${prefix}/user.cfg ++ if [ -n "\${GRUB2_PASSWORD}" ]; then ++ set superusers="root" ++ export superusers ++ password_pbkdf2 root \${GRUB2_PASSWORD} ++ fi ++fi ++EOF diff --git a/SOURCES/0033-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch b/SOURCES/0033-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch deleted file mode 100644 index 7e9e829..0000000 --- a/SOURCES/0033-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 28 Oct 2013 10:13:27 -0400 -Subject: [PATCH] F10 doesn't work on serial, so don't tell the user to hit it - (#987443) - -Signed-off-by: Peter Jones ---- - grub-core/normal/menu_text.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index 26e9e82042a..4895ffe7d1d 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -157,7 +157,7 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run) - - if (edit) - { -- ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \ -+ ret += grub_print_message_indented_real (_("Press Ctrl-x to start, Ctrl-c for a \ - command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."), - STANDARD_MARGIN, STANDARD_MARGIN, - term, dry_run); diff --git a/SOURCES/0034-Don-t-say-GNU-Linux-in-generated-menus.patch b/SOURCES/0034-Don-t-say-GNU-Linux-in-generated-menus.patch deleted file mode 100644 index db2a8b5..0000000 --- a/SOURCES/0034-Don-t-say-GNU-Linux-in-generated-menus.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 14 Mar 2011 14:27:42 -0400 -Subject: [PATCH] Don't say "GNU/Linux" in generated menus. - ---- - util/grub.d/10_linux.in | 4 ++-- - util/grub.d/20_linux_xen.in | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index ad2ac4b078d..4fc58c83304 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@" - CLASS="--class gnu-linux --class gnu --class os" - - if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then -- OS=GNU/Linux -+ OS="$(sed 's, release .*$,,g' /etc/system-release)" - else -- OS="${GRUB_DISTRIBUTOR} GNU/Linux" -+ OS="${GRUB_DISTRIBUTOR}" - CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" - fi - -diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in -index 3b1f4704921..ada20775a14 100644 ---- a/util/grub.d/20_linux_xen.in -+++ b/util/grub.d/20_linux_xen.in -@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@" - CLASS="--class gnu-linux --class gnu --class os --class xen" - - if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then -- OS=GNU/Linux -+ OS="$(sed 's, release .*$,,g' /etc/system-release)" - else -- OS="${GRUB_DISTRIBUTOR} GNU/Linux" -+ OS="${GRUB_DISTRIBUTOR}" - CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" - fi - diff --git a/SOURCES/0034-tcp-add-window-scaling-support.patch b/SOURCES/0034-tcp-add-window-scaling-support.patch new file mode 100644 index 0000000..61b5a67 --- /dev/null +++ b/SOURCES/0034-tcp-add-window-scaling-support.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Wed, 12 Aug 2015 08:57:55 -0700 +Subject: [PATCH] tcp: add window scaling support + +Sometimes we have to provision boxes across regions, such as California to +Sweden. The http server has a 10 minute timeout, so if we can't get our 250mb +image transferred fast enough our provisioning fails, which is not ideal. So +add tcp window scaling on open connections and set the window size to 1mb. With +this change we're able to get higher sustained transfers between regions and can +transfer our image in well below 10 minutes. Without this patch we'd time out +every time halfway through the transfer. Thanks, + +Signed-off-by: Josef Bacik +--- + grub-core/net/tcp.c | 42 +++++++++++++++++++++++++++++------------- + 1 file changed, 29 insertions(+), 13 deletions(-) + +diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c +index e8ad34b84d..7d4b822626 100644 +--- a/grub-core/net/tcp.c ++++ b/grub-core/net/tcp.c +@@ -106,6 +106,18 @@ struct tcphdr + grub_uint16_t urgent; + } GRUB_PACKED; + ++struct tcp_scale_opt { ++ grub_uint8_t kind; ++ grub_uint8_t length; ++ grub_uint8_t scale; ++} GRUB_PACKED; ++ ++struct tcp_synhdr { ++ struct tcphdr tcphdr; ++ struct tcp_scale_opt scale_opt; ++ grub_uint8_t padding; ++}; ++ + struct tcp_pseudohdr + { + grub_uint32_t src; +@@ -566,7 +578,7 @@ grub_net_tcp_open (char *server, + grub_net_tcp_socket_t socket; + static grub_uint16_t in_port = 21550; + struct grub_net_buff *nb; +- struct tcphdr *tcph; ++ struct tcp_synhdr *tcph; + int i; + grub_uint8_t *nbd; + grub_net_link_level_address_t ll_target_addr; +@@ -635,20 +647,24 @@ grub_net_tcp_open (char *server, + } + + tcph = (void *) nb->data; ++ grub_memset(tcph, 0, sizeof (*tcph)); + socket->my_start_seq = grub_get_time_ms (); + socket->my_cur_seq = socket->my_start_seq + 1; +- socket->my_window = 8192; +- tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq); +- tcph->ack = grub_cpu_to_be32_compile_time (0); +- tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN); +- tcph->window = grub_cpu_to_be16 (socket->my_window); +- tcph->urgent = 0; +- tcph->src = grub_cpu_to_be16 (socket->in_port); +- tcph->dst = grub_cpu_to_be16 (socket->out_port); +- tcph->checksum = 0; +- tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, +- &socket->inf->address, +- &socket->out_nla); ++ socket->my_window = 32768; ++ tcph->tcphdr.seqnr = grub_cpu_to_be32 (socket->my_start_seq); ++ tcph->tcphdr.ack = grub_cpu_to_be32_compile_time (0); ++ tcph->tcphdr.flags = grub_cpu_to_be16_compile_time ((6 << 12) | TCP_SYN); ++ tcph->tcphdr.window = grub_cpu_to_be16 (socket->my_window); ++ tcph->tcphdr.urgent = 0; ++ tcph->tcphdr.src = grub_cpu_to_be16 (socket->in_port); ++ tcph->tcphdr.dst = grub_cpu_to_be16 (socket->out_port); ++ tcph->tcphdr.checksum = 0; ++ tcph->scale_opt.kind = 3; ++ tcph->scale_opt.length = 3; ++ tcph->scale_opt.scale = 5; ++ tcph->tcphdr.checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, ++ &socket->inf->address, ++ &socket->out_nla); + + tcp_socket_register (socket); + diff --git a/SOURCES/0035-Don-t-draw-a-border-around-the-menu.patch b/SOURCES/0035-Don-t-draw-a-border-around-the-menu.patch deleted file mode 100644 index 31a973e..0000000 --- a/SOURCES/0035-Don-t-draw-a-border-around-the-menu.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Wed, 15 May 2013 16:47:33 -0400 -Subject: [PATCH] Don't draw a border around the menu - -It looks cleaner without it. ---- - grub-core/normal/menu_text.c | 43 ------------------------------------------- - 1 file changed, 43 deletions(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index 4895ffe7d1d..e72ed438ba3 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -108,47 +108,6 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right, - grub_print_message_indented_real (msg, margin_left, margin_right, term, 0); - } - --static void --draw_border (struct grub_term_output *term, const struct grub_term_screen_geometry *geo) --{ -- int i; -- -- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); -- -- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1, -- geo->first_entry_y - 1 }); -- grub_putcode (GRUB_UNICODE_CORNER_UL, term); -- for (i = 0; i < geo->entry_width + 1; i++) -- grub_putcode (GRUB_UNICODE_HLINE, term); -- grub_putcode (GRUB_UNICODE_CORNER_UR, term); -- -- for (i = 0; i < geo->num_entries; i++) -- { -- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1, -- geo->first_entry_y + i }); -- grub_putcode (GRUB_UNICODE_VLINE, term); -- grub_term_gotoxy (term, -- (struct grub_term_coordinate) { geo->first_entry_x + geo->entry_width + 1, -- geo->first_entry_y + i }); -- grub_putcode (GRUB_UNICODE_VLINE, term); -- } -- -- grub_term_gotoxy (term, -- (struct grub_term_coordinate) { geo->first_entry_x - 1, -- geo->first_entry_y - 1 + geo->num_entries + 1 }); -- grub_putcode (GRUB_UNICODE_CORNER_LL, term); -- for (i = 0; i < geo->entry_width + 1; i++) -- grub_putcode (GRUB_UNICODE_HLINE, term); -- grub_putcode (GRUB_UNICODE_CORNER_LR, term); -- -- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); -- -- grub_term_gotoxy (term, -- (struct grub_term_coordinate) { geo->first_entry_x - 1, -- (geo->first_entry_y - 1 + geo->num_entries -- + GRUB_TERM_MARGIN + 1) }); --} -- - static int - print_message (int nested, int edit, struct grub_term_output *term, int dry_run) - { -@@ -406,8 +365,6 @@ grub_menu_init_page (int nested, int edit, - - grub_term_normal_color = grub_color_menu_normal; - grub_term_highlight_color = grub_color_menu_highlight; -- if (geo->border) -- draw_border (term, geo); - grub_term_normal_color = old_color_normal; - grub_term_highlight_color = old_color_highlight; - geo->timeout_y = geo->first_entry_y + geo->num_entries diff --git a/SOURCES/0035-efinet-and-bootp-add-support-for-dhcpv6.patch b/SOURCES/0035-efinet-and-bootp-add-support-for-dhcpv6.patch new file mode 100644 index 0000000..efeeee0 --- /dev/null +++ b/SOURCES/0035-efinet-and-bootp-add-support-for-dhcpv6.patch @@ -0,0 +1,651 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 9 Jul 2019 11:47:37 +0200 +Subject: [PATCH] efinet and bootp: add support for dhcpv6 + +Signed-off-by: Peter Jones +--- + grub-core/net/bootp.c | 173 +++++++++++++++++++++++++++++++++++++ + grub-core/net/drivers/efi/efinet.c | 53 ++++++++++-- + grub-core/net/net.c | 72 +++++++++++++++ + grub-core/net/tftp.c | 4 + + include/grub/efi/api.h | 129 +++++++++++++++++++++++++-- + include/grub/net.h | 60 +++++++++++++ + 6 files changed, 477 insertions(+), 14 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 6fb5627025..e28fb6a09f 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -902,6 +902,179 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + + static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp; + ++struct grub_net_network_level_interface * ++grub_net_configure_by_dhcpv6_ack (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags ++ __attribute__((__unused__)), ++ const grub_net_link_level_address_t *hwaddr, ++ const struct grub_net_dhcpv6_packet *packet, ++ int is_def, char **device, char **path) ++{ ++ struct grub_net_network_level_interface *inter = NULL; ++ struct grub_net_network_level_address addr; ++ int mask = -1; ++ ++ if (!device || !path) ++ return NULL; ++ ++ *device = 0; ++ *path = 0; ++ ++ grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n", ++ hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2], ++ hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]); ++ ++ if (is_def) ++ grub_net_default_server = 0; ++ ++ if (is_def && !grub_net_default_server && packet) ++ { ++ const grub_uint8_t *options = packet->dhcp_options; ++ unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet); ++ unsigned int i; ++ ++ for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); ) ++ { ++ grub_uint16_t num, len; ++ grub_net_dhcpv6_option_t *opt = ++ (grub_net_dhcpv6_option_t *)(options + i); ++ ++ num = grub_be_to_cpu16(opt->option_num); ++ len = grub_be_to_cpu16(opt->option_len); ++ ++ grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len); ++ ++ if (len == 0) ++ break; ++ ++ if (len + i > 1024) ++ break; ++ ++ if (num == GRUB_NET_DHCP6_BOOTFILE_URL) ++ { ++ char *scheme, *userinfo, *host, *file; ++ char *tmp; ++ int hostlen; ++ int port; ++ int rc = extract_url_info ((const char *)opt->option_data, ++ (grub_size_t)len, ++ &scheme, &userinfo, &host, &port, ++ &file); ++ if (rc < 0) ++ continue; ++ ++ /* right now this only handles tftp. */ ++ if (grub_strcmp("tftp", scheme)) ++ { ++ grub_free (scheme); ++ grub_free (userinfo); ++ grub_free (host); ++ grub_free (file); ++ continue; ++ } ++ grub_free (userinfo); ++ ++ hostlen = grub_strlen (host); ++ if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']') ++ { ++ tmp = host+1; ++ host[hostlen-1] = '\0'; ++ } ++ else ++ tmp = host; ++ ++ *device = grub_xasprintf ("%s,%s", scheme, tmp); ++ grub_free (scheme); ++ grub_free (host); ++ ++ if (file && *file) ++ { ++ tmp = grub_strrchr (file, '/'); ++ if (tmp) ++ *(tmp+1) = '\0'; ++ else ++ file[0] = '\0'; ++ } ++ else if (!file) ++ file = grub_strdup (""); ++ ++ if (file[0] == '/') ++ { ++ *path = grub_strdup (file+1); ++ grub_free (file); ++ } ++ else ++ *path = file; ++ } ++ else if (num == GRUB_NET_DHCP6_IA_NA) ++ { ++ const grub_net_dhcpv6_option_t *ia_na_opt; ++ const grub_net_dhcpv6_opt_ia_na_t *ia_na = ++ (const grub_net_dhcpv6_opt_ia_na_t *)opt; ++ unsigned int left = len - OFFSET_OF (options, ia_na); ++ unsigned int j; ++ ++ if ((grub_uint8_t *)ia_na + left > ++ (grub_uint8_t *)options + option_max) ++ left -= ((grub_uint8_t *)ia_na + left) ++ - ((grub_uint8_t *)options + option_max); ++ ++ if (len < OFFSET_OF (option_data, opt) ++ + sizeof (grub_net_dhcpv6_option_t)) ++ { ++ grub_dprintf ("net", ++ "found dhcpv6 ia_na option with no address\n"); ++ continue; ++ } ++ ++ for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); ) ++ { ++ ia_na_opt = (const grub_net_dhcpv6_option_t *) ++ (ia_na->options + j); ++ grub_uint16_t ia_na_opt_num, ia_na_opt_len; ++ ++ ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num); ++ ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len); ++ if (ia_na_opt_len == 0) ++ break; ++ if (j + ia_na_opt_len > left) ++ break; ++ if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS) ++ { ++ const grub_net_dhcpv6_opt_ia_address_t *ia_addr; ++ ++ ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *) ++ ia_na_opt; ++ addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ grub_memcpy(addr.ipv6, ia_addr->ipv6_address, ++ sizeof (ia_addr->ipv6_address)); ++ inter = grub_net_add_addr (name, card, &addr, hwaddr, 0); ++ } ++ ++ j += ia_na_opt_len; ++ left -= ia_na_opt_len; ++ } ++ } ++ ++ i += len + 4; ++ } ++ ++ grub_print_error (); ++ } ++ ++ if (is_def) ++ { ++ grub_env_set ("net_default_interface", name); ++ grub_env_export ("net_default_interface"); ++ } ++ ++ if (inter) ++ grub_net_add_ipv6_local (inter, mask); ++ return inter; ++} ++ ++ + void + grub_bootp_init (void) + { +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 5388f952ba..173fb63153 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -18,11 +18,14 @@ + + #include + #include ++#include + #include + #include + #include + #include + #include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -329,7 +332,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + char **path) + { + struct grub_net_card *card; +- grub_efi_device_path_t *dp; ++ grub_efi_device_path_t *dp, *ldp = NULL; + + dp = grub_efi_get_device_path (hnd); + if (! dp) +@@ -340,14 +343,19 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + grub_efi_device_path_t *cdp; + struct grub_efi_pxe *pxe; + struct grub_efi_pxe_mode *pxe_mode; ++ + if (card->driver != &efidriver) + continue; ++ + cdp = grub_efi_get_device_path (card->efi_handle); + if (! cdp) + continue; ++ ++ ldp = grub_efi_find_last_device_path (dp); ++ + if (grub_efi_compare_device_paths (dp, cdp) != 0) + { +- grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp; ++ grub_efi_device_path_t *dup_dp, *dup_ldp; + int match; + + /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6 +@@ -356,7 +364,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + devices. We skip them when enumerating cards, so here we need to + find matching MAC device. + */ +- ldp = grub_efi_find_last_device_path (dp); + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) +@@ -373,16 +380,46 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (!match) + continue; + } ++ + pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (! pxe) + continue; ++ + pxe_mode = pxe->mode; +- grub_net_configure_by_dhcp_ack (card->name, card, 0, +- (struct grub_net_bootp_packet *) +- &pxe_mode->dhcp_ack, +- sizeof (pxe_mode->dhcp_ack), +- 1, device, path); ++ if (pxe_mode->using_ipv6) ++ { ++ grub_net_link_level_address_t hwaddr; ++ struct grub_net_network_level_interface *intf; ++ ++ grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); ++ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", ++ pxe_mode->dhcp_ack_received ? "yes" : "no", ++ pxe_mode->dhcp_ack_received ? "" : " cannot continue"); ++ if (!pxe_mode->dhcp_ack_received) ++ continue; ++ ++ hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ grub_memcpy (hwaddr.mac, ++ card->efi_net->mode->current_address, ++ sizeof (hwaddr.mac)); ++ ++ intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr, ++ (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6, ++ 1, device, path); ++ if (intf && device && path) ++ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); ++ } ++ else ++ { ++ grub_dprintf ("efinet", "using ipv4 and dhcp\n"); ++ grub_net_configure_by_dhcp_ack (card->name, card, 0, ++ (struct grub_net_bootp_packet *) ++ &pxe_mode->dhcp_ack, ++ sizeof (pxe_mode->dhcp_ack), ++ 1, device, path); ++ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); ++ } + return; + } + } +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 0ef148f4ad..22f2689aae 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -960,6 +960,78 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa + grub_net_network_level_interfaces = inter; + } + ++int ++grub_ipv6_get_masksize (grub_uint16_t be_mask[8]) ++{ ++ grub_uint8_t *mask; ++ grub_uint16_t mask16[8]; ++ int x, y; ++ int ret = 128; ++ ++ grub_memcpy (mask16, be_mask, sizeof (mask16)); ++ for (x = 0; x < 8; x++) ++ mask16[x] = grub_be_to_cpu16 (mask16[x]); ++ ++ mask = (grub_uint8_t *)mask16; ++ ++ for (x = 15; x >= 0; x--) ++ { ++ grub_uint8_t octet = mask[x]; ++ if (!octet) ++ { ++ ret -= 8; ++ continue; ++ } ++ for (y = 0; y < 8; y++) ++ { ++ if (octet & (1 << y)) ++ break; ++ else ++ ret--; ++ } ++ break; ++ } ++ ++ return ret; ++} ++ ++grub_err_t ++grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter, ++ int mask) ++{ ++ struct grub_net_route *route; ++ ++ if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) ++ return 0; ++ ++ if (mask == -1) ++ mask = grub_ipv6_get_masksize ((grub_uint16_t *)inter->address.ipv6); ++ ++ if (mask == -1) ++ return 0; ++ ++ route = grub_zalloc (sizeof (*route)); ++ if (!route) ++ return grub_errno; ++ ++ route->name = grub_xasprintf ("%s:local", inter->name); ++ if (!route->name) ++ { ++ grub_free (route); ++ return grub_errno; ++ } ++ ++ route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ grub_memcpy (route->target.ipv6.base, inter->address.ipv6, ++ sizeof (inter->address.ipv6)); ++ route->target.ipv6.masksize = mask; ++ route->is_gateway = 0; ++ route->interface = inter; ++ ++ grub_net_route_register (route); ++ ++ return 0; ++} + + grub_err_t + grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter, +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 7f44b30f52..4ab2f5c735 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -358,18 +358,22 @@ tftp_open (struct grub_file *file, const char *filename) + file->not_easily_seekable = 1; + file->data = data; + ++ grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server); + err = grub_net_resolve_address (file->device->net->server, &addr); + if (err) + { ++ grub_dprintf("tftp", "Address resolution failed: %d\n", err); + grub_free (data); + return err; + } + ++ grub_dprintf("tftp", "opening connection\n"); + data->sock = grub_net_udp_open (addr, + TFTP_SERVER_PORT, tftp_receive, + file); + if (!data->sock) + { ++ grub_dprintf("tftp", "connection failed\n"); + grub_free (data); + return grub_errno; + } +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index f1a52210c0..117469450d 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -592,10 +592,16 @@ typedef void *grub_efi_handle_t; + typedef void *grub_efi_event_t; + typedef grub_efi_uint64_t grub_efi_lba_t; + typedef grub_efi_uintn_t grub_efi_tpl_t; +-typedef grub_uint8_t grub_efi_mac_address_t[32]; +-typedef grub_uint8_t grub_efi_ipv4_address_t[4]; +-typedef grub_uint16_t grub_efi_ipv6_address_t[8]; +-typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4))); ++typedef grub_efi_uint8_t grub_efi_mac_address_t[32]; ++typedef grub_efi_uint8_t grub_efi_ipv4_address_t[4]; ++typedef grub_efi_uint8_t grub_efi_ipv6_address_t[16]; ++typedef union ++{ ++ grub_efi_uint32_t addr[4]; ++ grub_efi_ipv4_address_t v4; ++ grub_efi_ipv6_address_t v6; ++} grub_efi_ip_address_t __attribute__ ((aligned(4))); ++ + typedef grub_efi_uint64_t grub_efi_physical_address_t; + typedef grub_efi_uint64_t grub_efi_virtual_address_t; + +@@ -1474,16 +1480,127 @@ struct grub_efi_simple_text_output_interface + }; + typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t; + +-typedef grub_uint8_t grub_efi_pxe_packet_t[1472]; ++typedef struct grub_efi_pxe_dhcpv4_packet ++{ ++ grub_efi_uint8_t bootp_opcode; ++ grub_efi_uint8_t bootp_hwtype; ++ grub_efi_uint8_t bootp_hwaddr_len; ++ grub_efi_uint8_t bootp_gate_hops; ++ grub_efi_uint32_t bootp_ident; ++ grub_efi_uint16_t bootp_seconds; ++ grub_efi_uint16_t bootp_flags; ++ grub_efi_uint8_t bootp_ci_addr[4]; ++ grub_efi_uint8_t bootp_yi_addr[4]; ++ grub_efi_uint8_t bootp_si_addr[4]; ++ grub_efi_uint8_t bootp_gi_addr[4]; ++ grub_efi_uint8_t bootp_hw_addr[16]; ++ grub_efi_uint8_t bootp_srv_name[64]; ++ grub_efi_uint8_t bootp_boot_file[128]; ++ grub_efi_uint32_t dhcp_magik; ++ grub_efi_uint8_t dhcp_options[56]; ++} grub_efi_pxe_dhcpv4_packet_t; ++ ++struct grub_efi_pxe_dhcpv6_packet ++{ ++ grub_efi_uint32_t message_type:8; ++ grub_efi_uint32_t transaction_id:24; ++ grub_efi_uint8_t dhcp_options[1024]; ++} GRUB_PACKED; ++typedef struct grub_efi_pxe_dhcpv6_packet grub_efi_pxe_dhcpv6_packet_t; ++ ++typedef union ++{ ++ grub_efi_uint8_t raw[1472]; ++ grub_efi_pxe_dhcpv4_packet_t dhcpv4; ++ grub_efi_pxe_dhcpv6_packet_t dhcpv6; ++} grub_efi_pxe_packet_t; ++ ++#define GRUB_EFI_PXE_MAX_IPCNT 8 ++#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8 ++#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8 ++ ++typedef struct grub_efi_pxe_ip_filter ++{ ++ grub_efi_uint8_t filters; ++ grub_efi_uint8_t ip_count; ++ grub_efi_uint8_t reserved; ++ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; ++} grub_efi_pxe_ip_filter_t; ++ ++typedef struct grub_efi_pxe_arp_entry ++{ ++ grub_efi_ip_address_t ip_addr; ++ grub_efi_mac_address_t mac_addr; ++} grub_efi_pxe_arp_entry_t; ++ ++typedef struct grub_efi_pxe_route_entry ++{ ++ grub_efi_ip_address_t ip_addr; ++ grub_efi_ip_address_t subnet_mask; ++ grub_efi_ip_address_t gateway_addr; ++} grub_efi_pxe_route_entry_t; ++ ++typedef struct grub_efi_pxe_icmp_error ++{ ++ grub_efi_uint8_t type; ++ grub_efi_uint8_t code; ++ grub_efi_uint16_t checksum; ++ union ++ { ++ grub_efi_uint32_t reserved; ++ grub_efi_uint32_t mtu; ++ grub_efi_uint32_t pointer; ++ struct ++ { ++ grub_efi_uint16_t identifier; ++ grub_efi_uint16_t sequence; ++ } echo; ++ } u; ++ grub_efi_uint8_t data[494]; ++} grub_efi_pxe_icmp_error_t; ++ ++typedef struct grub_efi_pxe_tftp_error ++{ ++ grub_efi_uint8_t error_code; ++ grub_efi_char8_t error_string[127]; ++} grub_efi_pxe_tftp_error_t; + + typedef struct grub_efi_pxe_mode + { +- grub_uint8_t unused[52]; ++ grub_efi_boolean_t started; ++ grub_efi_boolean_t ipv6_available; ++ grub_efi_boolean_t ipv6_supported; ++ grub_efi_boolean_t using_ipv6; ++ grub_efi_boolean_t bis_supported; ++ grub_efi_boolean_t bis_detected; ++ grub_efi_boolean_t auto_arp; ++ grub_efi_boolean_t send_guid; ++ grub_efi_boolean_t dhcp_discover_valid; ++ grub_efi_boolean_t dhcp_ack_received; ++ grub_efi_boolean_t proxy_offer_received; ++ grub_efi_boolean_t pxe_discover_valid; ++ grub_efi_boolean_t pxe_reply_received; ++ grub_efi_boolean_t pxe_bis_reply_received; ++ grub_efi_boolean_t icmp_error_received; ++ grub_efi_boolean_t tftp_error_received; ++ grub_efi_boolean_t make_callbacks; ++ grub_efi_uint8_t ttl; ++ grub_efi_uint8_t tos; ++ grub_efi_ip_address_t station_ip; ++ grub_efi_ip_address_t subnet_mask; + grub_efi_pxe_packet_t dhcp_discover; + grub_efi_pxe_packet_t dhcp_ack; + grub_efi_pxe_packet_t proxy_offer; + grub_efi_pxe_packet_t pxe_discover; + grub_efi_pxe_packet_t pxe_reply; ++ grub_efi_pxe_packet_t pxe_bis_reply; ++ grub_efi_pxe_ip_filter_t ip_filter; ++ grub_efi_uint32_t arp_cache_entries; ++ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES]; ++ grub_efi_uint32_t route_table_entries; ++ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES]; ++ grub_efi_pxe_icmp_error_t icmp_error; ++ grub_efi_pxe_tftp_error_t tftp_error; + } grub_efi_pxe_mode_t; + + typedef struct grub_efi_pxe +diff --git a/include/grub/net.h b/include/grub/net.h +index 7ae4b6bd80..8a05ec4fe7 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -447,6 +447,51 @@ struct grub_net_bootp_packet + grub_uint8_t vendor[0]; + } GRUB_PACKED; + ++enum ++ { ++ GRUB_NET_DHCP6_IA_NA = 3, ++ GRUB_NET_DHCP6_IA_ADDRESS = 5, ++ GRUB_NET_DHCP6_BOOTFILE_URL = 59, ++ }; ++ ++struct grub_net_dhcpv6_option ++{ ++ grub_uint16_t option_num; ++ grub_uint16_t option_len; ++ grub_uint8_t option_data[]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t; ++ ++struct grub_net_dhcpv6_opt_ia_na ++{ ++ grub_uint16_t option_num; ++ grub_uint16_t option_len; ++ grub_uint32_t iaid; ++ grub_uint32_t t1; ++ grub_uint32_t t2; ++ grub_uint8_t options[]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t; ++ ++struct grub_net_dhcpv6_opt_ia_address ++{ ++ grub_uint16_t option_num; ++ grub_uint16_t option_len; ++ grub_uint64_t ipv6_address[2]; ++ grub_uint32_t preferred_lifetime; ++ grub_uint32_t valid_lifetime; ++ grub_uint8_t options[]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t; ++ ++struct grub_net_dhcpv6_packet ++{ ++ grub_uint32_t message_type:8; ++ grub_uint32_t transaction_id:24; ++ grub_uint8_t dhcp_options[1024]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t; ++ + #define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 + #define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 + #define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 +@@ -482,6 +527,21 @@ grub_net_configure_by_dhcp_ack (const char *name, + grub_size_t size, + int is_def, char **device, char **path); + ++struct grub_net_network_level_interface * ++grub_net_configure_by_dhcpv6_ack (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags, ++ const grub_net_link_level_address_t *hwaddr, ++ const struct grub_net_dhcpv6_packet *packet, ++ int is_def, char **device, char **path); ++ ++int ++grub_ipv6_get_masksize(grub_uint16_t *mask); ++ ++grub_err_t ++grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf, ++ int mask); ++ + grub_err_t + grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf, + int mask); diff --git a/SOURCES/0036-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch b/SOURCES/0036-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch new file mode 100644 index 0000000..95490cd --- /dev/null +++ b/SOURCES/0036-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch @@ -0,0 +1,271 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jun 2016 11:01:39 -0400 +Subject: [PATCH] Add grub-get-kernel-settings and use it in 10_linux + +This patch adds grub-get-kernel-settings, which reads the system kernel +installation configuration from /etc/sysconfig/kernel, and outputs +${GRUB_...} variables suitable for evaluation by grub-mkconfig. Those +variables are then used by 10_linux to choose whether or not to create +debug stanzas. + +Resolves: rhbz#1226325 +[rharwood: migrate man page to h2m] +--- + configure.ac | 1 + + Makefile.util.def | 7 ++ + docs/man/grub-get-kernel-settings.h2m | 2 + + util/bash-completion.d/grub-completion.bash.in | 22 +++++++ + util/grub-get-kernel-settings.in | 88 ++++++++++++++++++++++++++ + util/grub-mkconfig.in | 3 + + util/grub.d/10_linux.in | 23 +++++-- + 7 files changed, 141 insertions(+), 5 deletions(-) + create mode 100644 docs/man/grub-get-kernel-settings.h2m + create mode 100644 util/grub-get-kernel-settings.in + +diff --git a/configure.ac b/configure.ac +index 7f59ad788f..0d0e6782a1 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-install]) + grub_TRANSFORM([grub-mkconfig]) + grub_TRANSFORM([grub-mkfont]) + grub_TRANSFORM([grub-mkimage]) ++grub_TRANSFORM([grub-get-kernel-settings]) + grub_TRANSFORM([grub-glue-efi]) + grub_TRANSFORM([grub-mklayout]) + grub_TRANSFORM([grub-mkpasswd-pbkdf2]) +diff --git a/Makefile.util.def b/Makefile.util.def +index 4ee22c5daa..18a9242776 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -716,6 +716,13 @@ script = { + installdir = sbin; + }; + ++script = { ++ name = grub-get-kernel-settings; ++ common = util/grub-get-kernel-settings.in; ++ mansection = 3; ++ installdir = sbin; ++}; ++ + script = { + name = grub-set-default; + common = util/grub-set-default.in; +diff --git a/docs/man/grub-get-kernel-settings.h2m b/docs/man/grub-get-kernel-settings.h2m +new file mode 100644 +index 0000000000..b8051f01f3 +--- /dev/null ++++ b/docs/man/grub-get-kernel-settings.h2m +@@ -0,0 +1,2 @@ ++[NAME] ++grub-get-kernel-settings \- Evaluate the system's kernel installation settings for use while making a grub configuration file +diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in +index 44bf135b9f..5c4acd496d 100644 +--- a/util/bash-completion.d/grub-completion.bash.in ++++ b/util/bash-completion.d/grub-completion.bash.in +@@ -264,6 +264,28 @@ have ${__grub_sparc64_setup_program} && \ + unset __grub_sparc64_setup_program + + ++# ++# grub-get-kernel-settings ++# ++_grub_get_kernel_settings () { ++ local cur ++ ++ COMPREPLY=() ++ cur=`_get_cword` ++ ++ if [[ "$cur" == -* ]]; then ++ __grubcomp "$(__grub_get_options_from_help)" ++ else ++ # Default complete with a filename ++ _filedir ++ fi ++} ++__grub_get_kernel_settings_program="@grub_get_kernel_settings@" ++have ${__grub_get_kernel_settings_program} && \ ++ complete -F _grub_get_kernel_settings -o filenames ${__grub_get_kernel_settings_program} ++unset __grub_get_kernel_settings_program ++ ++ + # + # grub-install + # +diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in +new file mode 100644 +index 0000000000..7e87dfccc0 +--- /dev/null ++++ b/util/grub-get-kernel-settings.in +@@ -0,0 +1,88 @@ ++#!/bin/sh ++set -e ++ ++# Evaluate new-kernel-pkg's configuration file. ++# Copyright (C) 2016 Free Software Foundation, Inc. ++# ++# GRUB is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# GRUB is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with GRUB. If not, see . ++ ++PACKAGE_NAME=@PACKAGE_NAME@ ++PACKAGE_VERSION=@PACKAGE_VERSION@ ++datadir="@datadir@" ++if [ "x$pkgdatadir" = x ]; then ++ pkgdatadir="${datadir}/@PACKAGE@" ++fi ++ ++self=`basename $0` ++ ++export TEXTDOMAIN=@PACKAGE@ ++export TEXTDOMAINDIR="@localedir@" ++ ++. "${pkgdatadir}/grub-mkconfig_lib" ++ ++# Usage: usage ++# Print the usage. ++usage () { ++ gettext_printf "Usage: %s [OPTION]\n" "$self" ++ gettext "Evaluate new-kernel-pkg configuration"; echo ++ echo ++ print_option_help "-h, --help" "$(gettext "print this message and exit")" ++ print_option_help "-v, --version" "$(gettext "print the version information and exit")" ++ echo ++} ++ ++# Check the arguments. ++while test $# -gt 0 ++do ++ option=$1 ++ shift ++ ++ case "$option" in ++ -h | --help) ++ usage ++ exit 0 ;; ++ -v | --version) ++ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" ++ exit 0 ;; ++ -*) ++ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 ++ usage ++ exit 1 ++ ;; ++ # Explicitly ignore non-option arguments, for compatibility. ++ esac ++done ++ ++if test -f /etc/sysconfig/kernel ; then ++ . /etc/sysconfig/kernel ++fi ++ ++if [ "$MAKEDEBUG" = "yes" ]; then ++ echo GRUB_LINUX_MAKE_DEBUG=true ++ echo export GRUB_LINUX_MAKE_DEBUG ++ echo GRUB_CMDLINE_LINUX_DEBUG=\"systemd.log_level=debug systemd.log_target=kmsg\" ++ echo export GRUB_CMDLINE_LINUX_DEBUG ++ echo GRUB_LINUX_DEBUG_TITLE_POSTFIX=\" with debugging\" ++ echo export GRUB_LINUX_DEBUG_TITLE_POSTFIX ++fi ++if [ "$DEFAULTDEBUG" = "yes" ]; then ++ echo GRUB_DEFAULT_TO_DEBUG=true ++else ++ echo GRUB_DEFAULT_TO_DEBUG=false ++fi ++echo export GRUB_DEFAULT_TO_DEBUG ++if [ "$UPDATEDEFAULT" = "yes" ]; then ++ echo GRUB_UPDATE_DEFAULT_KERNEL=true ++ echo export GRUB_UPDATE_DEFAULT_KERNEL ++fi +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index ba14cf6261..005f093809 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -45,6 +45,7 @@ grub_probe="${sbindir}/@grub_probe@" + grub_file="${bindir}/@grub_file@" + grub_editenv="${bindir}/@grub_editenv@" + grub_script_check="${bindir}/@grub_script_check@" ++grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@" + + export TEXTDOMAIN=@PACKAGE@ + export TEXTDOMAINDIR="@localedir@" +@@ -158,6 +159,8 @@ if test -f ${sysconfdir}/default/grub ; then + . ${sysconfdir}/default/grub + fi + ++eval "$("${grub_get_kernel_settings}")" || true ++ + if [ "x${GRUB_DISABLE_UUID}" = "xtrue" ]; then + if [ -z "${GRUB_DISABLE_LINUX_UUID}" ]; then + GRUB_DISABLE_LINUX_UUID="true" +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 786dbabb4a..292e333324 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -111,7 +111,8 @@ linux_entry () + os="$1" + version="$2" + type="$3" +- args="$4" ++ isdebug="$4" ++ args="$5" + + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" +@@ -123,6 +124,9 @@ linux_entry () + quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)" + title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" + fi ++ if [ x$isdebug = xdebug ]; then ++ title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}" ++ fi + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + else + echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" +@@ -306,11 +310,15 @@ while [ "x$list" != "x" ] ; do + fi + + if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then +- linux_entry "${OS}" "${version}" simple \ ++ linux_entry "${OS}" "${version}" simple standard \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then ++ linux_entry "${OS}" "${version}" simple debug \ ++ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}" ++ fi + + submenu_indentation="$grub_tab" +- ++ + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" + fi +@@ -319,10 +327,15 @@ while [ "x$list" != "x" ] ; do + is_top_level=false + fi + +- linux_entry "${OS}" "${version}" advanced \ ++ linux_entry "${OS}" "${version}" advanced standard \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then ++ linux_entry "${OS}" "${version}" advanced debug \ ++ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}" ++ fi ++ + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then +- linux_entry "${OS}" "${version}" recovery \ ++ linux_entry "${OS}" "${version}" recovery standard \ + "single ${GRUB_CMDLINE_LINUX}" + fi + diff --git a/SOURCES/0036-Use-the-standard-margin-for-the-timeout-string.patch b/SOURCES/0036-Use-the-standard-margin-for-the-timeout-string.patch deleted file mode 100644 index 49a382d..0000000 --- a/SOURCES/0036-Use-the-standard-margin-for-the-timeout-string.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Jon McCann -Date: Fri, 7 Jun 2013 10:52:32 -0400 -Subject: [PATCH] Use the standard margin for the timeout string - -So that it aligns with the other messages ---- - grub-core/normal/menu_text.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index e72ed438ba3..ca135624356 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -372,7 +372,7 @@ grub_menu_init_page (int nested, int edit, - if (bottom_message) - { - grub_term_gotoxy (term, -- (struct grub_term_coordinate) { GRUB_TERM_MARGIN, -+ (struct grub_term_coordinate) { STANDARD_MARGIN, - geo->timeout_y }); - - print_message (nested, edit, term, 0); -@@ -407,14 +407,14 @@ menu_text_print_timeout (int timeout, void *dataptr) - if (data->timeout_msg == TIMEOUT_UNKNOWN) - { - data->timeout_msg = grub_print_message_indented_real (msg_translated, -- 3, 1, data->term, 1) -+ STANDARD_MARGIN, 1, data->term, 1) - <= data->geo.timeout_lines ? TIMEOUT_NORMAL : TIMEOUT_TERSE; - if (data->timeout_msg == TIMEOUT_TERSE) - { - grub_free (msg_translated); - msg_translated = grub_xasprintf (_("%ds"), timeout); - if (grub_term_width (data->term) < 10) -- data->timeout_msg = TIMEOUT_TERSE_NO_MARGIN; -+ data->timeout_msg = STANDARD_MARGIN; - } - } - diff --git a/SOURCES/0037-Add-.eh_frame-to-list-of-relocations-stripped.patch b/SOURCES/0037-Add-.eh_frame-to-list-of-relocations-stripped.patch deleted file mode 100644 index ed48c5c..0000000 --- a/SOURCES/0037-Add-.eh_frame-to-list-of-relocations-stripped.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Fedora Ninjas -Date: Mon, 13 Jan 2014 21:50:59 -0500 -Subject: [PATCH] Add .eh_frame to list of relocations stripped - ---- - conf/Makefile.common | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/conf/Makefile.common b/conf/Makefile.common -index 2a1a886f6d5..191b1a70c6b 100644 ---- a/conf/Makefile.common -+++ b/conf/Makefile.common -@@ -38,7 +38,7 @@ CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding - LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) - CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 - CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) --STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -+STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx - - CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding - LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d diff --git a/SOURCES/0037-bz1374141-fix-incorrect-mask-for-ppc64.patch b/SOURCES/0037-bz1374141-fix-incorrect-mask-for-ppc64.patch new file mode 100644 index 0000000..15b2111 --- /dev/null +++ b/SOURCES/0037-bz1374141-fix-incorrect-mask-for-ppc64.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Masahiro Matsuya +Date: Sat, 29 Oct 2016 08:35:26 +0900 +Subject: [PATCH] bz1374141 fix incorrect mask for ppc64 + +The netmask configured in firmware is not respected on ppc64 (big endian). +When 255.255.252.0 is set as netmask in firmware, the following is the value of bootpath string in grub_ieee1275_parse_bootpath(). + + /vdevice/l-lan@30000002:speed=auto,duplex=auto,192.168.88.10,,192.168.89.113,192.168.88.1,5,5,255.255.252.0,512 + +The netmask in this bootpath is no problem, since it's a value specified in firmware. But, +The value of 'subnet_mask.ipv4' was set with 0xfffffc00, and __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)) returned 16 (not 22). +As a result, 16 was used for netmask wrongly. + +1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00) +0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4) +1111 1111 0000 0011 0000 0000 0000 0000 # ~grub_le_to_cpu32 (subnet_mask.ipv4) + +And, the count of zero with __builtin_ctz can be 16. +This patch changes it as below. + +1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00) +0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4) +1111 1111 1111 1111 1111 1100 0000 0000 # grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)) +0000 0000 0000 0000 0000 0011 1111 1111 # ~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)) + +The count of zero with __builtin_clz can be 22. (clz counts the number of one bits preceding the most significant zero bit) + +Signed-off-by: Masahiro Matsuya +Signed-off-by: Robbie Harwood +--- + grub-core/net/drivers/ieee1275/ofnet.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c +index ac4e62a95c..3860b6f78d 100644 +--- a/grub-core/net/drivers/ieee1275/ofnet.c ++++ b/grub-core/net/drivers/ieee1275/ofnet.c +@@ -220,8 +220,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath, + flags); + inter->vlantag = vlantag; + grub_net_add_ipv4_local (inter, +- __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4))); +- ++ __builtin_clz (~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)))); + } + + if (gateway_addr.ipv4 != 0) diff --git a/SOURCES/0038-Don-t-require-a-password-to-boot-entries-generated-b.patch b/SOURCES/0038-Don-t-require-a-password-to-boot-entries-generated-b.patch deleted file mode 100644 index fb0e197..0000000 --- a/SOURCES/0038-Don-t-require-a-password-to-boot-entries-generated-b.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 11 Feb 2014 11:14:50 -0500 -Subject: [PATCH] Don't require a password to boot entries generated by - grub-mkconfig. - -When we set a password, we just want that to mean you can't /edit/ an entry. - -Resolves: rhbz#1030176 - -Signed-off-by: Peter Jones ---- - util/grub.d/10_linux.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 4fc58c83304..635d2fe0cd3 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -26,7 +26,7 @@ datarootdir="@datarootdir@" - export TEXTDOMAIN=@PACKAGE@ - export TEXTDOMAINDIR="@localedir@" - --CLASS="--class gnu-linux --class gnu --class os" -+CLASS="--class gnu-linux --class gnu --class os --unrestricted" - - if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then - OS="$(sed 's, release .*$,,g' /etc/system-release)" diff --git a/SOURCES/0038-Make-grub_fatal-also-backtrace.patch b/SOURCES/0038-Make-grub_fatal-also-backtrace.patch new file mode 100644 index 0000000..f876575 --- /dev/null +++ b/SOURCES/0038-Make-grub_fatal-also-backtrace.patch @@ -0,0 +1,172 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 27 Jan 2016 09:22:42 -0500 +Subject: [PATCH] Make grub_fatal() also backtrace. + +--- + grub-core/Makefile.core.def | 3 ++ + grub-core/kern/misc.c | 8 +++++- + grub-core/lib/arm64/backtrace.c | 62 +++++++++++++++++++++++++++++++++++++++++ + grub-core/lib/backtrace.c | 2 ++ + grub-core/lib/i386/backtrace.c | 14 +++++++++- + 5 files changed, 87 insertions(+), 2 deletions(-) + create mode 100644 grub-core/lib/arm64/backtrace.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index c15e91943b..058c88ac3a 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -188,6 +188,9 @@ kernel = { + + softdiv = lib/division.c; + ++ x86 = lib/i386/backtrace.c; ++ x86 = lib/backtrace.c; ++ + i386 = kern/i386/dl.c; + i386_xen = kern/i386/dl.c; + i386_xen_pvh = kern/i386/dl.c; +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index 63b586d09c..a3e215155b 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + union printf_arg + { +@@ -1199,8 +1200,13 @@ grub_printf_fmt_check (const char *fmt, const char *fmt_expected) + static void __attribute__ ((noreturn)) + grub_abort (void) + { ++#ifndef GRUB_UTIL ++#if defined(__i386__) || defined(__x86_64__) ++ grub_backtrace(); ++#endif ++#endif + grub_printf ("\nAborted."); +- ++ + #ifndef GRUB_UTIL + if (grub_term_inputs) + #endif +diff --git a/grub-core/lib/arm64/backtrace.c b/grub-core/lib/arm64/backtrace.c +new file mode 100644 +index 0000000000..1079b5380e +--- /dev/null ++++ b/grub-core/lib/arm64/backtrace.c +@@ -0,0 +1,62 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_STACK_FRAME 102400 ++ ++void ++grub_backtrace_pointer (int frame) ++{ ++ while (1) ++ { ++ void *lp = __builtin_return_address (frame); ++ if (!lp) ++ break; ++ ++ lp = __builtin_extract_return_addr (lp); ++ ++ grub_printf ("%p: ", lp); ++ grub_backtrace_print_address (lp); ++ grub_printf (" ("); ++ for (i = 0; i < 2; i++) ++ grub_printf ("%p,", ((void **)ptr) [i + 2]); ++ grub_printf ("%p)\n", ((void **)ptr) [i + 2]); ++ nptr = *(void **)ptr; ++ if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME ++ || nptr == ptr) ++ { ++ grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr); ++ break; ++ } ++ ptr = nptr; ++ } ++} ++ ++void ++grub_backtrace (void) ++{ ++ grub_backtrace_pointer (1); ++} ++ +diff --git a/grub-core/lib/backtrace.c b/grub-core/lib/backtrace.c +index 825a8800e2..c0ad6ab8be 100644 +--- a/grub-core/lib/backtrace.c ++++ b/grub-core/lib/backtrace.c +@@ -29,6 +29,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + void + grub_backtrace_print_address (void *addr) + { ++#ifndef GRUB_UTIL + grub_dl_t mod; + + FOR_DL_MODULES (mod) +@@ -44,6 +45,7 @@ grub_backtrace_print_address (void *addr) + } + } + ++#endif + grub_printf ("%p", addr); + } + +diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c +index c3e03c7275..c67273db3a 100644 +--- a/grub-core/lib/i386/backtrace.c ++++ b/grub-core/lib/i386/backtrace.c +@@ -15,11 +15,23 @@ + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ ++#include ++#ifdef GRUB_UTIL ++#define REALLY_GRUB_UTIL GRUB_UTIL ++#undef GRUB_UTIL ++#endif ++ ++#include ++#include ++ ++#ifdef REALLY_GRUB_UTIL ++#define GRUB_UTIL REALLY_GRUB_UTIL ++#undef REALLY_GRUB_UTIL ++#endif + + #include + #include + #include +-#include + #include + #include + #include diff --git a/SOURCES/0039-Don-t-emit-Booting-.-message.patch b/SOURCES/0039-Don-t-emit-Booting-.-message.patch deleted file mode 100644 index 4133b52..0000000 --- a/SOURCES/0039-Don-t-emit-Booting-.-message.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 18 Feb 2014 09:37:49 -0500 -Subject: [PATCH] Don't emit "Booting ..." message. - -UI team still hates this stuff, so we're disabling it for RHEL 7. - -Resolves: rhbz#1023142 - -Signed-off-by: Peter Jones ---- - grub-core/normal/menu.c | 4 +++- - grub-core/normal/menu_entry.c | 3 --- - 2 files changed, 3 insertions(+), 4 deletions(-) - -diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c -index d7a222e681b..37d753d8081 100644 ---- a/grub-core/normal/menu.c -+++ b/grub-core/normal/menu.c -@@ -838,12 +838,14 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) - - /* Callback invoked immediately before a menu entry is executed. */ - static void --notify_booting (grub_menu_entry_t entry, -+notify_booting (grub_menu_entry_t __attribute__((unused)) entry, - void *userdata __attribute__((unused))) - { -+#if 0 - grub_printf (" "); - grub_printf_ (N_("Booting `%s'"), entry->title); - grub_printf ("\n\n"); -+#endif - } - - /* Callback invoked when a default menu entry executed because of a timeout -diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c -index 50eef918cf6..de64a367c4e 100644 ---- a/grub-core/normal/menu_entry.c -+++ b/grub-core/normal/menu_entry.c -@@ -1176,9 +1176,6 @@ run (struct screen *screen) - char *dummy[1] = { NULL }; - - grub_cls (); -- grub_printf (" "); -- grub_printf_ (N_("Booting a command list")); -- grub_printf ("\n\n"); - - errs_before = grub_err_printed_errors; - diff --git a/SOURCES/0039-Make-our-info-pages-say-grub2-where-appropriate.patch b/SOURCES/0039-Make-our-info-pages-say-grub2-where-appropriate.patch new file mode 100644 index 0000000..afba285 --- /dev/null +++ b/SOURCES/0039-Make-our-info-pages-say-grub2-where-appropriate.patch @@ -0,0 +1,1008 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 9 Jul 2019 12:59:58 +0200 +Subject: [PATCH] Make our info pages say "grub2" where appropriate. + +This needs to be hooked up to --program-transform=, but I haven't had +time. + +Signed-off-by: Peter Jones +--- + docs/grub-dev.texi | 4 +- + docs/grub.texi | 321 ++++++++++++++++++++++++++++------------------------- + 2 files changed, 171 insertions(+), 154 deletions(-) + +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi +index 6c629a23e2..19f708ee66 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -1,7 +1,7 @@ + \input texinfo + @c -*-texinfo-*- + @c %**start of header +-@setfilename grub-dev.info ++@setfilename grub2-dev.info + @include version-dev.texi + @settitle GNU GRUB Developers Manual @value{VERSION} + @c Unify all our little indices for now. +@@ -32,7 +32,7 @@ Invariant Sections. + + @dircategory Kernel + @direntry +-* grub-dev: (grub-dev). The GRand Unified Bootloader Dev ++* grub2-dev: (grub2-dev). The GRand Unified Bootloader Dev + @end direntry + + @setchapternewpage odd +diff --git a/docs/grub.texi b/docs/grub.texi +index 69f08d289f..0615d0ed97 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -1,7 +1,7 @@ + \input texinfo + @c -*-texinfo-*- + @c %**start of header +-@setfilename grub.info ++@setfilename grub2.info + @include version.texi + @settitle GNU GRUB Manual @value{VERSION} + @c Unify all our little indices for now. +@@ -32,15 +32,15 @@ Invariant Sections. + + @dircategory Kernel + @direntry +-* GRUB: (grub). The GRand Unified Bootloader +-* grub-install: (grub)Invoking grub-install. Install GRUB on your drive +-* grub-mkconfig: (grub)Invoking grub-mkconfig. Generate GRUB configuration +-* grub-mkpasswd-pbkdf2: (grub)Invoking grub-mkpasswd-pbkdf2. +-* grub-mkrelpath: (grub)Invoking grub-mkrelpath. +-* grub-mkrescue: (grub)Invoking grub-mkrescue. Make a GRUB rescue image +-* grub-mount: (grub)Invoking grub-mount. Mount a file system using GRUB +-* grub-probe: (grub)Invoking grub-probe. Probe device information +-* grub-script-check: (grub)Invoking grub-script-check. ++* GRUB2: (grub2). The GRand Unified Bootloader ++* grub2-install: (grub2)Invoking grub2-install. Install GRUB on your drive ++* grub2-mkconfig: (grub2)Invoking grub2-mkconfig. Generate GRUB configuration ++* grub2-mkpasswd-pbkdf2: (grub2)Invoking grub2-mkpasswd-pbkdf2. ++* grub2-mkrelpath: (grub2)Invoking grub2-mkrelpath. ++* grub2-mkrescue: (grub2)Invoking grub2-mkrescue. Make a GRUB rescue image ++* grub2-mount: (grub2)Invoking grub2-mount. Mount a file system using GRUB ++* grub2-probe: (grub2)Invoking grub2-probe. Probe device information ++* grub2-script-check: (grub2)Invoking grub2-script-check. + @end direntry + + @setchapternewpage odd +@@ -103,15 +103,15 @@ This edition documents version @value{VERSION}. + * Platform-specific operations:: Platform-specific operations + * Supported kernels:: The list of supported kernels + * Troubleshooting:: Error messages produced by GRUB +-* Invoking grub-install:: How to use the GRUB installer +-* Invoking grub-mkconfig:: Generate a GRUB configuration file +-* Invoking grub-mkpasswd-pbkdf2:: ++* Invoking grub2-install:: How to use the GRUB installer ++* Invoking grub2-mkconfig:: Generate a GRUB configuration file ++* Invoking grub2-mkpasswd-pbkdf2:: + Generate GRUB password hashes +-* Invoking grub-mkrelpath:: Make system path relative to its root +-* Invoking grub-mkrescue:: Make a GRUB rescue image +-* Invoking grub-mount:: Mount a file system using GRUB +-* Invoking grub-probe:: Probe device information for GRUB +-* Invoking grub-script-check:: Check GRUB script file for syntax errors ++* Invoking grub2-mkrelpath:: Make system path relative to its root ++* Invoking grub2-mkrescue:: Make a GRUB rescue image ++* Invoking grub2-mount:: Mount a file system using GRUB ++* Invoking grub2-probe:: Probe device information for GRUB ++* Invoking grub2-script-check:: Check GRUB script file for syntax errors + * Obtaining and Building GRUB:: How to obtain and build GRUB + * Reporting bugs:: Where you should send a bug report + * Future:: Some future plans on GRUB +@@ -230,7 +230,7 @@ surprising. + + @item + @file{grub.cfg} is typically automatically generated by +-@command{grub-mkconfig} (@pxref{Simple configuration}). This makes it ++@command{grub2-mkconfig} (@pxref{Simple configuration}). This makes it + easier to handle versioned kernel upgrades. + + @item +@@ -244,7 +244,7 @@ scripting language: variables, conditionals, and loops are available. + @item + A small amount of persistent storage is available across reboots, using the + @command{save_env} and @command{load_env} commands in GRUB and the +-@command{grub-editenv} utility. This is not available in all configurations ++@command{grub2-editenv} utility. This is not available in all configurations + (@pxref{Environment block}). + + @item +@@ -549,7 +549,7 @@ On OS which have device nodes similar to Unix-like OS GRUB tools use the + OS name. E.g. for GNU/Linux: + + @example +-# @kbd{grub-install /dev/sda} ++# @kbd{grub2-install /dev/sda} + @end example + + On AROS we use another syntax. For volumes: +@@ -572,7 +572,7 @@ For disks we use syntax: + E.g. + + @example +-# @kbd{grub-install //:ata.device/0/0} ++# @kbd{grub2-install //:ata.device/0/0} + @end example + + On Windows we use UNC path. For volumes it's typically +@@ -599,7 +599,7 @@ For disks it's + E.g. + + @example +-# @kbd{grub-install \\?\PhysicalDrive0} ++# @kbd{grub2-install \\?\PhysicalDrive0} + @end example + + Beware that you may need to further escape the backslashes depending on your +@@ -609,7 +609,7 @@ When compiled with cygwin support then cygwin drive names are automatically + when needed. E.g. + + @example +-# @kbd{grub-install /dev/sda} ++# @kbd{grub2-install /dev/sda} + @end example + + @node Installation +@@ -622,7 +622,7 @@ from the source tarball, or as a package for your OS. + + After you have done that, you need to install the boot loader on a + drive (floppy or hard disk) by using the utility +-@command{grub-install} (@pxref{Invoking grub-install}) on a UNIX-like OS. ++@command{grub2-install} (@pxref{Invoking grub2-install}) on a UNIX-like OS. + + GRUB comes with boot images, which are normally put in the directory + @file{/usr/lib/grub/-} (for BIOS-based machines +@@ -633,22 +633,22 @@ loader needs to find them (usually @file{/boot}) will be called + the @dfn{boot directory}. + + @menu +-* Installing GRUB using grub-install:: ++* Installing GRUB using grub2-install:: + * Making a GRUB bootable CD-ROM:: + * Device map:: + * BIOS installation:: + @end menu + + +-@node Installing GRUB using grub-install +-@section Installing GRUB using grub-install ++@node Installing GRUB using grub2-install ++@section Installing GRUB using grub2-install + + For information on where GRUB should be installed on PC BIOS platforms, + @pxref{BIOS installation}. + + In order to install GRUB under a UNIX-like OS (such +-as @sc{gnu}), invoke the program @command{grub-install} (@pxref{Invoking +-grub-install}) as the superuser (@dfn{root}). ++as @sc{gnu}), invoke the program @command{grub2-install} (@pxref{Invoking ++grub2-install}) as the superuser (@dfn{root}). + + The usage is basically very simple. You only need to specify one + argument to the program, namely, where to install the boot loader. The +@@ -657,13 +657,13 @@ For example, under Linux the following will install GRUB into the MBR + of the first IDE disk: + + @example +-# @kbd{grub-install /dev/sda} ++# @kbd{grub2-install /dev/sda} + @end example + + Likewise, under GNU/Hurd, this has the same effect: + + @example +-# @kbd{grub-install /dev/hd0} ++# @kbd{grub2-install /dev/hd0} + @end example + + But all the above examples assume that GRUB should put images under +@@ -677,7 +677,7 @@ boot floppy with a filesystem. Here is an example: + # @kbd{mke2fs /dev/fd0} + # @kbd{mount -t ext2 /dev/fd0 /mnt} + # @kbd{mkdir /mnt/boot} +-# @kbd{grub-install --boot-directory=/mnt/boot /dev/fd0} ++# @kbd{grub2-install --boot-directory=/mnt/boot /dev/fd0} + # @kbd{umount /mnt} + @end group + @end example +@@ -689,30 +689,37 @@ floppy instead of exposing the USB drive as a hard disk (they call it + @example + # @kbd{losetup /dev/loop0 /dev/sdb1} + # @kbd{mount /dev/loop0 /mnt/usb} +-# @kbd{grub-install --boot-directory=/mnt/usb/bugbios --force --allow-floppy /dev/loop0} ++# @kbd{grub2-install --boot-directory=/mnt/usb/bugbios --force --allow-floppy /dev/loop0} + @end example + + This install doesn't conflict with standard install as long as they are in + separate directories. + ++Note that @command{grub2-install} is actually just a shell script and the ++real task is done by other tools such as @command{grub2-mkimage}. Therefore, ++you may run those commands directly to install GRUB, without using ++@command{grub2-install}. Don't do that, however, unless you are very familiar ++with the internals of GRUB. Installing a boot loader on a running OS may be ++extremely dangerous. ++ + On EFI systems for fixed disk install you have to mount EFI System Partition. + If you mount it at @file{/boot/efi} then you don't need any special arguments: + + @example +-# @kbd{grub-install} ++# @kbd{grub2-install} + @end example + + Otherwise you need to specify where your EFI System partition is mounted: + + @example +-# @kbd{grub-install --efi-directory=/mnt/efi} ++# @kbd{grub2-install --efi-directory=/mnt/efi} + @end example + + For removable installs you have to use @option{--removable} and specify both + @option{--boot-directory} and @option{--efi-directory}: + + @example +-# @kbd{grub-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable} ++# @kbd{grub2-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable} + @end example + + @node Making a GRUB bootable CD-ROM +@@ -732,10 +739,10 @@ usually also need to include a configuration file @file{grub.cfg} and some + other GRUB modules. + + To make a simple generic GRUB rescue CD, you can use the +-@command{grub-mkrescue} program (@pxref{Invoking grub-mkrescue}): ++@command{grub2-mkrescue} program (@pxref{Invoking grub2-mkrescue}): + + @example +-$ @kbd{grub-mkrescue -o grub.iso} ++$ @kbd{grub2-mkrescue -o grub.iso} + @end example + + You will often need to include other files in your image. To do this, first +@@ -758,7 +765,7 @@ directory @file{iso/}. + Finally, make the image: + + @example +-$ @kbd{grub-mkrescue -o grub.iso iso} ++$ @kbd{grub2-mkrescue -o grub.iso iso} + @end example + + This produces a file named @file{grub.iso}, which then can be burned +@@ -774,7 +781,7 @@ storage devices. + @node Device map + @section The map between BIOS drives and OS devices + +-If the device map file exists, the GRUB utilities (@command{grub-probe}, ++If the device map file exists, the GRUB utilities (@command{grub2-probe}, + etc.) read it to map BIOS drives to OS devices. This file consists of lines + like this: + +@@ -1254,23 +1261,23 @@ need to write the whole thing by hand. + @node Simple configuration + @section Simple configuration handling + +-The program @command{grub-mkconfig} (@pxref{Invoking grub-mkconfig}) ++The program @command{grub2-mkconfig} (@pxref{Invoking grub2-mkconfig}) + generates @file{grub.cfg} files suitable for most cases. It is suitable for + use when upgrading a distribution, and will discover available kernels and + attempt to generate menu entries for them. + +-@command{grub-mkconfig} does have some limitations. While adding extra ++@command{grub2-mkconfig} does have some limitations. While adding extra + custom menu entries to the end of the list can be done by editing +-@file{/etc/grub.d/40_custom} or creating @file{/boot/grub/custom.cfg}, ++@file{/etc/grub.d/40_custom} or creating @file{/boot/grub2/custom.cfg}, + changing the order of menu entries or changing their titles may require + making complex changes to shell scripts stored in @file{/etc/grub.d/}. This + may be improved in the future. In the meantime, those who feel that it + would be easier to write @file{grub.cfg} directly are encouraged to do so + (@pxref{Booting}, and @ref{Shell-like scripting}), and to disable any system +-provided by their distribution to automatically run @command{grub-mkconfig}. ++provided by their distribution to automatically run @command{grub2-mkconfig}. + + The file @file{/etc/default/grub} controls the operation of +-@command{grub-mkconfig}. It is sourced by a shell script, and so must be ++@command{grub2-mkconfig}. It is sourced by a shell script, and so must be + valid POSIX shell input; normally, it will just be a sequence of + @samp{KEY=value} lines, but if the value contains spaces or other special + characters then it must be quoted. For example: +@@ -1308,7 +1315,7 @@ works it's not recommended since titles often contain unstable device names + and may be translated + + If you set this to @samp{saved}, then the default menu entry will be that +-saved by @samp{GRUB_SAVEDEFAULT} or @command{grub-set-default}. This relies on ++saved by @samp{GRUB_SAVEDEFAULT} or @command{grub2-set-default}. This relies on + the environment block, which may not be available in all situations + (@pxref{Environment block}). + +@@ -1319,7 +1326,7 @@ If this option is set to @samp{true}, then, when an entry is selected, save + it as a new default entry for use by future runs of GRUB. This is only + useful if @samp{GRUB_DEFAULT=saved}; it is a separate option because + @samp{GRUB_DEFAULT=saved} is useful without this option, in conjunction with +-@command{grub-set-default}. Unset by default. ++@command{grub2-set-default}. Unset by default. + This option relies on the environment block, which may not be available in + all situations (@pxref{Environment block}). + +@@ -1449,7 +1456,7 @@ intel-uc.img intel-ucode.img amd-uc.img amd-ucode.img early_ucode.cpio microcode + @end example + + @item GRUB_DISABLE_LINUX_UUID +-Normally, @command{grub-mkconfig} will generate menu entries that use ++Normally, @command{grub2-mkconfig} will generate menu entries that use + universally-unique identifiers (UUIDs) to identify the root filesystem to + the Linux kernel, using a @samp{root=UUID=...} kernel parameter. This is + usually more reliable, but in some cases it may not be appropriate. To +@@ -1471,7 +1478,7 @@ If this option is set to @samp{true}, disable the generation of recovery + mode menu entries. + + @item GRUB_DISABLE_UUID +-Normally, @command{grub-mkconfig} will generate menu entries that use ++Normally, @command{grub2-mkconfig} will generate menu entries that use + universally-unique identifiers (UUIDs) to identify various filesystems to + search for files. This is usually more reliable, but in some cases it may + not be appropriate. To disable this use of UUIDs, set this option to +@@ -1482,12 +1489,12 @@ not be appropriate. To disable this use of UUIDs, set this option to + @item GRUB_VIDEO_BACKEND + If graphical video support is required, either because the @samp{gfxterm} + graphical terminal is in use or because @samp{GRUB_GFXPAYLOAD_LINUX} is set, +-then @command{grub-mkconfig} will normally load all available GRUB video ++then @command{grub2-mkconfig} will normally load all available GRUB video + drivers and use the one most appropriate for your hardware. If you need to + override this for some reason, then you can set this option. + +-After @command{grub-install} has been run, the available video drivers are +-listed in @file{/boot/grub/video.lst}. ++After @command{grub2-install} has been run, the available video drivers are ++listed in @file{/boot/grub2/video.lst}. + + @item GRUB_GFXMODE + Set the resolution used on the @samp{gfxterm} graphical terminal. Note that +@@ -1519,7 +1526,7 @@ boot sequence. If you have problems, set this option to @samp{text} and + GRUB will tell Linux to boot in normal text mode. + + @item GRUB_DISABLE_OS_PROBER +-Normally, @command{grub-mkconfig} will try to use the external ++Normally, @command{grub2-mkconfig} will try to use the external + @command{os-prober} program, if installed, to discover other operating + systems installed on the same system and generate appropriate menu entries + for them. Set this option to @samp{true} to disable this. +@@ -1529,7 +1536,7 @@ List of space-separated FS UUIDs of filesystems to be ignored from os-prober + output. For efi chainloaders it's @@ + + @item GRUB_DISABLE_SUBMENU +-Normally, @command{grub-mkconfig} will generate top level menu entry for ++Normally, @command{grub2-mkconfig} will generate top level menu entry for + the kernel with highest version number and put all other found kernels + or alternative menu entries for recovery mode in submenu. For entries returned + by @command{os-prober} first entry will be put on top level and all others +@@ -1537,11 +1544,11 @@ in submenu. If this option is set to @samp{true}, flat menu with all entries + on top level will be generated instead. Changing this option will require + changing existing values of @samp{GRUB_DEFAULT}, @samp{fallback} (@pxref{fallback}) + and @samp{default} (@pxref{default}) environment variables as well as saved +-default entry using @command{grub-set-default} and value used with +-@command{grub-reboot}. ++default entry using @command{grub2-set-default} and value used with ++@command{grub2-reboot}. + + @item GRUB_ENABLE_CRYPTODISK +-If set to @samp{y}, @command{grub-mkconfig} and @command{grub-install} will ++If set to @samp{y}, @command{grub2-mkconfig} and @command{grub2-install} will + check for encrypted disks and generate additional commands needed to access + them during boot. Note that in this case unattended boot is not possible + because GRUB will wait for passphrase to unlock encrypted container. +@@ -1600,7 +1607,7 @@ confusing @samp{GRUB_TIMEOUT_STYLE=countdown} or + + @end table + +-For more detailed customisation of @command{grub-mkconfig}'s output, you may ++For more detailed customisation of @command{grub2-mkconfig}'s output, you may + edit the scripts in @file{/etc/grub.d} directly. + @file{/etc/grub.d/40_custom} is particularly useful for adding entire custom + menu entries; simply type the menu entries you want to add at the end of +@@ -1862,7 +1869,7 @@ images as well. + Mount this partition on/mnt/boot and disable GRUB in all OSes and manually + install self-compiled latest GRUB with: + +-@code{grub-install --boot-directory=/mnt/boot /dev/sda} ++@code{grub2-install --boot-directory=/mnt/boot /dev/sda} + + In all the OSes install GRUB tools but disable installing GRUB in bootsector, + so you'll have menu.lst and grub.cfg available for use. Also disable os-prober +@@ -1872,20 +1879,20 @@ use by setting: + + in /etc/default/grub + +-Then write a grub.cfg (/mnt/boot/grub/grub.cfg): ++Then write a grub.cfg (/mnt/boot/grub2/grub.cfg): + + @example + + menuentry "OS using grub2" @{ + insmod xfs + search --set=root --label OS1 --hint hd0,msdos8 +- configfile /boot/grub/grub.cfg ++ configfile /boot/grub2/grub.cfg + @} + + menuentry "OS using grub2-legacy" @{ + insmod ext2 + search --set=root --label OS2 --hint hd0,msdos6 +- legacy_configfile /boot/grub/menu.lst ++ legacy_configfile /boot/grub2/menu.lst + @} + + menuentry "Windows XP" @{ +@@ -1948,15 +1955,15 @@ GRUB supports embedding a configuration file directly into the core image, + so that it is loaded before entering normal mode. This is useful, for + example, when it is not straightforward to find the real configuration file, + or when you need to debug problems with loading that file. +-@command{grub-install} uses this feature when it is not using BIOS disk ++@command{grub2-install} uses this feature when it is not using BIOS disk + functions or when installing to a different disk from the one containing + @file{/boot/grub}, in which case it needs to use the @command{search} + command (@pxref{search}) to find @file{/boot/grub}. + + To embed a configuration file, use the @option{-c} option to +-@command{grub-mkimage}. The file is copied into the core image, so it may ++@command{grub2-mkimage}. The file is copied into the core image, so it may + reside anywhere on the file system, and may be removed after running +-@command{grub-mkimage}. ++@command{grub2-mkimage}. + + After the embedded configuration file (if any) is executed, GRUB will load + the @samp{normal} module (@pxref{normal}), which will then read the real +@@ -1991,13 +1998,13 @@ included in the core image: + @example + @group + search.fs_label grub root +-if [ -e /boot/grub/example/test1.cfg ]; then ++if [ -e /boot/grub2/example/test1.cfg ]; then + set prefix=($root)/boot/grub +- configfile /boot/grub/example/test1.cfg ++ configfile /boot/grub2/example/test1.cfg + else +- if [ -e /boot/grub/example/test2.cfg ]; then ++ if [ -e /boot/grub2/example/test2.cfg ]; then + set prefix=($root)/boot/grub +- configfile /boot/grub/example/test2.cfg ++ configfile /boot/grub2/example/test2.cfg + else + echo "Could not find an example configuration file!" + fi +@@ -2521,7 +2528,7 @@ grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/i38 + @end group + @end example + +-Then follow instructions printed out by grub-mknetdir on configuring your DHCP ++Then follow instructions printed out by grub2-mknetdir on configuring your DHCP + server. + + The grub.cfg file is placed in the same directory as the path output by +@@ -2715,7 +2722,7 @@ team are: + @end table + + To take full advantage of this function, install GRUB into the MBR +-(@pxref{Installing GRUB using grub-install}). ++(@pxref{Installing GRUB using grub2-install}). + + If you have a laptop which has a similar feature and not in the above list + could you figure your address and contribute? +@@ -2776,7 +2783,7 @@ bytes. + The sole function of @file{boot.img} is to read the first sector of the core + image from a local disk and jump to it. Because of the size restriction, + @file{boot.img} cannot understand any file system structure, so +-@command{grub-install} hardcodes the location of the first sector of the ++@command{grub2-install} hardcodes the location of the first sector of the + core image into @file{boot.img} when installing GRUB. + + @item diskboot.img +@@ -2806,7 +2813,7 @@ images. + + @item core.img + This is the core image of GRUB. It is built dynamically from the kernel +-image and an arbitrary list of modules by the @command{grub-mkimage} ++image and an arbitrary list of modules by the @command{grub2-mkimage} + program. Usually, it contains enough modules to access @file{/boot/grub}, + and loads everything else (including menu handling, the ability to load + target operating systems, and so on) from the file system at run-time. The +@@ -2858,7 +2865,7 @@ GRUB 2 has no single Stage 2 image. Instead, it loads modules from + In GRUB 2, images for booting from CD-ROM drives are now constructed using + @file{cdboot.img} and @file{core.img}, making sure that the core image + contains the @samp{iso9660} module. It is usually best to use the +-@command{grub-mkrescue} program for this. ++@command{grub2-mkrescue} program for this. + + @item nbgrub + There is as yet no equivalent for @file{nbgrub} in GRUB 2; it was used by +@@ -3014,8 +3021,8 @@ There are two ways to specify files, by @dfn{absolute file name} and by + + An absolute file name resembles a Unix absolute file name, using + @samp{/} for the directory separator (not @samp{\} as in DOS). One +-example is @samp{(hd0,1)/boot/grub/grub.cfg}. This means the file +-@file{/boot/grub/grub.cfg} in the first partition of the first hard ++example is @samp{(hd0,1)/boot/grub2/grub.cfg}. This means the file ++@file{/boot/grub2/grub.cfg} in the first partition of the first hard + disk. If you omit the device name in an absolute file name, GRUB uses + GRUB's @dfn{root device} implicitly. So if you set the root device to, + say, @samp{(hd1,1)} by the command @samp{set root=(hd1,1)} (@pxref{set}), +@@ -3023,8 +3030,8 @@ then @code{/boot/kernel} is the same as @code{(hd1,1)/boot/kernel}. + + On ZFS filesystem the first path component must be + @var{volume}@samp{@@}[@var{snapshot}]. +-So @samp{/rootvol@@snap-129/boot/grub/grub.cfg} refers to file +-@samp{/boot/grub/grub.cfg} in snapshot of volume @samp{rootvol} with name ++So @samp{/rootvol@@snap-129/boot/grub2/grub.cfg} refers to file ++@samp{/boot/grub2/grub.cfg} in snapshot of volume @samp{rootvol} with name + @samp{snap-129}. Trailing @samp{@@} after volume name is mandatory even if + snapshot name is omitted. + +@@ -3427,7 +3434,7 @@ The more recent release of Minix would then be identified as + @samp{other>minix>minix-3.4.0}. + + This variable is often set by @samp{GRUB_DEFAULT} (@pxref{Simple +-configuration}), @command{grub-set-default}, or @command{grub-reboot}. ++configuration}), @command{grub2-set-default}, or @command{grub2-reboot}. + + + @node fallback +@@ -3517,7 +3524,7 @@ If this variable is set, it names the language code that the + example, French would be named as @samp{fr}, and Simplified Chinese as + @samp{zh_CN}. + +-@command{grub-mkconfig} (@pxref{Simple configuration}) will try to set a ++@command{grub2-mkconfig} (@pxref{Simple configuration}) will try to set a + reasonable default for this variable based on the system locale. + + +@@ -3525,10 +3532,10 @@ reasonable default for this variable based on the system locale. + @subsection locale_dir + + If this variable is set, it names the directory where translation files may +-be found (@pxref{gettext}), usually @file{/boot/grub/locale}. Otherwise, ++be found (@pxref{gettext}), usually @file{/boot/grub2/locale}. Otherwise, + internationalization is disabled. + +-@command{grub-mkconfig} (@pxref{Simple configuration}) will set a reasonable ++@command{grub2-mkconfig} (@pxref{Simple configuration}) will set a reasonable + default for this variable if internationalization is needed and any + translation files are available. + +@@ -3646,7 +3653,7 @@ input. The default is not to pause output. + + The location of the @samp{/boot/grub} directory as an absolute file name + (@pxref{File name syntax}). This is normally set by GRUB at startup based +-on information provided by @command{grub-install}. GRUB modules are ++on information provided by @command{grub2-install}. GRUB modules are + dynamically loaded from this directory, so it must be set correctly in order + for many parts of GRUB to work. + +@@ -3737,17 +3744,17 @@ GRUB provides an ``environment block'' which can be used to save a small + amount of state. + + The environment block is a preallocated 1024-byte file, which normally lives +-in @file{/boot/grub/grubenv} (although you should not assume this). At boot ++in @file{/boot/grub2/grubenv} (although you should not assume this). At boot + time, the @command{load_env} command (@pxref{load_env}) loads environment + variables from it, and the @command{save_env} (@pxref{save_env}) command + saves environment variables to it. From a running system, the +-@command{grub-editenv} utility can be used to edit the environment block. ++@command{grub2-editenv} utility can be used to edit the environment block. + + For safety reasons, this storage is only available when installed on a plain + disk (no LVM or RAID), using a non-checksumming filesystem (no ZFS), and + using BIOS or EFI functions (no ATA, USB or IEEE1275). + +-@command{grub-mkconfig} uses this facility to implement ++@command{grub2-mkconfig} uses this facility to implement + @samp{GRUB_SAVEDEFAULT} (@pxref{Simple configuration}). + + +@@ -4476,7 +4483,7 @@ Translate @var{string} into the current language. + + The current language code is stored in the @samp{lang} variable in GRUB's + environment (@pxref{lang}). Translation files in MO format are read from +-@samp{locale_dir} (@pxref{locale_dir}), usually @file{/boot/grub/locale}. ++@samp{locale_dir} (@pxref{locale_dir}), usually @file{/boot/grub2/locale}. + @end deffn + + +@@ -4871,7 +4878,7 @@ Define a user named @var{user} with password @var{clear-password}. + + @deffn Command password_pbkdf2 user hashed-password + Define a user named @var{user} with password hash @var{hashed-password}. +-Use @command{grub-mkpasswd-pbkdf2} (@pxref{Invoking grub-mkpasswd-pbkdf2}) ++Use @command{grub2-mkpasswd-pbkdf2} (@pxref{Invoking grub2-mkpasswd-pbkdf2}) + to generate password hashes. @xref{Security}. + @end deffn + +@@ -5814,8 +5821,8 @@ The @samp{password} (@pxref{password}) and @samp{password_pbkdf2} + which has an associated password. @samp{password} sets the password in + plain text, requiring @file{grub.cfg} to be secure; @samp{password_pbkdf2} + sets the password hashed using the Password-Based Key Derivation Function +-(RFC 2898), requiring the use of @command{grub-mkpasswd-pbkdf2} +-(@pxref{Invoking grub-mkpasswd-pbkdf2}) to generate password hashes. ++(RFC 2898), requiring the use of @command{grub2-mkpasswd-pbkdf2} ++(@pxref{Invoking grub2-mkpasswd-pbkdf2}) to generate password hashes. + + In order to enable authentication support, the @samp{superusers} environment + variable must be set to a list of usernames, separated by any of spaces, +@@ -5860,7 +5867,7 @@ menuentry "May be run by user1 or a superuser" --users user1 @{ + @end group + @end example + +-The @command{grub-mkconfig} program does not yet have built-in support for ++The @command{grub2-mkconfig} program does not yet have built-in support for + generating configuration files with authentication. You can use + @file{/etc/grub.d/40_custom} to add simple superuser authentication, by + adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} +@@ -5887,7 +5894,17 @@ may halt or otherwise impact the boot process. + + An initial trusted public key can be embedded within the GRUB @file{core.img} + using the @code{--pubkey} option to @command{grub-install} +-(@pxref{Invoking grub-install}). ++(@pxref{Invoking grub2-install}). ++ ++@comment Unfortunately --pubkey is not yet supported by grub2-install, ++@comment but we should not bring up internal detail grub2-mkimage here ++@comment in the user guide (as opposed to developer's manual). ++ ++@comment An initial trusted public key can be embedded within the GRUB ++@comment @file{core.img} using the @code{--pubkey} option to ++@comment @command{grub2-mkimage} (@pxref{Invoking grub2-install}). Presently it ++@comment is necessary to write a custom wrapper around @command{grub2-mkimage} ++@comment using the @code{--grub-mkimage} flag to @command{grub2-install}. + + GRUB uses GPG-style detached signatures (meaning that a file + @file{foo.sig} will be produced when file @file{foo} is signed), and +@@ -5907,8 +5924,8 @@ gpg --detach-sign /path/to/file + For successful validation of all of GRUB's subcomponents and the + loaded OS kernel, they must all be signed. One way to accomplish this + is the following (after having already produced the desired +-@file{grub.cfg} file, e.g., by running @command{grub-mkconfig} +-(@pxref{Invoking grub-mkconfig}): ++@file{grub.cfg} file, e.g., by running @command{grub2-mkconfig} ++(@pxref{Invoking grub2-mkconfig}): + + @example + @group +@@ -5930,7 +5947,7 @@ See also: @ref{check_signatures}, @ref{verify_detached}, @ref{trust}, + Note that internally signature enforcement is controlled by setting + the environment variable @code{check_signatures} equal to + @code{enforce}. Passing one or more @code{--pubkey} options to +-@command{grub-mkimage} implicitly defines @code{check_signatures} ++@command{grub2-mkimage} implicitly defines @code{check_signatures} + equal to @code{enforce} in @file{core.img} prior to processing any + configuration files. + +@@ -6388,10 +6405,10 @@ Required files are: + + GRUB's normal start-up procedure involves setting the @samp{prefix} + environment variable to a value set in the core image by +-@command{grub-install}, setting the @samp{root} variable to match, loading ++@command{grub2-install}, setting the @samp{root} variable to match, loading + the @samp{normal} module from the prefix, and running the @samp{normal} + command (@pxref{normal}). This command is responsible for reading +-@file{/boot/grub/grub.cfg}, running the menu, and doing all the useful ++@file{/boot/grub2/grub.cfg}, running the menu, and doing all the useful + things GRUB is supposed to do. + + If, instead, you only get a rescue shell, this usually means that GRUB +@@ -6417,8 +6434,8 @@ normal + + However, any problem that leaves you in the rescue shell probably means that + GRUB was not correctly installed. It may be more useful to try to reinstall +-it properly using @kbd{grub-install @var{device}} (@pxref{Invoking +-grub-install}). When doing this, there are a few things to remember: ++it properly using @kbd{grub2-install @var{device}} (@pxref{Invoking ++grub2-install}). When doing this, there are a few things to remember: + + @itemize @bullet{} + @item +@@ -6430,7 +6447,7 @@ is usually better to use UUIDs or file system labels and avoid depending on + drive ordering entirely. + + @item +-At least on BIOS systems, if you tell @command{grub-install} to install GRUB ++At least on BIOS systems, if you tell @command{grub2-install} to install GRUB + to a partition but GRUB has already been installed in the master boot + record, then the GRUB installation in the partition will be ignored. + +@@ -6461,21 +6478,21 @@ entry which claims partition start at block 0. This change will not hamper + bootability on other machines. + + +-@node Invoking grub-install +-@chapter Invoking grub-install ++@node Invoking grub2-install ++@chapter Invoking grub2-install + +-The program @command{grub-install} generates a GRUB core image using +-@command{grub-mkimage} and installs it on your system. You must specify the ++The program @command{grub2-install} generates a GRUB core image using ++@command{grub2-mkimage} and installs it on your system. You must specify the + device name on which you want to install GRUB, like this: + + @example +-grub-install @var{install_device} ++grub2-install @var{install_device} + @end example + + The device name @var{install_device} is an OS device name or a GRUB + device name. + +-@command{grub-install} accepts the following options: ++@command{grub2-install} accepts the following options: + + @table @option + @item --help +@@ -6491,13 +6508,13 @@ separate partition or a removable disk. + If this option is not specified then it defaults to @file{/boot}, so + + @example +-@kbd{grub-install /dev/sda} ++@kbd{grub2-install /dev/sda} + @end example + + is equivalent to + + @example +-@kbd{grub-install --boot-directory=/boot/ /dev/sda} ++@kbd{grub2-install --boot-directory=/boot/ /dev/sda} + @end example + + Here is an example in which you have a separate @dfn{boot} partition which is +@@ -6505,16 +6522,16 @@ mounted on + @file{/mnt/boot}: + + @example +-@kbd{grub-install --boot-directory=/mnt/boot /dev/sdb} ++@kbd{grub2-install --boot-directory=/mnt/boot /dev/sdb} + @end example + + @item --recheck +-Recheck the device map, even if @file{/boot/grub/device.map} already ++Recheck the device map, even if @file{/boot/grub2/device.map} already + exists. You should use this option whenever you add/remove a disk + into/from your computer. + + @item --no-rs-codes +-By default on x86 BIOS systems, @command{grub-install} will use some ++By default on x86 BIOS systems, @command{grub2-install} will use some + extra space in the bootloader embedding area for Reed-Solomon + error-correcting codes. This enables GRUB to still boot successfully + if some blocks are corrupted. The exact amount of protection offered +@@ -6527,17 +6544,17 @@ installation}) where GRUB does not reside in any unpartitioned space + outside of the MBR. Disable the Reed-Solomon codes with this option. + @end table + +-@node Invoking grub-mkconfig +-@chapter Invoking grub-mkconfig ++@node Invoking grub2-mkconfig ++@chapter Invoking grub2-mkconfig + +-The program @command{grub-mkconfig} generates a configuration file for GRUB ++The program @command{grub2-mkconfig} generates a configuration file for GRUB + (@pxref{Simple configuration}). + + @example +-grub-mkconfig -o /boot/grub/grub.cfg ++grub-mkconfig -o /boot/grub2/grub.cfg + @end example + +-@command{grub-mkconfig} accepts the following options: ++@command{grub2-mkconfig} accepts the following options: + + @table @option + @item --help +@@ -6553,17 +6570,17 @@ it to standard output. + @end table + + +-@node Invoking grub-mkpasswd-pbkdf2 +-@chapter Invoking grub-mkpasswd-pbkdf2 ++@node Invoking grub2-mkpasswd-pbkdf2 ++@chapter Invoking grub2-mkpasswd-pbkdf2 + +-The program @command{grub-mkpasswd-pbkdf2} generates password hashes for ++The program @command{grub2-mkpasswd-pbkdf2} generates password hashes for + GRUB (@pxref{Security}). + + @example + grub-mkpasswd-pbkdf2 + @end example + +-@command{grub-mkpasswd-pbkdf2} accepts the following options: ++@command{grub2-mkpasswd-pbkdf2} accepts the following options: + + @table @option + @item -c @var{number} +@@ -6581,23 +6598,23 @@ Length of the salt. Defaults to 64. + @end table + + +-@node Invoking grub-mkrelpath +-@chapter Invoking grub-mkrelpath ++@node Invoking grub2-mkrelpath ++@chapter Invoking grub2-mkrelpath + +-The program @command{grub-mkrelpath} makes a file system path relative to ++The program @command{grub2-mkrelpath} makes a file system path relative to + the root of its containing file system. For instance, if @file{/usr} is a + mount point, then: + + @example +-$ @kbd{grub-mkrelpath /usr/share/grub/unicode.pf2} ++$ @kbd{grub2-mkrelpath /usr/share/grub/unicode.pf2} + @samp{/share/grub/unicode.pf2} + @end example + + This is mainly used internally by other GRUB utilities such as +-@command{grub-mkconfig} (@pxref{Invoking grub-mkconfig}), but may ++@command{grub2-mkconfig} (@pxref{Invoking grub2-mkconfig}), but may + occasionally also be useful for debugging. + +-@command{grub-mkrelpath} accepts the following options: ++@command{grub2-mkrelpath} accepts the following options: + + @table @option + @item --help +@@ -6608,17 +6625,17 @@ Print the version number of GRUB and exit. + @end table + + +-@node Invoking grub-mkrescue +-@chapter Invoking grub-mkrescue ++@node Invoking grub2-mkrescue ++@chapter Invoking grub2-mkrescue + +-The program @command{grub-mkrescue} generates a bootable GRUB rescue image ++The program @command{grub2-mkrescue} generates a bootable GRUB rescue image + (@pxref{Making a GRUB bootable CD-ROM}). + + @example + grub-mkrescue -o grub.iso + @end example + +-All arguments not explicitly listed as @command{grub-mkrescue} options are ++All arguments not explicitly listed as @command{grub2-mkrescue} options are + passed on directly to @command{xorriso} in @command{mkisofs} emulation mode. + Options passed to @command{xorriso} will normally be interpreted as + @command{mkisofs} options; if the option @samp{--} is used, then anything +@@ -6633,7 +6650,7 @@ mkdir -p disk/boot/grub + grub-mkrescue -o grub.iso disk + @end example + +-@command{grub-mkrescue} accepts the following options: ++@command{grub2-mkrescue} accepts the following options: + + @table @option + @item --help +@@ -6661,15 +6678,15 @@ Use @var{file} as the @command{xorriso} program, rather than the built-in + default. + + @item --grub-mkimage=@var{file} +-Use @var{file} as the @command{grub-mkimage} program, rather than the ++Use @var{file} as the @command{grub2-mkimage} program, rather than the + built-in default. + @end table + + +-@node Invoking grub-mount +-@chapter Invoking grub-mount ++@node Invoking grub2-mount ++@chapter Invoking grub2-mount + +-The program @command{grub-mount} performs a read-only mount of any file ++The program @command{grub2-mount} performs a read-only mount of any file + system or file system image that GRUB understands, using GRUB's file system + drivers via FUSE. (It is only available if FUSE development files were + present when GRUB was built.) This has a number of uses: +@@ -6701,13 +6718,13 @@ even if nobody has yet written a FUSE module specifically for that file + system type. + @end itemize + +-Using @command{grub-mount} is normally as simple as: ++Using @command{grub2-mount} is normally as simple as: + + @example + grub-mount /dev/sda1 /mnt + @end example + +-@command{grub-mount} must be given one or more images and a mount point as ++@command{grub2-mount} must be given one or more images and a mount point as + non-option arguments (if it is given more than one image, it will treat them + as a RAID set), and also accepts the following options: + +@@ -6729,13 +6746,13 @@ Show debugging output for conditions matching @var{string}. + @item -K prompt|@var{file} + @itemx --zfs-key=prompt|@var{file} + Load a ZFS encryption key. If you use @samp{prompt} as the argument, +-@command{grub-mount} will read a passphrase from the terminal; otherwise, it ++@command{grub2-mount} will read a passphrase from the terminal; otherwise, it + will read key material from the specified file. + + @item -r @var{device} + @itemx --root=@var{device} + Set the GRUB root device to @var{device}. You do not normally need to set +-this; @command{grub-mount} will automatically set the root device to the ++this; @command{grub2-mount} will automatically set the root device to the + root of the supplied file system. + + If @var{device} is just a number, then it will be treated as a partition +@@ -6753,10 +6770,10 @@ Print verbose messages. + @end table + + +-@node Invoking grub-probe +-@chapter Invoking grub-probe ++@node Invoking grub2-probe ++@chapter Invoking grub2-probe + +-The program @command{grub-probe} probes device information for a given path ++The program @command{grub2-probe} probes device information for a given path + or device. + + @example +@@ -6764,7 +6781,7 @@ grub-probe --target=fs /boot/grub + grub-probe --target=drive --device /dev/sda1 + @end example + +-@command{grub-probe} must be given a path or device as a non-option ++@command{grub2-probe} must be given a path or device as a non-option + argument, and also accepts the following options: + + @table @option +@@ -6777,16 +6794,16 @@ Print the version number of GRUB and exit. + @item -d + @itemx --device + If this option is given, then the non-option argument is a system device +-name (such as @samp{/dev/sda1}), and @command{grub-probe} will print ++name (such as @samp{/dev/sda1}), and @command{grub2-probe} will print + information about that device. If it is not given, then the non-option + argument is a filesystem path (such as @samp{/boot/grub}), and +-@command{grub-probe} will print information about the device containing that ++@command{grub2-probe} will print information about the device containing that + part of the filesystem. + + @item -m @var{file} + @itemx --device-map=@var{file} + Use @var{file} as the device map (@pxref{Device map}) rather than the +-default, usually @samp{/boot/grub/device.map}. ++default, usually @samp{/boot/grub2/device.map}. + + @item -t @var{target} + @itemx --target=@var{target} +@@ -6839,19 +6856,19 @@ Print verbose messages. + @end table + + +-@node Invoking grub-script-check +-@chapter Invoking grub-script-check ++@node Invoking grub2-script-check ++@chapter Invoking grub2-script-check + +-The program @command{grub-script-check} takes a GRUB script file ++The program @command{grub2-script-check} takes a GRUB script file + (@pxref{Shell-like scripting}) and checks it for syntax errors, similar to + commands such as @command{sh -n}. It may take a @var{path} as a non-option + argument; if none is supplied, it will read from standard input. + + @example +-grub-script-check /boot/grub/grub.cfg ++grub-script-check /boot/grub2/grub.cfg + @end example + +-@command{grub-script-check} accepts the following options: ++@command{grub2-script-check} accepts the following options: + + @table @option + @item --help diff --git a/SOURCES/0040-Replace-a-lot-of-man-pages-with-slightly-nicer-ones.patch b/SOURCES/0040-Replace-a-lot-of-man-pages-with-slightly-nicer-ones.patch deleted file mode 100644 index daa6fae..0000000 --- a/SOURCES/0040-Replace-a-lot-of-man-pages-with-slightly-nicer-ones.patch +++ /dev/null @@ -1,1959 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 4 Mar 2014 11:00:23 -0500 -Subject: [PATCH] Replace a lot of man pages with slightly nicer ones. - -Replace a bunch of machine generated ones with ones that look nicer. ---- - configure.ac | 23 ++++++ - conf/Makefile.extra-dist | 1 - - docs/Makefile.am | 2 - - docs/man/grub-bios-setup.h2m | 6 -- - docs/man/grub-editenv.h2m | 5 -- - docs/man/grub-emu.h2m | 6 -- - docs/man/grub-file.h2m | 2 - - docs/man/grub-fstest.h2m | 4 - - docs/man/grub-glue-efi.h2m | 4 - - docs/man/grub-install.h2m | 6 -- - docs/man/grub-kbdcomp.h2m | 10 --- - docs/man/grub-macbless.h2m | 4 - - docs/man/grub-macho2img.h2m | 4 - - docs/man/grub-menulst2cfg.h2m | 4 - - docs/man/grub-mkconfig.h2m | 4 - - docs/man/grub-mkfont.h2m | 4 - - docs/man/grub-mkimage.h2m | 6 -- - docs/man/grub-mklayout.h2m | 10 --- - docs/man/grub-mknetdir.h2m | 4 - - docs/man/grub-mkpasswd-pbkdf2.h2m | 4 - - docs/man/grub-mkrelpath.h2m | 4 - - docs/man/grub-mkrescue.h2m | 4 - - docs/man/grub-mkstandalone.h2m | 4 - - docs/man/grub-mount.h2m | 2 - - docs/man/grub-ofpathname.h2m | 4 - - docs/man/grub-pe2elf.h2m | 4 - - docs/man/grub-probe.h2m | 4 - - docs/man/grub-reboot.h2m | 5 -- - docs/man/grub-render-label.h2m | 3 - - docs/man/grub-script-check.h2m | 4 - - docs/man/grub-set-default.h2m | 5 -- - docs/man/grub-sparc64-setup.h2m | 6 -- - docs/man/grub-syslinux2cfg.h2m | 4 - - gentpl.py | 5 +- - util/grub-bios-setup.8 | 54 +++++++++++++ - util/grub-editenv.1 | 46 +++++++++++ - util/grub-file.1 | 165 ++++++++++++++++++++++++++++++++++++++ - util/grub-fstest.1 | 99 +++++++++++++++++++++++ - util/grub-glue-efi.1 | 31 +++++++ - util/grub-install.8 | 128 +++++++++++++++++++++++++++++ - util/grub-kbdcomp.1 | 19 +++++ - util/grub-macbless.1 | 22 +++++ - util/grub-menulst2cfg.1 | 12 +++ - util/grub-mkconfig.8 | 17 ++++ - util/grub-mkfont.1 | 87 ++++++++++++++++++++ - util/grub-mkimage.1 | 95 ++++++++++++++++++++++ - util/grub-mklayout.1 | 27 +++++++ - util/grub-mknetdir.1 | 12 +++ - util/grub-mkpasswd-pbkdf2.1 | 27 +++++++ - util/grub-mkrelpath.1 | 12 +++ - util/grub-mkrescue.1 | 123 ++++++++++++++++++++++++++++ - util/grub-mkstandalone.1 | 100 +++++++++++++++++++++++ - util/grub-ofpathname.8 | 12 +++ - util/grub-probe.8 | 80 ++++++++++++++++++ - util/grub-reboot.8 | 21 +++++ - util/grub-render-label.1 | 51 ++++++++++++ - util/grub-script-check.1 | 21 +++++ - util/grub-set-default.8 | 21 +++++ - util/grub-sparc64-setup.8 | 12 +++ - 59 files changed, 1318 insertions(+), 147 deletions(-) - delete mode 100644 docs/man/grub-bios-setup.h2m - delete mode 100644 docs/man/grub-editenv.h2m - delete mode 100644 docs/man/grub-emu.h2m - delete mode 100644 docs/man/grub-file.h2m - delete mode 100644 docs/man/grub-fstest.h2m - delete mode 100644 docs/man/grub-glue-efi.h2m - delete mode 100644 docs/man/grub-install.h2m - delete mode 100644 docs/man/grub-kbdcomp.h2m - delete mode 100644 docs/man/grub-macbless.h2m - delete mode 100644 docs/man/grub-macho2img.h2m - delete mode 100644 docs/man/grub-menulst2cfg.h2m - delete mode 100644 docs/man/grub-mkconfig.h2m - delete mode 100644 docs/man/grub-mkfont.h2m - delete mode 100644 docs/man/grub-mkimage.h2m - delete mode 100644 docs/man/grub-mklayout.h2m - delete mode 100644 docs/man/grub-mknetdir.h2m - delete mode 100644 docs/man/grub-mkpasswd-pbkdf2.h2m - delete mode 100644 docs/man/grub-mkrelpath.h2m - delete mode 100644 docs/man/grub-mkrescue.h2m - delete mode 100644 docs/man/grub-mkstandalone.h2m - delete mode 100644 docs/man/grub-mount.h2m - delete mode 100644 docs/man/grub-ofpathname.h2m - delete mode 100644 docs/man/grub-pe2elf.h2m - delete mode 100644 docs/man/grub-probe.h2m - delete mode 100644 docs/man/grub-reboot.h2m - delete mode 100644 docs/man/grub-render-label.h2m - delete mode 100644 docs/man/grub-script-check.h2m - delete mode 100644 docs/man/grub-set-default.h2m - delete mode 100644 docs/man/grub-sparc64-setup.h2m - delete mode 100644 docs/man/grub-syslinux2cfg.h2m - create mode 100644 util/grub-bios-setup.8 - create mode 100644 util/grub-editenv.1 - create mode 100644 util/grub-file.1 - create mode 100644 util/grub-fstest.1 - create mode 100644 util/grub-glue-efi.1 - create mode 100644 util/grub-install.8 - create mode 100644 util/grub-kbdcomp.1 - create mode 100644 util/grub-macbless.1 - create mode 100644 util/grub-menulst2cfg.1 - create mode 100644 util/grub-mkconfig.8 - create mode 100644 util/grub-mkfont.1 - create mode 100644 util/grub-mkimage.1 - create mode 100644 util/grub-mklayout.1 - create mode 100644 util/grub-mknetdir.1 - create mode 100644 util/grub-mkpasswd-pbkdf2.1 - create mode 100644 util/grub-mkrelpath.1 - create mode 100644 util/grub-mkrescue.1 - create mode 100644 util/grub-mkstandalone.1 - create mode 100644 util/grub-ofpathname.8 - create mode 100644 util/grub-probe.8 - create mode 100644 util/grub-reboot.8 - create mode 100644 util/grub-render-label.1 - create mode 100644 util/grub-script-check.1 - create mode 100644 util/grub-set-default.8 - create mode 100644 util/grub-sparc64-setup.8 - -diff --git a/configure.ac b/configure.ac -index 8331f95b645..bec8535af70 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -77,6 +77,29 @@ grub_TRANSFORM([grub-set-default]) - grub_TRANSFORM([grub-sparc64-setup]) - grub_TRANSFORM([grub-render-label]) - grub_TRANSFORM([grub-file]) -+grub_TRANSFORM([grub-bios-setup.3]) -+grub_TRANSFORM([grub-editenv.1]) -+grub_TRANSFORM([grub-fstest.3]) -+grub_TRANSFORM([grub-glue-efi.3]) -+grub_TRANSFORM([grub-install.1]) -+grub_TRANSFORM([grub-kbdcomp.3]) -+grub_TRANSFORM([grub-menulst2cfg.1]) -+grub_TRANSFORM([grub-mkconfig.1]) -+grub_TRANSFORM([grub-mkfont.3]) -+grub_TRANSFORM([grub-mkimage.1]) -+grub_TRANSFORM([grub-mklayout.3]) -+grub_TRANSFORM([grub-mknetdir.3]) -+grub_TRANSFORM([grub-mkpasswd-pbkdf2.3]) -+grub_TRANSFORM([grub-mkrelpath.3]) -+grub_TRANSFORM([grub-mkrescue.1]) -+grub_TRANSFORM([grub-mkstandalone.3]) -+grub_TRANSFORM([grub-ofpathname.3]) -+grub_TRANSFORM([grub-probe.3]) -+grub_TRANSFORM([grub-reboot.3]) -+grub_TRANSFORM([grub-render-label.3]) -+grub_TRANSFORM([grub-script-check.3]) -+grub_TRANSFORM([grub-set-default.1]) -+grub_TRANSFORM([grub-sparc64-setup.3]) - - # Optimization flag. Allow user to override. - if test "x$TARGET_CFLAGS" = x; then -diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist -index 8f1485d52a5..b909f2c073a 100644 ---- a/conf/Makefile.extra-dist -+++ b/conf/Makefile.extra-dist -@@ -11,7 +11,6 @@ EXTRA_DIST += unicode - EXTRA_DIST += util/import_gcry.py - EXTRA_DIST += util/import_unicode.py - --EXTRA_DIST += docs/man - EXTRA_DIST += docs/autoiso.cfg - EXTRA_DIST += docs/grub.cfg - EXTRA_DIST += docs/osdetect.cfg -diff --git a/docs/Makefile.am b/docs/Makefile.am -index 93eb3962765..ab28f199694 100644 ---- a/docs/Makefile.am -+++ b/docs/Makefile.am -@@ -5,5 +5,3 @@ info_TEXINFOS = grub.texi grub-dev.texi - grub_TEXINFOS = fdl.texi - - EXTRA_DIST = font_char_metrics.png font_char_metrics.txt -- -- -diff --git a/docs/man/grub-bios-setup.h2m b/docs/man/grub-bios-setup.h2m -deleted file mode 100644 -index ac6ede36296..00000000000 ---- a/docs/man/grub-bios-setup.h2m -+++ /dev/null -@@ -1,6 +0,0 @@ --[NAME] --grub-bios-setup \- set up a device to boot using GRUB --[SEE ALSO] --.BR grub-install (8), --.BR grub-mkimage (1), --.BR grub-mkrescue (1) -diff --git a/docs/man/grub-editenv.h2m b/docs/man/grub-editenv.h2m -deleted file mode 100644 -index 3859d3d4c4f..00000000000 ---- a/docs/man/grub-editenv.h2m -+++ /dev/null -@@ -1,5 +0,0 @@ --[NAME] --grub-editenv \- edit GRUB environment block --[SEE ALSO] --.BR grub-reboot (8), --.BR grub-set-default (8) -diff --git a/docs/man/grub-emu.h2m b/docs/man/grub-emu.h2m -deleted file mode 100644 -index ef1c000656a..00000000000 ---- a/docs/man/grub-emu.h2m -+++ /dev/null -@@ -1,6 +0,0 @@ --[NAME] --grub-emu \- GRUB emulator --[SEE ALSO] --If you are trying to install GRUB, then you should use --.BR grub-install (8) --rather than this program. -diff --git a/docs/man/grub-file.h2m b/docs/man/grub-file.h2m -deleted file mode 100644 -index e09bb4d3101..00000000000 ---- a/docs/man/grub-file.h2m -+++ /dev/null -@@ -1,2 +0,0 @@ --[NAME] --grub-file \- check file type -diff --git a/docs/man/grub-fstest.h2m b/docs/man/grub-fstest.h2m -deleted file mode 100644 -index 9676b159afd..00000000000 ---- a/docs/man/grub-fstest.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-fstest \- debug tool for GRUB filesystem drivers --[SEE ALSO] --.BR grub-probe (8) -diff --git a/docs/man/grub-glue-efi.h2m b/docs/man/grub-glue-efi.h2m -deleted file mode 100644 -index c1c6ded49ff..00000000000 ---- a/docs/man/grub-glue-efi.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-glue-efi \- generate a fat binary for EFI --[DESCRIPTION] --grub-glue-efi processes ia32 and amd64 EFI images and glues them according to Apple format. -diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m -deleted file mode 100644 -index 8cbbc87a0f2..00000000000 ---- a/docs/man/grub-install.h2m -+++ /dev/null -@@ -1,6 +0,0 @@ --[NAME] --grub-install \- install GRUB to a device --[SEE ALSO] --.BR grub-mkconfig (8), --.BR grub-mkimage (1), --.BR grub-mkrescue (1) -diff --git a/docs/man/grub-kbdcomp.h2m b/docs/man/grub-kbdcomp.h2m -deleted file mode 100644 -index d81f9157e01..00000000000 ---- a/docs/man/grub-kbdcomp.h2m -+++ /dev/null -@@ -1,10 +0,0 @@ --[NAME] --grub-kbdcomp \- generate a GRUB keyboard layout file --[DESCRIPTION] --grub-kbdcomp processes a X keyboard layout description in --.BR keymaps (5) --format into a format that can be used by GRUB's --.B keymap --command. --[SEE ALSO] --.BR grub-mklayout (8) -diff --git a/docs/man/grub-macbless.h2m b/docs/man/grub-macbless.h2m -deleted file mode 100644 -index 0197c0087d7..00000000000 ---- a/docs/man/grub-macbless.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-macbless \- bless a mac file/directory --[SEE ALSO] --.BR grub-install (1) -diff --git a/docs/man/grub-macho2img.h2m b/docs/man/grub-macho2img.h2m -deleted file mode 100644 -index d79aaeed8f9..00000000000 ---- a/docs/man/grub-macho2img.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-macho2img \- convert Mach-O to raw image --[SEE ALSO] --.BR grub-mkimage (1) -diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m -deleted file mode 100644 -index c2e0055ed7e..00000000000 ---- a/docs/man/grub-menulst2cfg.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-menulst2cfg \- transform legacy menu.lst into grub.cfg --[SEE ALSO] --.BR grub-mkconfig (8) -diff --git a/docs/man/grub-mkconfig.h2m b/docs/man/grub-mkconfig.h2m -deleted file mode 100644 -index 9b42f813010..00000000000 ---- a/docs/man/grub-mkconfig.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-mkconfig \- generate a GRUB configuration file --[SEE ALSO] --.BR grub-install (8) -diff --git a/docs/man/grub-mkfont.h2m b/docs/man/grub-mkfont.h2m -deleted file mode 100644 -index d46fe600eca..00000000000 ---- a/docs/man/grub-mkfont.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-mkfont \- make GRUB font files --[SEE ALSO] --.BR grub-mkconfig (8) -diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m -deleted file mode 100644 -index f0fbc2bb197..00000000000 ---- a/docs/man/grub-mkimage.h2m -+++ /dev/null -@@ -1,6 +0,0 @@ --[NAME] --grub-mkimage \- make a bootable image of GRUB --[SEE ALSO] --.BR grub-install (8), --.BR grub-mkrescue (1), --.BR grub-mknetdir (8) -diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m -deleted file mode 100644 -index 1e43409c0ab..00000000000 ---- a/docs/man/grub-mklayout.h2m -+++ /dev/null -@@ -1,10 +0,0 @@ --[NAME] --grub-mklayout \- generate a GRUB keyboard layout file --[DESCRIPTION] --grub-mklayout processes a keyboard layout description in --.BR keymaps (5) --format into a format that can be used by GRUB's --.B keymap --command. --[SEE ALSO] --.BR grub-mkconfig (8) -diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m -deleted file mode 100644 -index a2ef13ec111..00000000000 ---- a/docs/man/grub-mknetdir.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-mknetdir \- prepare a GRUB netboot directory. --[SEE ALSO] --.BR grub-mkimage (1) -diff --git a/docs/man/grub-mkpasswd-pbkdf2.h2m b/docs/man/grub-mkpasswd-pbkdf2.h2m -deleted file mode 100644 -index 4d202f3da7e..00000000000 ---- a/docs/man/grub-mkpasswd-pbkdf2.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB --[SEE ALSO] --.BR grub-mkconfig (8) -diff --git a/docs/man/grub-mkrelpath.h2m b/docs/man/grub-mkrelpath.h2m -deleted file mode 100644 -index d01f3961e3f..00000000000 ---- a/docs/man/grub-mkrelpath.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-mkrelpath \- make a system path relative to its root --[SEE ALSO] --.BR grub-probe (8) -diff --git a/docs/man/grub-mkrescue.h2m b/docs/man/grub-mkrescue.h2m -deleted file mode 100644 -index a427f02e3c6..00000000000 ---- a/docs/man/grub-mkrescue.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-mkrescue \- make a GRUB rescue image --[SEE ALSO] --.BR grub-mkimage (1) -diff --git a/docs/man/grub-mkstandalone.h2m b/docs/man/grub-mkstandalone.h2m -deleted file mode 100644 -index c77313978ad..00000000000 ---- a/docs/man/grub-mkstandalone.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-mkstandalone \- make a memdisk-based GRUB image --[SEE ALSO] --.BR grub-mkimage (1) -diff --git a/docs/man/grub-mount.h2m b/docs/man/grub-mount.h2m -deleted file mode 100644 -index 8d168982d72..00000000000 ---- a/docs/man/grub-mount.h2m -+++ /dev/null -@@ -1,2 +0,0 @@ --[NAME] --grub-mount \- export GRUB filesystem with FUSE -diff --git a/docs/man/grub-ofpathname.h2m b/docs/man/grub-ofpathname.h2m -deleted file mode 100644 -index 74b43eea039..00000000000 ---- a/docs/man/grub-ofpathname.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-ofpathname \- find OpenBOOT path for a device --[SEE ALSO] --.BR grub-probe (8) -diff --git a/docs/man/grub-pe2elf.h2m b/docs/man/grub-pe2elf.h2m -deleted file mode 100644 -index 7ca29bd703c..00000000000 ---- a/docs/man/grub-pe2elf.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-pe2elf \- convert PE image to ELF --[SEE ALSO] --.BR grub-mkimage (1) -diff --git a/docs/man/grub-probe.h2m b/docs/man/grub-probe.h2m -deleted file mode 100644 -index 6e1ffdcf937..00000000000 ---- a/docs/man/grub-probe.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-probe \- probe device information for GRUB --[SEE ALSO] --.BR grub-fstest (1) -diff --git a/docs/man/grub-reboot.h2m b/docs/man/grub-reboot.h2m -deleted file mode 100644 -index e4acace65ce..00000000000 ---- a/docs/man/grub-reboot.h2m -+++ /dev/null -@@ -1,5 +0,0 @@ --[NAME] --grub-reboot \- set the default boot entry for GRUB, for the next boot only --[SEE ALSO] --.BR grub-set-default (8), --.BR grub-editenv (1) -diff --git a/docs/man/grub-render-label.h2m b/docs/man/grub-render-label.h2m -deleted file mode 100644 -index 50ae5247c05..00000000000 ---- a/docs/man/grub-render-label.h2m -+++ /dev/null -@@ -1,3 +0,0 @@ --[NAME] --grub-render-label \- generate a .disk_label for Apple Macs. -- -diff --git a/docs/man/grub-script-check.h2m b/docs/man/grub-script-check.h2m -deleted file mode 100644 -index 3653682671a..00000000000 ---- a/docs/man/grub-script-check.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-script-check \- check grub.cfg for syntax errors --[SEE ALSO] --.BR grub-mkconfig (8) -diff --git a/docs/man/grub-set-default.h2m b/docs/man/grub-set-default.h2m -deleted file mode 100644 -index 7945001c154..00000000000 ---- a/docs/man/grub-set-default.h2m -+++ /dev/null -@@ -1,5 +0,0 @@ --[NAME] --grub-set-default \- set the saved default boot entry for GRUB --[SEE ALSO] --.BR grub-reboot (8), --.BR grub-editenv (1) -diff --git a/docs/man/grub-sparc64-setup.h2m b/docs/man/grub-sparc64-setup.h2m -deleted file mode 100644 -index 18f803a50db..00000000000 ---- a/docs/man/grub-sparc64-setup.h2m -+++ /dev/null -@@ -1,6 +0,0 @@ --[NAME] --grub-sparc64-setup \- set up a device to boot using GRUB --[SEE ALSO] --.BR grub-install (8), --.BR grub-mkimage (1), --.BR grub-mkrescue (1) -diff --git a/docs/man/grub-syslinux2cfg.h2m b/docs/man/grub-syslinux2cfg.h2m -deleted file mode 100644 -index ad25c8ab753..00000000000 ---- a/docs/man/grub-syslinux2cfg.h2m -+++ /dev/null -@@ -1,4 +0,0 @@ --[NAME] --grub-syslinux2cfg \- transform syslinux config into grub.cfg --[SEE ALSO] --.BR grub-menulst2cfg (8) -diff --git a/gentpl.py b/gentpl.py -index c86550d4f9e..2cba0bbbd6f 100644 ---- a/gentpl.py -+++ b/gentpl.py -@@ -805,10 +805,7 @@ def manpage(defn, adddeps): - - output("if COND_MAN_PAGES\n") - gvar_add("man_MANS", name + "." + mansection) -- rule(name + "." + mansection, name + " " + adddeps, """ --chmod a+x """ + name + """ --PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=""" + mansection + """ -i $(top_srcdir)/docs/man/""" + name + """.h2m -o $@ """ + name + """ --""") -+ rule(name + "." + mansection, name + " " + adddeps, "cat $(top_srcdir)/util/" + name + "." + mansection + " | $(top_builddir)/config.status --file=$@:-") - gvar_add("CLEANFILES", name + "." + mansection) - output("endif\n") - -diff --git a/util/grub-bios-setup.8 b/util/grub-bios-setup.8 -new file mode 100644 -index 00000000000..56f582b3d75 ---- /dev/null -+++ b/util/grub-bios-setup.8 -@@ -0,0 +1,54 @@ -+.TH GRUB-BIOS-SETUP 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-bios-setup\fR \(em Set up images to boot from a device. -+ -+.SH SYNOPSIS -+\fBgrub-bios-setup\fR [-a | --allow-floppy] [-b | --boot-image=\fIFILE\fR] -+.RS 17 -+[-c | --core-image=\fIFILE\fR] [-d | --directory=\fIDIR\fR] -+.RE -+.RS 17 -+[-f | --force] [-m | --device-map=\fIFILE\fR] -+.RE -+.RS 17 -+[-s | --skip-fs-probe] [-v | --verbose] \fIDEVICE\fR -+ -+.SH DESCRIPTION -+You should not normally run this program directly. Use grub-install instead. -+ -+.SH OPTIONS -+.TP -+\fB--allow-floppy\fR -+Make the device also bootable as a floppy. This option is the default for -+/dev/fdX devices. Some BIOSes will not boot images created with this option. -+ -+.TP -+\fB--boot-image\fR=\fIFILE\fR -+Use FILE as the boot image. The default value is \fBboot.img\fR. -+ -+.TP -+\fB--core-image\fR=\fIFILE\fR -+Use FILE as ther core image. The default value is \fBcore.img\fR. -+ -+.TP -+\fB--directory\fR=\fIDIR\fR -+Use GRUB files in the directory DIR. The default value is \fB/boot/grub\fR. -+ -+.TP -+\fB--force\fR -+Install even if problems are detected. -+ -+.TP -+\fB--device-map\fR=\fIFILE\fR -+Use FILE as the device map. The default value is /boot/grub/device.map . -+ -+.TP -+\fB--skip-fs-probe\fR -+Do not probe DEVICE for filesystems. -+ -+.TP -+\fB--verbose\fR -+Print verbose messages. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-editenv.1 b/util/grub-editenv.1 -new file mode 100644 -index 00000000000..d28ba03ba42 ---- /dev/null -+++ b/util/grub-editenv.1 -@@ -0,0 +1,46 @@ -+.TH GRUB-EDITENV 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-editenv\fR \(em Manage the GRUB environment block. -+ -+.SH SYNOPSIS -+\fBgrub-editenv\fR [-v | --verbose] [\fIFILE\fR] -+.RS 14 -+ -+ -+.SH DESCRIPTION -+\fBgrub-editenv\fR is a command line tool to manage GRUB's stored environment. -+ -+.SH OPTIONS -+.TP -+\fB--verbose\fR -+Print verbose messages. -+ -+.TP -+\fBFILE\fR -+.RS 7 -+File name to use for grub environment. Default is /boot/grub/grubenv . -+.RE -+ -+.SH COMMANDS -+.TP -+\fBcreate\fR -+.RS 7 -+Create a blank environment block file. -+.RE -+ -+.TP -+\fBlist\fR -+.RS 7 -+List the current variables. -+.RE -+ -+.TP -+\fBset\fR [\fINAME\fR=\fIVALUE\fR ...] -+Set variables. -+ -+.TP -+\fBunset [\fINAME\fR ...] -+Delete variables. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-file.1 b/util/grub-file.1 -new file mode 100644 -index 00000000000..b29cb327889 ---- /dev/null -+++ b/util/grub-file.1 -@@ -0,0 +1,165 @@ -+.TH GRUB-FILE 1 "Web Feb 26 2014" -+.SH NAME -+\fBgrub-file\fR \(em Check if FILE is of specified type. -+ -+.SH SYNOPSIS -+\fBgrub-file\fR (--is-i386-xen-pae-domu | --is-x86_64-xen-domu | -+.RS 11 -+--is-x86-xen-dom0 | --is-x86-multiboot | -+.RE -+.RS 11 -+--is-x86-multiboot2 | --is-arm-linux | --is-arm64-linux | -+.RE -+.RS 11 -+--is-ia64-linux | --is-mips-linux | --is-mipsel-linux | -+.RE -+.RS 11 -+--is-sparc64-linux | --is-powerpc-linux | --is-x86-linux | -+.RE -+.RS 11 -+--is-x86-linux32 | --is-x86-kfreebsd | --is-i386-kfreebsd | -+.RE -+.RS 11 -+--is-x86_64-kfreebsd | --is-x86-knetbsd | -+.RE -+.RS 11 -+--is-i386-knetbsd | --is-x86_64-knetbsd | --is-i386-efi | -+.RE -+.RS 11 -+--is-x86_64-efi | --is-ia64-efi | --is-arm64-efi | -+.RE -+.RS 11 -+--is-arm-efi | --is-hibernated-hiberfil | --is-x86_64-xnu | -+.RE -+.RS 11 -+--is-i386-xnu | --is-xnu-hibr | --is-x86-bios-bootsector) -+.RE -+.RS 11 -+\fIFILE\fR -+ -+.SH DESCRIPTION -+\fBgrub-file\fR is used to check if \fIFILE\fR is of a specified type. -+ -+.SH OPTIONS -+.TP -+--is-i386-xen-pae-domu -+Check if FILE can be booted as i386 PAE Xen unprivileged guest kernel -+ -+.TP -+--is-x86_64-xen-domu -+Check if FILE can be booted as x86_64 Xen unprivileged guest kernel -+ -+.TP -+--is-x86-xen-dom0 -+Check if FILE can be used as Xen x86 privileged guest kernel -+ -+.TP -+--is-x86-multiboot -+Check if FILE can be used as x86 multiboot kernel -+ -+.TP -+--is-x86-multiboot2 -+Check if FILE can be used as x86 multiboot2 kernel -+ -+.TP -+--is-arm-linux -+Check if FILE is ARM Linux -+ -+.TP -+--is-arm64-linux -+Check if FILE is ARM64 Linux -+ -+.TP -+--is-ia64-linux -+Check if FILE is IA64 Linux -+ -+.TP -+--is-mips-linux -+Check if FILE is MIPS Linux -+ -+.TP -+--is-mipsel-linux -+Check if FILE is MIPSEL Linux -+ -+.TP -+--is-sparc64-linux -+Check if FILE is SPARC64 Linux -+ -+.TP -+--is-powerpc-linux -+Check if FILE is POWERPC Linux -+ -+.TP -+--is-x86-linux -+Check if FILE is x86 Linux -+ -+.TP -+--is-x86-linux32 -+Check if FILE is x86 Linux supporting 32-bit protocol -+ -+.TP -+--is-x86-kfreebsd -+Check if FILE is x86 kFreeBSD -+ -+.TP -+--is-i386-kfreebsd -+Check if FILE is i386 kFreeBSD -+ -+.TP -+--is-x86_64-kfreebsd -+Check if FILE is x86_64 kFreeBSD -+ -+.TP -+--is-x86-knetbsd -+Check if FILE is x86 kNetBSD -+ -+.TP -+--is-i386-knetbsd -+Check if FILE is i386 kNetBSD -+ -+.TP -+--is-x86_64-knetbsd -+Check if FILE is x86_64 kNetBSD -+ -+.TP -+--is-i386-efi -+Check if FILE is i386 EFI file -+ -+.TP -+--is-x86_64-efi -+Check if FILE is x86_64 EFI file -+ -+.TP -+--is-ia64-efi -+Check if FILE is IA64 EFI file -+ -+.TP -+--is-arm64-efi -+Check if FILE is ARM64 EFI file -+ -+.TP -+--is-arm-efi -+Check if FILE is ARM EFI file -+ -+.TP -+--is-hibernated-hiberfil -+Check if FILE is hiberfil.sys in hibernated state -+ -+.TP -+--is-x86_64-xnu -+Check if FILE is x86_64 XNU (Mac OS X kernel) -+ -+.TP -+--is-i386-xnu -+Check if FILE is i386 XNU (Mac OS X kernel) -+ -+.TP -+--is-xnu-hibr -+Check if FILE is XNU (Mac OS X kernel) hibernated image -+ -+.TP -+--is-x86-bios-bootsector -+Check if FILE is BIOS bootsector -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-fstest.1 b/util/grub-fstest.1 -new file mode 100644 -index 00000000000..792fa78634c ---- /dev/null -+++ b/util/grub-fstest.1 -@@ -0,0 +1,99 @@ -+.TH GRUB-FSTEST 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-fstest\fR — Debug tool for GRUB's filesystem driver. -+ -+.SH SYNOPSIS -+\fBgrub-fstest\fR [-c | --diskcount=\fINUM\fR] [-C | --crypto] -+.RS 13 -+[-d | --debug=\fISTRING\fR] [-K | --zfs-key=\fIFILE\fR|\fIprompt\fR] -+.RE -+.RS 13 -+[-n | --length=\fINUM\fR] [-r | --root=\fIDEVICE_NAME\fR] -+.RE -+.RS 13 -+[-s | --skip=\fINUM\fR] [-u | --uncompress] [-v | --verbose] -+.RE -+.RS 13 -+\fIIMAGE_PATH\fR -+ -+.SH DESCRIPTION -+\fBgrub-fstest\fR is a tool for testing GRUB's filesystem drivers. You should not normally need to run this program. -+ -+.SH OPTIONS -+.TP -+\fB--diskcount\fR=\fINUM\fR -+Specify the number of input files. -+ -+.TP -+\fB--crypto\fR -+Mount cryptographic devices. -+ -+.TP -+\fB--debug\fR=\fISTRING\fR -+Set debug environment variable. -+ -+.TP -+\fB--zfs-key\fR=\fIFILE\fR|\fIprompt\fR -+Load ZFS cryptographic key. -+ -+.TP -+\fB--length\fR=\fINUM\fR -+Handle NUM bytes in output file. -+ -+.TP -+\fB--root\fR=\fIDEVICE_NAME\fR -+Set root device. -+ -+.TP -+\fB--skip\fR=\fINUM\fR -+Skip NUM bytes from output file. -+ -+.TP -+\fB--uncompress\fR -+Uncompress data. -+ -+.TP -+\fB--verbose\fR -+Print verbose messages. -+ -+.SH COMMANDS -+.TP -+\fBblocklist\fR \fIFILE\fR -+Display block list of \fIFILE\fR. -+ -+.TP -+\fBcat\fR \fIFILE\fR -+Display \fIFILE\fR on standard output. -+ -+.TP -+\fBcmp\fR \fIFILE\fR \fILOCAL\fR -+Compare \fIFILE\fR with local file \fILOCAL\fR. -+ -+.TP -+\fBcp\fR \fIFILE\fR \fILOCAL\fR -+Copy \fIFILE\fR to local file \fILOCAL\fR. -+ -+.TP -+\fBcrc\fR \fIFILE\fR -+Display the CRC-32 checksum of \fIFILE\fR. -+ -+.TP -+\fBhex\fR \fIFILE\fR -+Display contents of \fIFILE\fR in hexidecimal. -+ -+.TP -+\fBls\fR \fIPATH\fR -+List files at \fIPATH\fR. -+ -+.TP -+\fBxnu_uuid\fR \fIDEVICE\fR -+Display the XNU UUID of \fIDEVICE\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-glue-efi.1 b/util/grub-glue-efi.1 -new file mode 100644 -index 00000000000..72bd555d577 ---- /dev/null -+++ b/util/grub-glue-efi.1 -@@ -0,0 +1,31 @@ -+.TH GRUB-GLUE-EFI 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-glue-efi\fR \(em Create an Apple fat EFI binary. -+ -+.SH SYNOPSIS -+\fBgrub-glue-efi\fR <-3 | --input32=\fIFILE\fR> <-6 | --input64=\fIFILE\fR> -+.RS 15 -+<-o | --output=\fIFILE\fR> [-v | --verbose] -+ -+.SH DESCRIPTION -+\fBgrub-glue-efi\fR creates an Apple fat EFI binary from two EFI binaries. -+ -+.SH OPTIONS -+.TP -+\fB--input32\fR=\fIFILE\fR -+Read 32-bit binary from \fIFILE\fR. -+ -+.TP -+\fB--input64\fR=\fIFILE\fR -+Read 64-bit binary from \fIFILE\fR. -+ -+.TP -+\fB--output\fR=\fIFILE\fR -+Write resulting fat binary to \fIFILE\fR. -+ -+.TP -+\fB--verbose\fR -+Print verbose messages. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-install.8 b/util/grub-install.8 -new file mode 100644 -index 00000000000..1db89e94b3b ---- /dev/null -+++ b/util/grub-install.8 -@@ -0,0 +1,128 @@ -+.TH GRUB-INSTALL 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-install\fR \(em Install GRUB on a device. -+ -+.SH SYNOPSIS -+\fBgrub-install\fR [--modules=\fIMODULES\fR] [--install-modules=\fIMODULES\fR] -+.RS 14 -+[--themes=\fITHEMES\fR] [--fonts=\fIFONTS\fR] [--locales=\fILOCALES\fR] -+.RE -+.RS 14 -+[--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] [-d | --directory=\fIDIR\fR] -+.RE -+.RS 14 -+[--grub-mkimage=\fIFILE\fR] [--boot-directory=\fIDIR\fR] -+.RE -+.RS 14 -+[--target=\fITARGET\fR] [--grub-setup=\fIFILE\fR] -+.RE -+.RS 14 -+[--grub-mkrelpath=\fIFILE\fR] [--grub-probe=\fIFILE\fR] -+.RE -+.RS 14 -+[--allow-floppy] [--recheck] [--force] [--force-file-id] -+.RE -+.RS 14 -+[--disk-module=\fIMODULE\fR] [--no-nvram] [--removable] -+.RE -+.RS 14 -+[--bootloader-id=\fIID\fR] [--efi-directory=\fIDIR\fR] \fIINSTALL_DEVICE\fR -+ -+.SH DESCRIPTION -+\fBgrub-install\fR installs GRUB onto a device. This includes copying GRUB images into the target directory (generally \fI/boot/grub\fR), and on some platforms may also include installing GRUB onto a boot sector. -+ -+.SH OPTIONS -+.TP -+\fB--modules\fR=\fIMODULES\fR\! -+Pre-load modules specified by \fIMODULES\fR. -+ -+.TP -+\fB--install-modules\fR=\fIMODULES\fR -+Install only \fIMODULES\fR and their dependencies. The default is to install all available modules. -+ -+.TP -+\fB--themes\fR=\fITHEMES\fR -+Install \fITHEMES\fR. The default is to install the \fIstarfield\fR theme, if available. -+ -+.TP -+\fB--fonts\fR=\fIFONTS\fR -+Install \fIFONTS\fR. The default is to install the \fIunicode\fR font. -+ -+.TP -+\fB--locales\fR=\fILOCALES\fR -+Install only locales listed in \fILOCALES\fR. The default is to install all available locales. -+ -+.TP -+\fB--compress\fR=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR -+Compress GRUB files using the specified compression algorithm. -+ -+.TP -+\fB--directory\fR=\fIDIR\fR -+Use images and modules in \fIDIR\fR. -+ -+.TP -+\fB--grub-mkimage\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-mkimage\fR. The default is \fI/usr/bin/grub-mkimage\fR. -+ -+.TP -+\fB--boot-directory\fR=\fIDIR\fR -+Use \fIDIR\fR as the boot directory. The default is \fI/boot\fR. GRUB will put its files in a subdirectory of this directory named \fIgrub\fR. -+ -+.TP -+\fB--target\fR=\fITARGET\fR -+Install GRUB for \fITARGET\fR platform. The default is the platform \fBgrub-install\fR is running on. -+ -+.TP -+\fB--grub-setup\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-setup\fR. The default is \fI/usr/bin/grub-setup\fR. -+ -+.TP -+\fB--grub-mkrelpath\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-mkrelpath\fR. The default is \fI/usr/bin/grub-mkrelpath\fR. -+ -+.TP -+\fB--grub-probe\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-probe\fR. The default is \fI/usr/bin/grub-mkrelpath\fR. -+ -+.TP -+\fB--allow-floppy -+Make the device also bootable as a floppy. This option is the default for /dev/fdX devices. Some BIOSes will not boot images created with this option. -+ -+.TP -+\fB--recheck -+Delete any existing device map and create a new one if necessary. -+ -+.TP -+\fB--force -+Install even if problems are detected. -+ -+.TP -+\fB--force-file-id -+Use identifier file even if UUID is available. -+ -+.TP -+\fB--disk-module\fR=\fIMODULE\fR -+Use \fIMODULE\fR for disk access. This allows you to manually specify either \fIbiosdisk\fR or \fInative\fR disk access. This option is only available on the BIOS target platform. -+ -+.TP -+\fB--no-nvram -+Do not update the \fIboot-device\fR NVRAM variable. This option is only available on IEEE1275 target platforms. -+ -+.TP -+\fB--removable -+Treat the target device as if it is removeable. This option is only available on the EFI target platform. -+ -+.TP -+\fB--bootloader-id\fR=\fIID\fR -+Use \fIID\fR as the bootloader ID. This option is only available on the EFI target platform. -+ -+.TP -+\fB--efi-directory\fR=\fIDIR\fR -+Use \fIDIR\fR as the EFI System Partition root. This option is only available on the EFI target platform. -+ -+.TP -+\fIINSTALL_DEVICE\fR -+Install GRUB to the block device \fIINSTALL_DEVICE\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-kbdcomp.1 b/util/grub-kbdcomp.1 -new file mode 100644 -index 00000000000..0bb969a5b43 ---- /dev/null -+++ b/util/grub-kbdcomp.1 -@@ -0,0 +1,19 @@ -+.TH GRUB-KBDCOMP 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-kbdcomp\fR \(em Generate a GRUB keyboard layout file. -+ -+.SH SYNOPSIS -+\fBgrub-kbdcomp\fR <-o | --output=\fIFILE\fR> \fICKBMAP_ARGUMENTS\fR -+ -+.SH DESCRIPTION -+\fBgrub-kbdcomp\fR processes an X keyboard layout description in -+\fBkeymaps\fR(5) format into a format that can be used by GRUB's \fBkeymap\fR -+command. -+ -+.SH OPTIONS -+.TP -+\fB--output\fR=\fIFILE\fR -+Write output to \fIFILE\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-macbless.1 b/util/grub-macbless.1 -new file mode 100644 -index 00000000000..41a96186f70 ---- /dev/null -+++ b/util/grub-macbless.1 -@@ -0,0 +1,22 @@ -+.TH GRUB-MACBLESS 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-macbless\fR \(em Mac-style bless on HFS or HFS+ -+ -+.SH SYNOPSIS -+\fBgrub-macbless\fR [-v | --verbose] [-p | --ppc] \fIFILE\fR | [-x | --x86] \fIFILE\fR -+ -+.SH OPTIONS -+.TP -+--x86 -+Bless for x86 based Macs. -+ -+.TP -+--ppc -+Bless for PPC based Macs. -+ -+.TP -+--verbose -+Print verbose messages. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-menulst2cfg.1 b/util/grub-menulst2cfg.1 -new file mode 100644 -index 00000000000..91e2ef87113 ---- /dev/null -+++ b/util/grub-menulst2cfg.1 -@@ -0,0 +1,12 @@ -+.TH GRUB-MENULST2CFG 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-menulst2cfg\fR \(em Convert a configuration file from GRUB 0.xx to GRUB 2.xx format. -+ -+.SH SYNOPSIS -+\fBgrub-menulst2cfg\fR [\fIINFILE\fR [\fIOUTFILE\fR]] -+ -+.SH DESCRIPTION -+\fBgrub-menulst2cfg\fR converts a configuration file from GRUB 0.xx to the current format. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkconfig.8 b/util/grub-mkconfig.8 -new file mode 100644 -index 00000000000..a2d1f577b9b ---- /dev/null -+++ b/util/grub-mkconfig.8 -@@ -0,0 +1,17 @@ -+.TH GRUB-MKCONFIG 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mkconfig\fR \(em Generate a GRUB configuration file. -+ -+.SH SYNOPSIS -+\fBgrub-mkconfig\fR [-o | --output=\fIFILE\fR] -+ -+.SH DESCRIPTION -+\fBgrub-mkconfig\fR generates a configuration file for GRUB. -+ -+.SH OPTIONS -+.TP -+\fB--output\fR=\fIFILE\fR -+Write generated output to \fIFILE\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkfont.1 b/util/grub-mkfont.1 -new file mode 100644 -index 00000000000..3494857987d ---- /dev/null -+++ b/util/grub-mkfont.1 -@@ -0,0 +1,87 @@ -+.TH GRUB-MKFONT 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mkfont\fR \(em Convert common font file formats into the PF2 format. -+ -+.SH SYNOPSIS -+\fBgrub-mkfont\fR [--ascii-bitmaps] [-a | --force-autohint] -+.RS 13 -+[-b | --bold] [-c | --asce=\fINUM\fR] [-d | --desc=\fINUM\fR] -+.RE -+.RS 13 -+[-i | --index=\fINUM\fR] [-n | --name=\fINAME\fR] [--no-bitmap] -+.RE -+.RS 13 -+[--no-hinting] <-o | --output=\fIFILE\fR> -+.RE -+.RS 13 -+[-r | --range=\fIFROM-TO\fR[\fI,FROM-TO\fR]] [-s | --size=\fISIZE\fR] -+.RE -+.RS 13 -+[-v | --verbose] [--width-spec] \fIFONT_FILES\fR -+ -+.SH DESCRIPTION -+\fBgrub-mkfont\fR converts font files from common formats into the PF2 format used by GRUB. -+ -+.SH OPTIONS -+.TP -+--ascii-bitmaps -+Save only bitmaps for ASCII characters. -+ -+.TP -+--force-autohint -+Force generation of automatic hinting. -+ -+.TP -+--bold -+Convert font to bold. -+ -+.TP -+--asce=\fINUM\fR -+Set font ascent to \fINUM\fR. -+ -+.TP -+--desc=\fINUM\fR -+Set font descent to \fINUM\fR. -+ -+.TP -+--index=\fINUM\fR -+Select face index \fINUM\fR. -+ -+.TP -+--name=\fINAME\fR -+Set font family to \fINAME\fR. -+ -+.TP -+--no-bitmap -+Ignore bitmap strikes when loading. -+ -+.TP -+--no-hinting -+Disable hinting. -+ -+.TP -+--output=\fIFILE\fR -+Save ouptut to \fIFILE\fR. This argument is required. -+ -+.TP -+--range=\fIFROM-TO\fR\fI,FROM-TO\fR -+Set the font ranges to each pair of \fIFROM\fR,\fITO\fR. -+ -+.TP -+--size=\fISIZE\fR -+Set font size to \fISIZE\fR. -+ -+.TP -+--verbose -+Print verbose messages. -+ -+.TP -+--width-spec -+Create a width summary file. -+ -+.TP -+\fIFONT_FILES\fR -+The input files to be converted. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkimage.1 b/util/grub-mkimage.1 -new file mode 100644 -index 00000000000..4dea4f54597 ---- /dev/null -+++ b/util/grub-mkimage.1 -@@ -0,0 +1,95 @@ -+.TH GRUB-MKIMAGE 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mkimage\fR \(em Make a bootable GRUB image. -+ -+.SH SYNOPSIS -+\fBgrub-mkimage\fR [-c | --config=\fRFILE\fI] [-C | --compression=(\fIxz\fR,\fInone\fR,\fIauto\fR)] -+.RS 14 -+[-d | --directory=\fRDIR\fR] [-k | --pubkey=\fIFILE\fR] -+.RE -+.RS 14 -+[-m | --memdisk=\fIFILE\fR] [-n | --note] [-o | --output=\fIFILE\fR] -+.RE -+.RS 14 -+[-O | --format=\fIFORMAT\fR] [-p | --prefix=\fIDIR\fR] -+.RE -+.RS 14 -+[-v | --verbose] \fIMODULES\fR -+ -+.SH DESCRIPTION -+\fBgrub-mkimage\fI builds a bootable image of GRUB. -+ -+.SH OPTIONS -+.TP -+--config=\fIFILE\fR -+Embed \fIFILE\fR as the image's initial configuration file. -+ -+.TP -+--compression=(\fIxz\fR,\fInone\fR,\fIauto\fR) -+Use one of \fIxz\fR, \fInone\fR, or \fIauto\fR as the compression method for the core image. -+ -+.TP -+--directory=\fIDIR\fR -+Use images and modules from \fIDIR\fR. The default value is \fB/usr/lib/grub/\fR. -+ -+.TP -+--pubkey=\fIFILE\fR -+Embed the public key \fIFILE\fR for signature checking. -+ -+.TP -+--memdisk=\fIFILE\fR -+Embed the memdisk image \fIFILE\fR. If no \fB-p\fR option is also specified, this implies \fI-p (memdisk)/boot/grub\fR. -+ -+.TP -+--note -+Add a CHRP \fINOTE\fR section. This option is only valid on IEEE1275 platforms. -+ -+.TP -+--output=\fIFILE\fR -+Write the generated file to \fIFILE\fR. The default is to write to standard output. -+ -+.TP -+--format=\fIFORMAT\fR -+Generate an image in the specified \fIFORMAT\fR. Valid values are: -+.RS -+.RS 4 -+.P -+i386-coreboot, -+i386-multiboot, -+i386-pc, -+i386-pc-pxe, -+i386-efi, -+i386-ieee1275, -+i386-qemu, -+x86_64-efi, -+mipsel-yeeloong-flash, -+mipsel-fuloong2f-flash, -+mipself-loongson-elf, -+powerpc-ieee1275, -+sparc64-ieee1275-raw, -+sparc64-ieee1275-cdcore, -+sparc64-ieee1275-aout, -+ia64-efi, -+mips-arc, -+mipsel-arc, -+mipsel-qemu_mips-elf, -+mips-qemu_mips-flash, -+mipsel-qemu_mips-flash, -+mips-qemu_mips-elf -+.RE -+.RE -+ -+.TP -+--prefix=\fIDIR\fR -+Set prefix directory. The default value is \fI/boot/grub\fR. -+ -+.TP -+--verbose -+Print verbose messages. -+ -+.TP -+\fIMODULES\fR -+Include \fIMODULES\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mklayout.1 b/util/grub-mklayout.1 -new file mode 100644 -index 00000000000..d1bbc2ec515 ---- /dev/null -+++ b/util/grub-mklayout.1 -@@ -0,0 +1,27 @@ -+.TH GRUB-MKLAYOUT 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mklayout\fR \(em Generate a GRUB keyboard layout file. -+ -+.SH SYNOPSIS -+\fBgrub-mklayout\fR [-i | --input=\fIFILE\fR] [-o | --output=\fIFILE\fR] -+.RS 15 -+[-v | --verbose] -+ -+.SH DESCRIPTION -+\fBgrub-mklayout\fR generates a GRUB keyboard layout description which corresponds with the Linux console layout description given as input. -+ -+.SH OPTIONS -+.TP -+--input=\fIFILE\fR -+Use \fIFILE\fR as the input. The default value is the standard input device. -+ -+.TP -+--output=\fIFILE\fR -+Use \fIFILE\fR as the output. The default value is the standard output device. -+ -+.TP -+--verbose -+Print verbose messages. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mknetdir.1 b/util/grub-mknetdir.1 -new file mode 100644 -index 00000000000..fa7e8d4ef0d ---- /dev/null -+++ b/util/grub-mknetdir.1 -@@ -0,0 +1,12 @@ -+.TH GRUB-MKNETDIR 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mknetdir\fR \(em Prepare a GRUB netboot directory. -+ -+.SH SYNOPSIS -+\fBgrub-mknetdir\fR -+ -+.SH DESCRIPTION -+\fBgrub-mknetdir\fR prepares a directory for GRUB to be netbooted from. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkpasswd-pbkdf2.1 b/util/grub-mkpasswd-pbkdf2.1 -new file mode 100644 -index 00000000000..73c437c15d8 ---- /dev/null -+++ b/util/grub-mkpasswd-pbkdf2.1 -@@ -0,0 +1,27 @@ -+.TH GRUB-MKPASSWD-PBKDF2 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mkpasswd-pbkdf2\fR \(em Generate a PBKDF2 password hash. -+ -+.SH SYNOPSIS -+\fBgrub-mkpasswd-pbkdf2\fR [-c | --iteration-count=\fINUM\fR] [-l | --buflen=\fINUM\fR] -+.RS 22 -+[-s | --salt=\fINUM\fR] -+ -+.SH DESCRIPTION -+\fBgrub-mkpasswd-pbkdf2\fR generates a PBKDF2 password string suitable for use in a GRUB configuration file. -+ -+.SH OPTIONS -+.TP -+--iteration-count=\fINUM\fR -+Number of PBKDF2 iterations. -+ -+.TP -+--buflen=\fINUM\fR -+Length of generated hash. -+ -+.TP -+--salt=\fINUM\fR -+Length of salt to use. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkrelpath.1 b/util/grub-mkrelpath.1 -new file mode 100644 -index 00000000000..85f1113621d ---- /dev/null -+++ b/util/grub-mkrelpath.1 -@@ -0,0 +1,12 @@ -+.TH GRUB-MKRELPATH 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mkrelpath\fR \(em Generate a relative GRUB path given an OS path. -+ -+.SH SYNOPSIS -+\fBgrub-mkrelpath\fR \fIFILE\fR -+ -+.SH DESCRIPTION -+\fBgrub-mkrelpath\fR takes an OS filesystem path for \fIFILE\fR and returns a relative path suitable for use in a GRUB configuration file. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkrescue.1 b/util/grub-mkrescue.1 -new file mode 100644 -index 00000000000..4ed9fc723fd ---- /dev/null -+++ b/util/grub-mkrescue.1 -@@ -0,0 +1,123 @@ -+.TH GRUB-MKRESCUE 3 "Wed Feb 26 2014" -+.SH NAME -+grub-mkrescue \(em Generate a GRUB rescue image using GNU Xorriso. -+ -+.SH SYNOPSIS -+\fBgrub-mkrescue\fR [-o | --output=\fIFILE\fR] [--modules=\fIMODULES\fR] -+.RS 15 -+[--install-modules=\fIMODULES\fR] [--themes=\fITHEMES\fR] -+.RE -+.RS 15 -+[--fonts=\fIFONTS\fR] [--locales=\fILOCALES\fR] -+.RE -+.RS 15 -+[--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] [-d | --directory=\fIDIR\fR] -+.RE -+.RS 15 -+[--grub-mkimage=\fIFILE\fR] [--rom-directory=\fIDIR\fR] -+.RE -+.RS 15 -+[--xorriso=\fIFILE\fR] [--grub-glue-efi=\fIFILE\fR] -+.RE -+.RS 15 -+[--grub-render-label=\fIFILE\fR] [--label-font=\fIFILE\fR] -+.RE -+.RS 15 -+[--label-color=\fICOLOR\fR] [--label-bgcolor=\fIFILE\fR] -+.RE -+.RS 15 -+[--product-name=\fISTRING\fR] [--product-version=\fISTRING\fR] -+.RE -+.RS 15 -+[--sparc-boot] [--arcs-boot] -+ -+.SH DESCRIPTION -+\fBgrub-mkrescue\fR can be used to generate a rescue image with the GRUB bootloader. -+ -+.SH OPTIONS -+.TP -+\fB--output\fR=\fIFILE\fR -+Write the generated file to \fIFILE\fR. The default is to write to standard output. -+ -+.TP -+\fB--modules\fR=\fIMODULES\fR -+Pre-load modules specified by \fIMODULES\fR. -+ -+.TP -+\fB--install-modules\fR=\fIMODULES\fR -+Install only \fIMODULES\fR and their dependencies. The default is to install all available modules. -+ -+.TP -+\fB--themes\fR=\fITHEMES\fR -+Install \fITHEMES\fR. The default is to install the \fIstarfield\fR theme, if available. -+ -+.TP -+\fB--fonts\fR=\fIFONTS\fR -+Install \fIFONTS\fR. The default is to install the \fIunicode\fR font. -+ -+.TP -+\fB--locales\fR=\fILOCALES\fR -+Install only locales listed in \fILOCALES\fR. The default is to install all available locales. -+ -+.TP -+\fB--compress\fR[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR] -+Compress GRUB files using the specified compression algorithm. -+ -+.TP -+\fB--directory\fR=\fIDIR\fR -+Use images and modules in \fIDIR\fR. -+ -+.TP -+\fB--grub-mkimage\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-mkimage\fR(1). The default is \fI/usr/bin/grub-mkimage\fR. -+ -+.TP -+\fB--rom-directory\fR=\fIDIR\fR -+Save ROM images in \fIDIR\fR. -+ -+.TP -+\fB--xorriso\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBxorriso\fI. -+ -+.TP -+\fB--grub-glue-efi\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-glue-efi\fR(3). -+ -+.TP -+\fB--grub-render-label\fR=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-render-label\fR(3). -+ -+.TP -+\fB--label-font\fR=\fIFILE\fR -+Use \fIFILE\fR as the font file for generated labels. -+ -+.TP -+\fB--label-color\fR=\fICOLOR\fR -+Use \fICOLOR\fI as the color for generated labels. -+ -+.TP -+\fB--label-bgcolor\fR=\fICOLOR\fR -+Use \fICOLOR\fR as the background color for generated labels. -+ -+.TP -+\fB--product-name\fR=\fISTRING\fR -+Use \fISTRING\fR as the product name in generated labels. -+ -+.TP -+\fB--product-version\fR=\fISTRING\fR -+Use \fISTRING\fR as the product version in generated labels. -+ -+.TP -+\fB--sparc-boot\fR -+Enable booting the SPARC platform. This disables HFS+, APM, ARCS, and "boot as disk image" on the \fIi386-pc\fR target platform. -+ -+.TP -+\fB--arcs-boot\fR -+Enable ARCS booting. This is typically for big-endian MIPS machines, and disables HFS+, APM, sparc64, and "boot as disk image" on the \fIi386-pc\fR target platform. -+ -+.TP -+\fB--\fR -+All options after a \fB--\fR will be passed directly to xorriso's command line when generating the image. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkstandalone.1 b/util/grub-mkstandalone.1 -new file mode 100644 -index 00000000000..ba2d2bdf279 ---- /dev/null -+++ b/util/grub-mkstandalone.1 -@@ -0,0 +1,100 @@ -+.TH GRUB-MKSTANDALONE 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-mkstandalone\fR \(em Generate a standalone image in the selected format. -+ -+.SH SYNOPSIS -+\fBgrub-mkstandalone\fR [-o | --output=\fIFILE\fR] [-O | --format=\fIFORMAT\fR] -+.RS 19 -+[-C | --compression=(\fIxz\fR|\fInone\fR|\fIauto\fR)] -+.RE -+.RS 19 -+[--modules=\fIMODULES\fR] [--install-modules=\fIMODULES\fR] -+.RE -+.RS 19 -+[--themes=\fITHEMES\fR] [--fonts=\fIFONTS\fR] -+.RE -+.RS 19 -+[--locales=\fILOCALES\fR] [--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] -+.RE -+.RS 19 -+[-d | --directory=\fIDIR\fR] [--grub-mkimage=\fIFILE\fR] -+.RE -+.RS 19 -+\fISOURCE...\fR -+ -+.SH DESCRIPTION -+ -+.SH OPTIONS -+.TP -+--output=\fIFILE\fR -+Write the generated file to \fIFILE\fR. The default is to write to standard output. -+ -+.TP -+--format=\fIFORMAT\fR -+Generate an image in the specified \fIFORMAT\fR. Valid values are: -+.RS -+.RS 4 -+.P -+i386-coreboot, -+i386-multiboot, -+i386-pc, -+i386-pc-pxe, -+i386-efi, -+i386-ieee1275, -+i386-qemu, -+x86_64-efi, -+mipsel-yeeloong-flash, -+mipsel-fuloong2f-flash, -+mipself-loongson-elf, -+powerpc-ieee1275, -+sparc64-ieee1275-raw, -+sparc64-ieee1275-cdcore, -+sparc64-ieee1275-aout, -+ia64-efi, -+mips-arc, -+mipsel-arc, -+mipsel-qemu_mips-elf, -+mips-qemu_mips-flash, -+mipsel-qemu_mips-flash, -+mips-qemu_mips-elf -+.RE -+.RE -+ -+.TP -+--compression=(\fIxz\fR|\fInone\fR|\fIauto\fR) -+Use one of \fIxz\fR, \fInone\fR, or \fIauto\fR as the compression method for the core image. -+ -+.TP -+--modules=\fIMODULES\fR -+Pre-load modules specified by \fIMODULES\fR. -+ -+.TP -+--install-modules=\fIMODULES\fR -+Install only \fIMODULES\fR and their dependencies. The default is to install all available modules. -+ -+.TP -+--themes=\fITHEMES\fR -+Install \fITHEMES\fR. The default is to install the \fIstarfield\fR theme, if available. -+ -+.TP -+--fonts=\fIFONTS\fR -+Install \fIFONTS\fR. The default is to install the \fIunicode\fR font. -+ -+.TP -+--locales=\fILOCALES\fR -+Install only locales listed in \fILOCALES\fR. The default is to install all available locales. -+ -+.TP -+--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR] -+Compress GRUB files using the specified compression algorithm. -+ -+.TP -+--directory=\fIDIR\fR -+Use images and modules in \fIDIR\fR. -+ -+.TP -+--grub-mkimage=\fIFILE\fR -+Use \fIFILE\fR as \fBgrub-mkimage\fR. The default is \fI/usr/bin/grub-mkimage\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-ofpathname.8 b/util/grub-ofpathname.8 -new file mode 100644 -index 00000000000..bf3743aeba1 ---- /dev/null -+++ b/util/grub-ofpathname.8 -@@ -0,0 +1,12 @@ -+.TH GRUB-OFPATHNAME 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-ofpathname\fR \(em Generate an IEEE-1275 device path for a specified device. -+ -+.SH SYNOPSIS -+\fBgrub-ofpathname\fR \fIDEVICE\fR -+ -+.SH DESCRIPTION -+\fBgrub-ofpathname\fR generates an IEEE-1275 device path for the specified \fIDEVICE\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-probe.8 b/util/grub-probe.8 -new file mode 100644 -index 00000000000..04e26c832bb ---- /dev/null -+++ b/util/grub-probe.8 -@@ -0,0 +1,80 @@ -+.TH GRUB-PROBE 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-probe\fR \(em Probe device information for a given path. -+ -+.SH SYNOPSIS -+\fBgrub-probe\fR \[-d | --device] [-m | --device-map=\fIFILE\fR] -+.RS 12 -+[-t | --target=(fs|fs_uuid|fs_label|drive|device|partmap| -+.RE -+.RS 28 -+abstraction|cryptodisk_uuid| -+.RE -+.RS 28 -+msdos_parttype)] -+.RE -+.RS 12 -+[-v | --verbose] (PATH|DEVICE) -+ -+.SH DESCRIPTION -+\fBgrub-probe\fR probes a path or device for filesystem and related information. -+ -+.SH OPTIONS -+.TP -+--device -+Final option represents a \fIDEVICE\fR, rather than a filesystem \fIPATH\fR. -+.TP -+--device-map=\fIFILE\fR -+Use \fIFILE\fR as the device map. The default value is \fI/boot/grub/device.map\fR. -+ -+.TP -+--target=(fs|fs_uuid|fs_label|drive|device|partmap|msdos_parttype) -+Select among various output definitions. The default is \fIfs\fR. -+.RS -+.TP -+\fIfs\fR -+filesystem module -+ -+.TP -+\fIfs_uuid\fR -+filesystem UUID -+ -+.TP -+\fIfs_label\fR -+filesystem label -+ -+.TP -+\fIdrive\fR -+GRUB drive name -+ -+.TP -+\fIdevice\fR -+System device -+ -+.TP -+\fIpartmap\fR -+partition map module -+ -+.TP -+\fIabstraction\fR -+abstraction module -+ -+.TP -+\fIcryptodisk_uuid\fR -+cryptographic container -+ -+.TP -+\fImsdos_partmap\fR -+MS-DOS partition map -+.RE -+ -+.TP -+--verbose -+Print verbose output. -+ -+.TP -+(\fIPATH\fR|\fIDEVICE\fR) -+If --device is passed, a block \fIDEVICE\fR. Otherwise, the \fIPATH\fR of a file on the filesystem. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-reboot.8 b/util/grub-reboot.8 -new file mode 100644 -index 00000000000..faa5e4eece2 ---- /dev/null -+++ b/util/grub-reboot.8 -@@ -0,0 +1,21 @@ -+.TH GRUB-REBOOT 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-reboot\fR \(em Set the default boot menu entry for the next boot only. -+ -+.SH SYNOPSIS -+\fBgrub-reboot\fR [--boot-directory=\fIDIR\fR] \fIMENU_ENTRY\fR -+ -+.SH DESCRIPTION -+\fBgrub-reboot\fR sets the default boot menu entry for the next boot, but not further boots after that. This command only works for GRUB configuration files created with \fIGRUB_DEFAULT=saved\fR in \fI/etc/default/grub\fR. -+ -+.SH OPTIONS -+.TP -+--boot-directory=\fIDIR\fR -+Find GRUB images under \fIDIR/grub\fR. The default value is \fI/boot\fR, resulting in grub images being search for at \fI/boot/grub\fR. -+ -+.TP -+\fIMENU_ENTRY\fR -+A number, a menu item title or a menu item identifier. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-render-label.1 b/util/grub-render-label.1 -new file mode 100644 -index 00000000000..4d51c8abf01 ---- /dev/null -+++ b/util/grub-render-label.1 -@@ -0,0 +1,51 @@ -+.TH GRUB-RENDER-LABEL 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-render-label\fR \(em Render an Apple disk label. -+ -+.SH SYNOPSIS -+\fBgrub-render-label\fR [-b | --bgcolor=\fICOLOR\fR] [-c | --color=\fICOLOR\fR] -+.RS 19 -+[-f | --font=\fIFILE\fR] [-i | --input=\fIFILE\fR] -+.RE -+.RS 19 -+[-o | --output=\fIFILE\fR] [-t | --text=\fISTRING\fR] -+.RE -+.RS 19 -+[-v | --verbose] -+ -+.SH DESCRIPTION -+\fBgrub-render-label\fR renders an Apple disk label (.disk_label) file. -+ -+ -+.SH OPTIONS -+.TP -+\fB--color\fR=\fICOLOR\fR -+Use \fICOLOR\fI as the color for generated labels. -+ -+.TP -+\fB--bgcolor\fR=\fICOLOR\fR -+Use \fICOLOR\fR as the background color for generated labels. -+ -+.TP -+\fB--font\fR=\fIFILE\fR -+Use \fIFILE\fR as the font file for generated labels. -+ -+.TP -+--input=\fIFILE\fR -+Read input text from \fIFILE\fR. -+ -+.TP -+--output=\fIFILE\fR -+Render output to \fIFILE\fR. -+ -+.TP -+--text=\fISTRING\fR -+Use \fISTRING\fR as input text. -+ -+.TP -+--verbose -+Print verbose output. -+ -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-script-check.1 b/util/grub-script-check.1 -new file mode 100644 -index 00000000000..0f1f625b05d ---- /dev/null -+++ b/util/grub-script-check.1 -@@ -0,0 +1,21 @@ -+.TH GRUB-SCRIPT-CHECK 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-script-check\fR \(em Check GRUB configuration file for syntax errors. -+ -+.SH SYNOPSIS -+\fBgrub-script-check\fR [-v | --verbose] \fIPATH\fR -+ -+.SH DESCRIPTION -+\fBgrub-script-check\fR verifies that a specified GRUB configuration file does not contain syntax errors. -+ -+.SH OPTIONS -+.TP -+--verbose -+Print verbose output. -+ -+.TP -+\fIPATH\fR -+Path of the file to use as input. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-set-default.8 b/util/grub-set-default.8 -new file mode 100644 -index 00000000000..a96265a1509 ---- /dev/null -+++ b/util/grub-set-default.8 -@@ -0,0 +1,21 @@ -+.TH GRUB-SET-DEFAULT 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-set-default\fR \(em Set the default boot menu entry for GRUB. -+ -+.SH SYNOPSIS -+\fBgrub-set-default\fR [--boot-directory=\fIDIR\fR] \fIMENU_ENTRY\fR -+ -+.SH DESCRIPTION -+\fBgrub-set-default\fR sets the default boot menu entry for all subsequent boots. This command only works for GRUB configuration files created with \fIGRUB_DEFAULT=saved\fR in \fI/etc/default/grub\fR. -+ -+.SH OPTIONS -+.TP -+--boot-directory=\fIDIR\fR -+Find GRUB images under \fIDIR/grub\fR. The default value is \fI/boot\fR, resulting in grub images being search for at \fI/boot/grub\fR. -+ -+.TP -+\fIMENU_ENTRY\fR -+A number, a menu item title or a menu item identifier. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-sparc64-setup.8 b/util/grub-sparc64-setup.8 -new file mode 100644 -index 00000000000..37ea2dd5eaa ---- /dev/null -+++ b/util/grub-sparc64-setup.8 -@@ -0,0 +1,12 @@ -+.TH GRUB-SPARC64-SETUP 3 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-sparc64-setup\fR \(em Set up a device to boot a sparc64 GRUB image. -+ -+.SH SYNOPSIS -+\fBgrub-sparc64-setup\fR [OPTIONS]. -+ -+.SH DESCRIPTION -+You should not normally run this program directly. Use grub-install instead. -+ -+.SH SEE ALSO -+.BR "info grub" diff --git a/SOURCES/0040-macos-just-build-chainloader-entries-don-t-try-any-x.patch b/SOURCES/0040-macos-just-build-chainloader-entries-don-t-try-any-x.patch new file mode 100644 index 0000000..8d3139d --- /dev/null +++ b/SOURCES/0040-macos-just-build-chainloader-entries-don-t-try-any-x.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 24 May 2017 12:42:32 -0400 +Subject: [PATCH] macos: just build chainloader entries, don't try any xnu xnu. + +Since our bugs tell us that the xnu boot entries really just don't work +most of the time, and they create piles of extra boot entries, because +they can't quite figure out 32-vs-64 and other stuff like that. + +It's rediculous, and we should just boot their bootloader through the +chainloader instead. + +So this patch does that. + +Resolves: rhbz#893179 + +Signed-off-by: Peter Jones +--- + util/grub.d/30_os-prober.in | 78 +++++++++++---------------------------------- + 1 file changed, 18 insertions(+), 60 deletions(-) + +diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in +index 1b91c102f3..4b27bd2015 100644 +--- a/util/grub.d/30_os-prober.in ++++ b/util/grub.d/30_os-prober.in +@@ -42,68 +42,25 @@ if [ -z "${OSPROBED}" ] ; then + fi + + osx_entry() { +- if [ x$2 = x32 ]; then +- # TRANSLATORS: it refers to kernel architecture (32-bit) +- bitstr="$(gettext "(32-bit)")" +- else +- # TRANSLATORS: it refers to kernel architecture (64-bit) +- bitstr="$(gettext "(64-bit)")" +- fi + # TRANSLATORS: it refers on the OS residing on device %s + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" +- cat << EOF +-menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' { ++ hints="" ++ for hint in `"${grub_probe}" --device ${device} --target=efi_hints 2> /dev/null` ; do ++ hints="${hints} --hint=${hint}" ++ done ++ cat << EOF ++menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' { + EOF + save_default_entry | grub_add_tab + prepare_grub_to_access_device ${DEVICE} | grub_add_tab + cat << EOF ++ set gfxpayload=keep + load_video +- set do_resume=0 +- if [ /var/vm/sleepimage -nt10 / ]; then +- if xnu_resume /var/vm/sleepimage; then +- set do_resume=1 +- fi +- fi +- if [ \$do_resume = 0 ]; then +- xnu_uuid ${OSXUUID} uuid +- if [ -f /Extra/DSDT.aml ]; then +- acpi -e /Extra/DSDT.aml +- fi +- if [ /kernelcache -nt /System/Library/Extensions ]; then +- $1 /kernelcache boot-uuid=\${uuid} rd=*uuid +- elif [ -f /System/Library/Kernels/kernel ]; then +- $1 /System/Library/Kernels/kernel boot-uuid=\${uuid} rd=*uuid +- xnu_kextdir /System/Library/Extensions +- else +- $1 /mach_kernel boot-uuid=\${uuid} rd=*uuid +- if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then +- xnu_mkext /System/Library/Extensions.mkext +- else +- xnu_kextdir /System/Library/Extensions +- fi +- fi +- if [ -f /Extra/Extensions.mkext ]; then +- xnu_mkext /Extra/Extensions.mkext +- fi +- if [ -d /Extra/Extensions ]; then +- xnu_kextdir /Extra/Extensions +- fi +- if [ -f /Extra/devprop.bin ]; then +- xnu_devprop_load /Extra/devprop.bin +- fi +- if [ -f /Extra/splash.jpg ]; then +- insmod jpeg +- xnu_splash /Extra/splash.jpg +- fi +- if [ -f /Extra/splash.png ]; then +- insmod png +- xnu_splash /Extra/splash.png +- fi +- if [ -f /Extra/splash.tga ]; then +- insmod tga +- xnu_splash /Extra/splash.tga +- fi +- fi ++ insmod part_gpt ++ insmod hfsplus ++ search --no-floppy --fs-uuid --set=root ${hints} $(grub_get_device_id "${DEVICE}") ++ chainloader (\$root)/System/Library/CoreServices/boot.efi ++ boot + } + EOF + } +@@ -292,11 +249,12 @@ EOF + echo "$title_correction_code" + ;; + macosx) +- if [ "${UUID}" ]; then +- OSXUUID="${UUID}" +- osx_entry xnu_kernel 32 +- osx_entry xnu_kernel64 64 +- fi ++ for subdevice in ${DEVICE%[[:digit:]]*}* ; do ++ parttype="`"${grub_probe}" --device ${device} --target=gpt_parttype "${subdevice}" 2> /dev/null`" ++ if [[ "$parttype" = "426f6f74-0000-11aa-aa11-00306543ecac" ]]; then ++ DEVICE="${subdevice}" osx_entry ++ fi ++ done + ;; + hurd) + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" diff --git a/SOURCES/0041-grub2-btrfs-Add-ability-to-boot-from-subvolumes.patch b/SOURCES/0041-grub2-btrfs-Add-ability-to-boot-from-subvolumes.patch new file mode 100644 index 0000000..57d2391 --- /dev/null +++ b/SOURCES/0041-grub2-btrfs-Add-ability-to-boot-from-subvolumes.patch @@ -0,0 +1,703 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jeff Mahoney +Date: Tue, 9 Jul 2019 13:39:45 +0200 +Subject: [PATCH] grub2/btrfs: Add ability to boot from subvolumes + +This patch adds the ability to specify a different root on a btrfs +filesystem too boot from other than the default one. + +btrfs-list-snapshots will list the subvolumes available on the +filesystem. + +set btrfs_subvol= and set btrfs_subvolid= will specify +which subvolume to use and any pathnames provided with either of those +variables set will start using that root. If the subvolume or subvolume id +doesn't exist, then an error case will result. + +It is possible to boot into a separate GRUB instance by exporting the +variable and loading the config file from the subvolume. + +Signed-off-by: Jeff Mahoney +--- + grub-core/fs/btrfs.c | 552 +++++++++++++++++++++++++++++++++++++++++++++++++-- + include/grub/btrfs.h | 1 + + 2 files changed, 533 insertions(+), 20 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 63203034df..f1fff7385b 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -38,6 +38,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -79,9 +82,11 @@ struct grub_btrfs_superblock + grub_uint64_t generation; + grub_uint64_t root_tree; + grub_uint64_t chunk_tree; +- grub_uint8_t dummy2[0x20]; ++ grub_uint8_t dummy2[0x18]; ++ grub_uint64_t bytes_used; + grub_uint64_t root_dir_objectid; +- grub_uint8_t dummy3[0x41]; ++ grub_uint64_t num_devices; ++ grub_uint8_t dummy3[0x39]; + struct grub_btrfs_device this_device; + char label[0x100]; + grub_uint8_t dummy4[0x100]; +@@ -121,6 +126,7 @@ struct grub_btrfs_data + grub_uint64_t exttree; + grub_size_t extsize; + struct grub_btrfs_extent_data *extent; ++ grub_uint64_t fs_tree; + }; + + struct grub_btrfs_chunk_item +@@ -191,6 +197,14 @@ struct grub_btrfs_leaf_descriptor + } *data; + }; + ++struct grub_btrfs_root_ref ++{ ++ grub_uint64_t dirid; ++ grub_uint64_t sequence; ++ grub_uint16_t name_len; ++ const char name[0]; ++} __attribute__ ((packed)); ++ + struct grub_btrfs_time + { + grub_int64_t sec; +@@ -236,6 +250,14 @@ struct grub_btrfs_extent_data + + #define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100 + ++#define GRUB_BTRFS_ROOT_TREE_OBJECTID 1ULL ++#define GRUB_BTRFS_FS_TREE_OBJECTID 5ULL ++#define GRUB_BTRFS_ROOT_REF_KEY 156 ++#define GRUB_BTRFS_ROOT_ITEM_KEY 132 ++ ++static grub_uint64_t btrfs_default_subvolid = 0; ++static char *btrfs_default_subvol = NULL; ++ + static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2, + 256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2 + }; +@@ -1173,6 +1195,62 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + return GRUB_ERR_NONE; + } + ++static grub_err_t ++get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree, ++ grub_uint64_t objectid, grub_uint64_t offset, ++ grub_uint64_t *fs_root); ++ ++static grub_err_t ++lookup_root_by_id(struct grub_btrfs_data *data, grub_uint64_t id) ++{ ++ grub_err_t err; ++ grub_uint64_t tree; ++ ++ err = get_fs_root(data, data->sblock.root_tree, id, -1, &tree); ++ if (!err) ++ data->fs_tree = tree; ++ return err; ++} ++ ++static grub_err_t ++find_path (struct grub_btrfs_data *data, ++ const char *path, struct grub_btrfs_key *key, ++ grub_uint64_t *tree, grub_uint8_t *type); ++ ++static grub_err_t ++lookup_root_by_name(struct grub_btrfs_data *data, const char *path) ++{ ++ grub_err_t err; ++ grub_uint64_t tree = 0; ++ grub_uint8_t type; ++ struct grub_btrfs_key key; ++ ++ err = find_path (data, path, &key, &tree, &type); ++ if (err) ++ return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path); ++ ++ if (key.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0) ++ return grub_error(GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", path); ++ ++ data->fs_tree = tree; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++btrfs_handle_subvol(struct grub_btrfs_data *data __attribute__ ((unused))) ++{ ++ if (btrfs_default_subvol) ++ return lookup_root_by_name(data, btrfs_default_subvol); ++ ++ if (btrfs_default_subvolid) ++ return lookup_root_by_id(data, btrfs_default_subvolid); ++ ++ data->fs_tree = 0; ++ ++ return GRUB_ERR_NONE; ++} ++ ++ + static struct grub_btrfs_data * + grub_btrfs_mount (grub_device_t dev) + { +@@ -1208,6 +1286,13 @@ grub_btrfs_mount (grub_device_t dev) + data->devices_attached[0].dev = dev; + data->devices_attached[0].id = data->sblock.this_device.device_id; + ++ err = btrfs_handle_subvol (data); ++ if (err) ++ { ++ grub_free (data); ++ return NULL; ++ } ++ + return data; + } + +@@ -1673,6 +1758,91 @@ get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key, + return GRUB_ERR_NONE; + } + ++static grub_err_t ++find_pathname(struct grub_btrfs_data *data, grub_uint64_t objectid, ++ grub_uint64_t fs_root, const char *name, char **pathname) ++{ ++ grub_err_t err; ++ struct grub_btrfs_key key = { ++ .object_id = objectid, ++ .type = GRUB_BTRFS_ITEM_TYPE_INODE_REF, ++ .offset = 0, ++ }; ++ struct grub_btrfs_key key_out; ++ struct grub_btrfs_leaf_descriptor desc; ++ char *p = grub_strdup (name); ++ grub_disk_addr_t elemaddr; ++ grub_size_t elemsize; ++ grub_size_t alloc = grub_strlen(name) + 1; ++ ++ err = lower_bound(data, &key, &key_out, fs_root, ++ &elemaddr, &elemsize, &desc, 0); ++ if (err) ++ return grub_error(err, "lower_bound caught %d\n", err); ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF) ++ next(data, &desc, &elemaddr, &elemsize, &key_out); ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF) ++ { ++ return grub_error(GRUB_ERR_FILE_NOT_FOUND, ++ "Can't find inode ref for {%"PRIuGRUB_UINT64_T ++ ", %u, %"PRIuGRUB_UINT64_T"} %"PRIuGRUB_UINT64_T ++ "/%"PRIuGRUB_SIZE"\n", ++ key_out.object_id, key_out.type, ++ key_out.offset, elemaddr, elemsize); ++ } ++ ++ ++ while (key_out.type == GRUB_BTRFS_ITEM_TYPE_INODE_REF && ++ key_out.object_id != key_out.offset) { ++ struct grub_btrfs_inode_ref *inode_ref; ++ char *new; ++ ++ inode_ref = grub_malloc(elemsize + 1); ++ if (!inode_ref) ++ return grub_error(GRUB_ERR_OUT_OF_MEMORY, ++ "couldn't allocate memory for inode_ref (%"PRIuGRUB_SIZE")\n", elemsize); ++ ++ err = grub_btrfs_read_logical(data, elemaddr, inode_ref, elemsize, 0); ++ if (err) ++ return grub_error(err, "read_logical caught %d\n", err); ++ ++ alloc += grub_le_to_cpu16 (inode_ref->n) + 2; ++ new = grub_malloc(alloc); ++ if (!new) ++ return grub_error(GRUB_ERR_OUT_OF_MEMORY, ++ "couldn't allocate memory for name (%"PRIuGRUB_SIZE")\n", alloc); ++ ++ grub_memcpy(new, inode_ref->name, grub_le_to_cpu16 (inode_ref->n)); ++ if (p) ++ { ++ new[grub_le_to_cpu16 (inode_ref->n)] = '/'; ++ grub_strcpy (new + grub_le_to_cpu16 (inode_ref->n) + 1, p); ++ grub_free(p); ++ } ++ else ++ new[grub_le_to_cpu16 (inode_ref->n)] = 0; ++ grub_free(inode_ref); ++ ++ p = new; ++ ++ key.object_id = key_out.offset; ++ ++ err = lower_bound(data, &key, &key_out, fs_root, &elemaddr, ++ &elemsize, &desc, 0); ++ if (err) ++ return grub_error(err, "lower_bound caught %d\n", err); ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF) ++ next(data, &desc, &elemaddr, &elemsize, &key_out); ++ ++ } ++ ++ *pathname = p; ++ return 0; ++} ++ + static grub_err_t + find_path (struct grub_btrfs_data *data, + const char *path, struct grub_btrfs_key *key, +@@ -1691,14 +1861,26 @@ find_path (struct grub_btrfs_data *data, + char *origpath = NULL; + unsigned symlinks_max = 32; + +- err = get_root (data, key, tree, type); +- if (err) +- return err; +- + origpath = grub_strdup (path); + if (!origpath) + return grub_errno; + ++ if (data->fs_tree) ++ { ++ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; ++ *tree = data->fs_tree; ++ /* This is a tree root, so everything starts at objectid 256 */ ++ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); ++ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key->offset = 0; ++ } ++ else ++ { ++ err = get_root (data, key, tree, type); ++ if (err) ++ return err; ++ } ++ + while (1) + { + while (path[0] == '/') +@@ -1871,9 +2053,21 @@ find_path (struct grub_btrfs_data *data, + path = path_alloc = tmp; + if (path[0] == '/') + { +- err = get_root (data, key, tree, type); +- if (err) +- return err; ++ if (data->fs_tree) ++ { ++ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; ++ *tree = data->fs_tree; ++ /* This is a tree root, so everything starts at objectid 256 */ ++ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); ++ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key->offset = 0; ++ } ++ else ++ { ++ err = get_root (data, key, tree, type); ++ if (err) ++ return err; ++ } + } + continue; + } +@@ -2114,18 +2308,10 @@ grub_btrfs_read (grub_file_t file, char *buf, grub_size_t len) + data->tree, file->offset, buf, len); + } + +-static grub_err_t +-grub_btrfs_uuid (grub_device_t device, char **uuid) ++static char * ++btrfs_unparse_uuid(struct grub_btrfs_data *data) + { +- struct grub_btrfs_data *data; +- +- *uuid = NULL; +- +- data = grub_btrfs_mount (device); +- if (!data) +- return grub_errno; +- +- *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", ++ return grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->sblock.uuid[0]), + grub_be_to_cpu16 (data->sblock.uuid[1]), + grub_be_to_cpu16 (data->sblock.uuid[2]), +@@ -2134,6 +2320,20 @@ grub_btrfs_uuid (grub_device_t device, char **uuid) + grub_be_to_cpu16 (data->sblock.uuid[5]), + grub_be_to_cpu16 (data->sblock.uuid[6]), + grub_be_to_cpu16 (data->sblock.uuid[7])); ++} ++ ++static grub_err_t ++grub_btrfs_uuid (grub_device_t device, char **uuid) ++{ ++ struct grub_btrfs_data *data; ++ ++ *uuid = NULL; ++ ++ data = grub_btrfs_mount (device); ++ if (!data) ++ return grub_errno; ++ ++ *uuid = btrfs_unparse_uuid(data); + + grub_btrfs_unmount (data); + +@@ -2190,6 +2390,242 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), + } + #endif + ++static grub_err_t ++grub_cmd_btrfs_info (grub_command_t cmd __attribute__ ((unused)), int argc, ++ char **argv) ++{ ++ grub_device_t dev; ++ char *devname; ++ struct grub_btrfs_data *data; ++ char *uuid; ++ ++ if (argc < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); ++ ++ devname = grub_file_get_device_name(argv[0]); ++ ++ if (!devname) ++ return grub_errno; ++ ++ dev = grub_device_open (devname); ++ grub_free (devname); ++ if (!dev) ++ return grub_errno; ++ ++ data = grub_btrfs_mount (dev); ++ if (!data) ++ { ++ grub_device_close(dev); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to open fs"); ++ } ++ ++ if (data->sblock.label) ++ grub_printf("Label: '%s' ", data->sblock.label); ++ else ++ grub_printf("Label: none "); ++ ++ uuid = btrfs_unparse_uuid(data); ++ ++ grub_printf(" uuid: %s\n\tTotal devices %" PRIuGRUB_UINT64_T ++ " FS bytes used %" PRIuGRUB_UINT64_T "\n", ++ uuid, grub_cpu_to_le64(data->sblock.num_devices), ++ grub_cpu_to_le64(data->sblock.bytes_used)); ++ ++ grub_btrfs_unmount (data); ++ ++ return 0; ++} ++ ++static grub_err_t ++get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree, ++ grub_uint64_t objectid, grub_uint64_t offset, ++ grub_uint64_t *fs_root) ++{ ++ grub_err_t err; ++ struct grub_btrfs_key key_in = { ++ .object_id = objectid, ++ .type = GRUB_BTRFS_ROOT_ITEM_KEY, ++ .offset = offset, ++ }, key_out; ++ struct grub_btrfs_leaf_descriptor desc; ++ grub_disk_addr_t elemaddr; ++ grub_size_t elemsize; ++ struct grub_btrfs_root_item ri; ++ ++ err = lower_bound(data, &key_in, &key_out, tree, ++ &elemaddr, &elemsize, &desc, 0); ++ ++ if (err) ++ return err; ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM || elemaddr == 0) ++ return grub_error(GRUB_ERR_FILE_NOT_FOUND, ++ N_("can't find fs root for subvol %"PRIuGRUB_UINT64_T"\n"), ++ key_in.object_id); ++ ++ err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri), 0); ++ if (err) ++ return err; ++ ++ *fs_root = ri.tree; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static const struct grub_arg_option options[] = { ++ {"output", 'o', 0, N_("Output to a variable instead of the console."), ++ N_("VARNAME"), ARG_TYPE_STRING}, ++ {"path-only", 'p', 0, N_("Show only the path of the subvolume."), 0, 0}, ++ {"id-only", 'i', 0, N_("Show only the id of the subvolume."), 0, 0}, ++ {0, 0, 0, 0, 0, 0} ++}; ++ ++static grub_err_t ++grub_cmd_btrfs_list_subvols (struct grub_extcmd_context *ctxt, ++ int argc, char **argv) ++{ ++ struct grub_btrfs_data *data; ++ grub_device_t dev; ++ char *devname; ++ grub_uint64_t tree; ++ struct grub_btrfs_key key_in = { ++ .object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_FS_TREE_OBJECTID), ++ .type = GRUB_BTRFS_ROOT_REF_KEY, ++ .offset = 0, ++ }, key_out; ++ struct grub_btrfs_leaf_descriptor desc; ++ grub_disk_addr_t elemaddr; ++ grub_uint64_t fs_root = 0; ++ grub_size_t elemsize; ++ grub_size_t allocated = 0; ++ int r = 0; ++ grub_err_t err; ++ char *buf = NULL; ++ int print = 1; ++ int path_only = ctxt->state[1].set; ++ int num_only = ctxt->state[2].set; ++ char *varname = NULL; ++ char *output = NULL; ++ ++ if (ctxt->state[0].set) { ++ varname = ctxt->state[0].arg; ++ print = 0; ++ } ++ ++ if (argc < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); ++ ++ devname = grub_file_get_device_name(argv[0]); ++ if (!devname) ++ return grub_errno; ++ ++ dev = grub_device_open (devname); ++ grub_free (devname); ++ if (!dev) ++ return grub_errno; ++ ++ data = grub_btrfs_mount(dev); ++ if (!data) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "could not open device"); ++ ++ tree = data->sblock.root_tree; ++ err = get_fs_root(data, tree, grub_cpu_to_le64_compile_time (GRUB_BTRFS_FS_TREE_OBJECTID), ++ 0, &fs_root); ++ if (err) ++ goto out; ++ ++ err = lower_bound(data, &key_in, &key_out, tree, ++ &elemaddr, &elemsize, &desc, 0); ++ ++ if (err) ++ { ++ grub_btrfs_unmount(data); ++ return err; ++ } ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF || elemaddr == 0) ++ { ++ r = next(data, &desc, &elemaddr, &elemsize, &key_out); ++ } ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF) { ++ err = GRUB_ERR_FILE_NOT_FOUND; ++ grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("can't find root refs")); ++ goto out; ++ } ++ ++ do ++ { ++ struct grub_btrfs_root_ref *ref; ++ char *p = NULL; ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF) ++ { ++ r = 0; ++ break; ++ } ++ ++ if (elemsize > allocated) ++ { ++ grub_free(buf); ++ allocated = 2 * elemsize; ++ buf = grub_malloc(allocated + 1); ++ if (!buf) ++ { ++ r = -grub_errno; ++ break; ++ } ++ } ++ ref = (struct grub_btrfs_root_ref *)buf; ++ ++ err = grub_btrfs_read_logical(data, elemaddr, buf, elemsize, 0); ++ if (err) ++ { ++ r = -err; ++ break; ++ } ++ buf[elemsize] = 0; ++ ++ find_pathname(data, ref->dirid, fs_root, ref->name, &p); ++ ++ if (print) ++ { ++ if (num_only) ++ grub_printf("ID %"PRIuGRUB_UINT64_T"\n", key_out.offset); ++ else if (path_only) ++ grub_printf("%s\n", p); ++ else ++ grub_printf("ID %"PRIuGRUB_UINT64_T" path %s\n", key_out.offset, p); ++ } else { ++ char *old = output; ++ if (num_only) ++ output = grub_xasprintf("%s%"PRIuGRUB_UINT64_T"\n", ++ old ?: "", key_out.offset); ++ else if (path_only) ++ output = grub_xasprintf("%s%s\n", old ?: "", p); ++ else ++ output = grub_xasprintf("%sID %"PRIuGRUB_UINT64_T" path %s\n", ++ old ?: "", key_out.offset, p); ++ ++ if (old) ++ grub_free(old); ++ } ++ ++ r = next(data, &desc, &elemaddr, &elemsize, &key_out); ++ } while(r > 0); ++ ++ if (output) ++ grub_env_set(varname, output); ++ ++out: ++ free_iterator(&desc); ++ grub_btrfs_unmount(data); ++ ++ grub_device_close (dev); ++ ++ return 0; ++} ++ + static struct grub_fs grub_btrfs_fs = { + .name = "btrfs", + .fs_dir = grub_btrfs_dir, +@@ -2205,12 +2641,88 @@ static struct grub_fs grub_btrfs_fs = { + #endif + }; + ++static grub_command_t cmd_info; ++static grub_extcmd_t cmd_list_subvols; ++ ++static char * ++subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val) ++{ ++ unsigned long long result = 0; ++ ++ grub_errno = GRUB_ERR_NONE; ++ if (*val) ++ { ++ result = grub_strtoull(val, NULL, 10); ++ if (grub_errno) ++ return NULL; ++ } ++ ++ grub_free (btrfs_default_subvol); ++ btrfs_default_subvol = NULL; ++ btrfs_default_subvolid = result; ++ return grub_strdup(val); ++} ++ ++static const char * ++subvolid_get_env (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ if (btrfs_default_subvol) ++ return grub_xasprintf("subvol:%s", btrfs_default_subvol); ++ else if (btrfs_default_subvolid) ++ return grub_xasprintf("%"PRIuGRUB_UINT64_T, btrfs_default_subvolid); ++ else ++ return ""; ++} ++ ++static char * ++subvol_set_env (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val) ++{ ++ grub_free (btrfs_default_subvol); ++ btrfs_default_subvol = grub_strdup (val); ++ btrfs_default_subvolid = 0; ++ return grub_strdup(val); ++} ++ ++static const char * ++subvol_get_env (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ if (btrfs_default_subvol) ++ return btrfs_default_subvol; ++ else if (btrfs_default_subvolid) ++ return grub_xasprintf("subvolid:%" PRIuGRUB_UINT64_T, ++ btrfs_default_subvolid); ++ else ++ return ""; ++} ++ + GRUB_MOD_INIT (btrfs) + { + grub_fs_register (&grub_btrfs_fs); ++ cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info, ++ "DEVICE", ++ "Print BtrFS info about DEVICE."); ++ cmd_list_subvols = grub_register_extcmd("btrfs-list-subvols", ++ grub_cmd_btrfs_list_subvols, 0, ++ "[-p|-n] [-o var] DEVICE", ++ "Print list of BtrFS subvolumes on " ++ "DEVICE.", options); ++ grub_register_variable_hook ("btrfs_subvol", subvol_get_env, ++ subvol_set_env); ++ grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env, ++ subvolid_set_env); + } + + GRUB_MOD_FINI (btrfs) + { ++ grub_register_variable_hook ("btrfs_subvol", NULL, NULL); ++ grub_register_variable_hook ("btrfs_subvolid", NULL, NULL); ++ grub_unregister_command (cmd_info); ++ grub_unregister_extcmd (cmd_list_subvols); + grub_fs_unregister (&grub_btrfs_fs); + } ++ ++// vim: si et sw=2: +diff --git a/include/grub/btrfs.h b/include/grub/btrfs.h +index 9d93fb6c18..234ad97677 100644 +--- a/include/grub/btrfs.h ++++ b/include/grub/btrfs.h +@@ -29,6 +29,7 @@ enum + GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM = 0x84, + GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF = 0x90, + GRUB_BTRFS_ITEM_TYPE_DEVICE = 0xd8, ++ GRUB_BTRFS_ITEM_TYPE_ROOT_REF = 0x9c, + GRUB_BTRFS_ITEM_TYPE_CHUNK = 0xe4 + }; + diff --git a/SOURCES/0041-use-fw_path-prefix-when-fallback-searching-for-grub-.patch b/SOURCES/0041-use-fw_path-prefix-when-fallback-searching-for-grub-.patch deleted file mode 100644 index 985205c..0000000 --- a/SOURCES/0041-use-fw_path-prefix-when-fallback-searching-for-grub-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Fedora Ninjas -Date: Wed, 19 Feb 2014 15:58:43 -0500 -Subject: [PATCH] use fw_path prefix when fallback searching for grub config - -When PXE booting via UEFI firmware, grub was searching for grub.cfg -in the fw_path directory where the grub application was found. If -that didn't exist, a fallback search would look for config file names -based on MAC and IP address. However, the search would look in the -prefix directory which may not be the same fw_path. This patch -changes that behavior to use the fw_path directory for the fallback -search. Only if fw_path is NULL will the prefix directory be searched. - -Signed-off-by: Mark Salter ---- - grub-core/normal/main.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index ec1cd257397..d85f7598d23 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -349,7 +349,7 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), - char *config; - const char *prefix, *fw_path; - -- fw_path = grub_env_get ("fw_path"); -+ prefix = fw_path = grub_env_get ("fw_path"); - if (fw_path) - { - config = grub_xasprintf ("%s/grub.cfg", fw_path); -@@ -372,7 +372,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), - } - } - -- prefix = grub_env_get ("prefix"); -+ if (! prefix) -+ prefix = grub_env_get ("prefix"); - if (prefix) - { - grub_size_t config_len; diff --git a/SOURCES/0042-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch b/SOURCES/0042-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch deleted file mode 100644 index 61dd5ca..0000000 --- a/SOURCES/0042-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 8 Jul 2019 17:33:22 +0200 -Subject: [PATCH] Try mac/guid/etc before grub.cfg on tftp config files. - -Signed-off-by: Peter Jones ---- - grub-core/normal/main.c | 97 ++++++++++++++++++++++++++----------------------- - 1 file changed, 51 insertions(+), 46 deletions(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index d85f7598d23..1e509fceb91 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -347,61 +347,66 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), - /* Guess the config filename. It is necessary to make CONFIG static, - so that it won't get broken by longjmp. */ - char *config; -- const char *prefix, *fw_path; -- -- prefix = fw_path = grub_env_get ("fw_path"); -- if (fw_path) -- { -- config = grub_xasprintf ("%s/grub.cfg", fw_path); -- if (config) -- { -- grub_file_t file; -- -- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); -- if (file) -- { -- grub_file_close (file); -- grub_enter_normal_mode (config); -- } -- else -- { -- /* Ignore all errors. */ -- grub_errno = 0; -- } -- grub_free (config); -- } -- } -+ const char *prefix; -+ const char *net_search_cfg; -+ int disable_net_search = 0; - -+ prefix = grub_env_get ("fw_path"); - if (! prefix) - prefix = grub_env_get ("prefix"); -+ -+ net_search_cfg = grub_env_get ("feature_net_search_cfg"); -+ if (net_search_cfg && net_search_cfg[0] == 'n') -+ disable_net_search = 1; -+ - if (prefix) - { -- grub_size_t config_len; -- int disable_net_search = 0; -- const char *net_search_cfg; -- -- config_len = grub_strlen (prefix) + -- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); -- config = grub_malloc (config_len); -- -- if (!config) -- goto quit; -- -- grub_snprintf (config, config_len, "%s/grub.cfg", prefix); -- -- net_search_cfg = grub_env_get ("feature_net_search_cfg"); -- if (net_search_cfg && net_search_cfg[0] == 'n') -- disable_net_search = 1; -- - if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 && - !disable_net_search) -- grub_net_search_config_file (config); -+ { -+ grub_size_t config_len; -+ config_len = grub_strlen (prefix) + -+ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); -+ config = grub_malloc (config_len); - -- grub_enter_normal_mode (config); -- grub_free (config); -- } -+ if (! config) -+ goto quit; -+ -+ grub_snprintf (config, config_len, "%s/grub.cfg", prefix); -+ -+ grub_net_search_configfile (config); -+ -+ grub_enter_normal_mode (config); -+ grub_free (config); -+ config = NULL; -+ } -+ -+ if (!config) -+ { -+ config = grub_xasprintf ("%s/grub.cfg", prefix); -+ if (config) -+ { -+ grub_file_t file; -+ -+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); -+ if (file) -+ { -+ grub_file_close (file); -+ grub_enter_normal_mode (config); -+ } -+ else -+ { -+ /* Ignore all errors. */ -+ grub_errno = 0; -+ } -+ grub_free (config); -+ } -+ } -+ } - else -- grub_enter_normal_mode (0); -+ { -+ grub_enter_normal_mode (0); -+ } - } - else - grub_enter_normal_mode (argv[0]); diff --git a/SOURCES/0042-export-btrfs_subvol-and-btrfs_subvolid.patch b/SOURCES/0042-export-btrfs_subvol-and-btrfs_subvolid.patch new file mode 100644 index 0000000..719866e --- /dev/null +++ b/SOURCES/0042-export-btrfs_subvol-and-btrfs_subvolid.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 18 Dec 2013 09:57:04 +0000 +Subject: [PATCH] export btrfs_subvol and btrfs_subvolid + +We should export btrfs_subvol and btrfs_subvolid to have both visible +to subsidiary configuration files loaded using configfile. + +Signed-off-by: Michael Chang +--- + grub-core/fs/btrfs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index f1fff7385b..ad1b56b716 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -2714,6 +2714,8 @@ GRUB_MOD_INIT (btrfs) + subvol_set_env); + grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env, + subvolid_set_env); ++ grub_env_export ("btrfs_subvol"); ++ grub_env_export ("btrfs_subvolid"); + } + + GRUB_MOD_FINI (btrfs) diff --git a/SOURCES/0043-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch b/SOURCES/0043-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch deleted file mode 100644 index ef0b0f4..0000000 --- a/SOURCES/0043-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 4 Sep 2014 14:23:23 -0400 -Subject: [PATCH] Generate OS and CLASS in 10_linux from /etc/os-release - -This makes us use pretty names in the titles we generate in -grub2-mkconfig when GRUB_DISTRIBUTOR isn't set. - -Resolves: rhbz#996794 - -Signed-off-by: Peter Jones ---- - util/grub.d/10_linux.in | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 635d2fe0cd3..fed73271478 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -29,7 +29,8 @@ export TEXTDOMAINDIR="@localedir@" - CLASS="--class gnu-linux --class gnu --class os --unrestricted" - - if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then -- OS="$(sed 's, release .*$,,g' /etc/system-release)" -+ OS="$(eval $(grep PRETTY_NAME /etc/os-release) ; echo ${PRETTY_NAME})" -+ CLASS="--class $(eval $(grep '^ID_LIKE=\|^ID=' /etc/os-release) ; [ -n "${ID_LIKE}" ] && echo ${ID_LIKE} || echo ${ID}) ${CLASS}" - else - OS="${GRUB_DISTRIBUTOR}" - CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" diff --git a/SOURCES/0043-grub2-btrfs-03-follow_default.patch b/SOURCES/0043-grub2-btrfs-03-follow_default.patch new file mode 100644 index 0000000..621f029 --- /dev/null +++ b/SOURCES/0043-grub2-btrfs-03-follow_default.patch @@ -0,0 +1,198 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 21 Aug 2014 03:39:11 +0000 +Subject: [PATCH] grub2-btrfs-03-follow_default + +Signed-off-by: Michael Chang +Signed-off-by: Robbie Harwood +--- + grub-core/fs/btrfs.c | 107 ++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 76 insertions(+), 31 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index ad1b56b716..113c1f746c 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -1256,6 +1256,7 @@ grub_btrfs_mount (grub_device_t dev) + { + struct grub_btrfs_data *data; + grub_err_t err; ++ const char *relpath = grub_env_get ("btrfs_relative_path"); + + if (!dev->disk) + { +@@ -1286,11 +1287,14 @@ grub_btrfs_mount (grub_device_t dev) + data->devices_attached[0].dev = dev; + data->devices_attached[0].id = data->sblock.this_device.device_id; + +- err = btrfs_handle_subvol (data); +- if (err) ++ if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) + { +- grub_free (data); +- return NULL; ++ err = btrfs_handle_subvol (data); ++ if (err) ++ { ++ grub_free (data); ++ return NULL; ++ } + } + + return data; +@@ -1855,24 +1859,39 @@ find_path (struct grub_btrfs_data *data, + grub_size_t allocated = 0; + struct grub_btrfs_dir_item *direl = NULL; + struct grub_btrfs_key key_out; ++ int follow_default; + const char *ctoken; + grub_size_t ctokenlen; + char *path_alloc = NULL; + char *origpath = NULL; + unsigned symlinks_max = 32; ++ const char *relpath = grub_env_get ("btrfs_relative_path"); + ++ follow_default = 0; + origpath = grub_strdup (path); + if (!origpath) + return grub_errno; + +- if (data->fs_tree) ++ if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) + { +- *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; +- *tree = data->fs_tree; +- /* This is a tree root, so everything starts at objectid 256 */ +- key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); +- key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; +- key->offset = 0; ++ if (data->fs_tree) ++ { ++ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; ++ *tree = data->fs_tree; ++ /* This is a tree root, so everything starts at objectid 256 */ ++ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); ++ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key->offset = 0; ++ } ++ else ++ { ++ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; ++ *tree = data->sblock.root_tree; ++ key->object_id = data->sblock.root_dir_objectid; ++ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key->offset = 0; ++ follow_default = 1; ++ } + } + else + { +@@ -1883,15 +1902,23 @@ find_path (struct grub_btrfs_data *data, + + while (1) + { +- while (path[0] == '/') +- path++; +- if (!path[0]) +- break; +- slash = grub_strchr (path, '/'); +- if (!slash) +- slash = path + grub_strlen (path); +- ctoken = path; +- ctokenlen = slash - path; ++ if (!follow_default) ++ { ++ while (path[0] == '/') ++ path++; ++ if (!path[0]) ++ break; ++ slash = grub_strchr (path, '/'); ++ if (!slash) ++ slash = path + grub_strlen (path); ++ ctoken = path; ++ ctokenlen = slash - path; ++ } ++ else ++ { ++ ctoken = "default"; ++ ctokenlen = sizeof ("default") - 1; ++ } + + if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) + { +@@ -1902,7 +1929,9 @@ find_path (struct grub_btrfs_data *data, + + if (ctokenlen == 1 && ctoken[0] == '.') + { +- path = slash; ++ if (!follow_default) ++ path = slash; ++ follow_default = 0; + continue; + } + if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.') +@@ -1933,8 +1962,9 @@ find_path (struct grub_btrfs_data *data, + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + key->object_id = key_out.offset; + +- path = slash; +- ++ if (!follow_default) ++ path = slash; ++ follow_default = 0; + continue; + } + +@@ -2003,7 +2033,9 @@ find_path (struct grub_btrfs_data *data, + return err; + } + +- path = slash; ++ if (!follow_default) ++ path = slash; ++ follow_default = 0; + if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK) + { + struct grub_btrfs_inode inode; +@@ -2053,14 +2085,26 @@ find_path (struct grub_btrfs_data *data, + path = path_alloc = tmp; + if (path[0] == '/') + { +- if (data->fs_tree) ++ if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) + { +- *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; +- *tree = data->fs_tree; +- /* This is a tree root, so everything starts at objectid 256 */ +- key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); +- key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; +- key->offset = 0; ++ if (data->fs_tree) ++ { ++ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; ++ *tree = data->fs_tree; ++ /* This is a tree root, so everything starts at objectid 256 */ ++ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); ++ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key->offset = 0; ++ } ++ else ++ { ++ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; ++ *tree = data->sblock.root_tree; ++ key->object_id = data->sblock.root_dir_objectid; ++ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key->offset = 0; ++ follow_default = 1; ++ } + } + else + { +@@ -2716,6 +2760,7 @@ GRUB_MOD_INIT (btrfs) + subvolid_set_env); + grub_env_export ("btrfs_subvol"); + grub_env_export ("btrfs_subvolid"); ++ grub_env_export ("btrfs_relative_path"); + } + + GRUB_MOD_FINI (btrfs) diff --git a/SOURCES/0044-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch b/SOURCES/0044-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch deleted file mode 100644 index 3e2d3ae..0000000 --- a/SOURCES/0044-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 4 Sep 2014 15:52:08 -0400 -Subject: [PATCH] Minimize the sort ordering for .debug and -rescue- kernels. - -Resolves: rhbz#1065360 -Signed-off-by: Peter Jones ---- - util/grub-mkconfig_lib.in | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in -index 301d1ac229a..0f6505bf3b6 100644 ---- a/util/grub-mkconfig_lib.in -+++ b/util/grub-mkconfig_lib.in -@@ -253,6 +253,14 @@ version_test_gt () - *.old:*.old) ;; - *.old:*) version_test_gt_a="`echo "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;; - *:*.old) version_test_gt_b="`echo "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;; -+ *-rescue*:*-rescue*) ;; -+ *?debug:*?debug) ;; -+ *-rescue*:*?debug) return 1 ;; -+ *?debug:*-rescue*) return 0 ;; -+ *-rescue*:*) return 1 ;; -+ *:*-rescue*) return 0 ;; -+ *?debug:*) return 1 ;; -+ *:*?debug) return 0 ;; - esac - version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b" - return "$?" diff --git a/SOURCES/0044-grub2-btrfs-04-grub2-install.patch b/SOURCES/0044-grub2-btrfs-04-grub2-install.patch new file mode 100644 index 0000000..6b2bc78 --- /dev/null +++ b/SOURCES/0044-grub2-btrfs-04-grub2-install.patch @@ -0,0 +1,176 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 21 Aug 2014 03:39:11 +0000 +Subject: [PATCH] grub2-btrfs-04-grub2-install + +Signed-off-by: Michael Chang +Signed-off-by: Robbie Harwood +--- + grub-core/osdep/linux/getroot.c | 7 +++++++ + grub-core/osdep/unix/config.c | 17 +++++++++++++++-- + util/config.c | 10 ++++++++++ + util/grub-install.c | 15 +++++++++++++++ + util/grub-mkrelpath.c | 6 ++++++ + include/grub/emu/config.h | 1 + + 6 files changed, 54 insertions(+), 2 deletions(-) + +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 001b818fe5..caf9b1ccd3 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -376,6 +376,7 @@ get_btrfs_fs_prefix (const char *mount_path) + return NULL; + } + ++int use_relative_path_on_btrfs = 0; + + char ** + grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) +@@ -519,6 +520,12 @@ again: + { + ret = grub_find_root_devices_from_btrfs (dir); + fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path); ++ if (use_relative_path_on_btrfs) ++ { ++ if (fs_prefix) ++ free (fs_prefix); ++ fs_prefix = xstrdup ("/"); ++ } + } + else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0) + { +diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c +index 7d6325138c..46a881530c 100644 +--- a/grub-core/osdep/unix/config.c ++++ b/grub-core/osdep/unix/config.c +@@ -82,6 +82,19 @@ grub_util_load_config (struct grub_util_config *cfg) + if (v) + cfg->grub_distributor = xstrdup (v); + ++ v = getenv ("SUSE_BTRFS_SNAPSHOT_BOOTING"); ++ if (v) ++ { ++ if (grub_strncmp(v, "true", sizeof ("true") - 1) == 0) ++ { ++ cfg->is_suse_btrfs_snapshot_enabled = 1; ++ } ++ else ++ { ++ cfg->is_suse_btrfs_snapshot_enabled = 0; ++ } ++ } ++ + cfgfile = grub_util_get_config_filename (); + if (!grub_util_is_regular (cfgfile)) + return; +@@ -105,8 +118,8 @@ grub_util_load_config (struct grub_util_config *cfg) + *ptr++ = *iptr; + } + +- strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\" " +- "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\""); ++ strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\nSUSE_BTRFS_SNAPSHOT_BOOTING=%s\\n\" " ++ "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\" \"$SUSE_BTRFS_SNAPSHOT_BOOTING\""); + + argv[2] = script; + argv[3] = '\0'; +diff --git a/util/config.c b/util/config.c +index ebcdd8f5e2..f044a880a7 100644 +--- a/util/config.c ++++ b/util/config.c +@@ -42,6 +42,16 @@ grub_util_parse_config (FILE *f, struct grub_util_config *cfg, int simple) + cfg->is_cryptodisk_enabled = 1; + continue; + } ++ if (grub_strncmp (ptr, "SUSE_BTRFS_SNAPSHOT_BOOTING=", ++ sizeof ("SUSE_BTRFS_SNAPSHOT_BOOTING=") - 1) == 0) ++ { ++ ptr += sizeof ("SUSE_BTRFS_SNAPSHOT_BOOTING=") - 1; ++ if (*ptr == '"' || *ptr == '\'') ++ ptr++; ++ if (grub_strncmp(ptr, "true", sizeof ("true") - 1) == 0) ++ cfg->is_suse_btrfs_snapshot_enabled = 1; ++ continue; ++ } + if (grub_strncmp (ptr, "GRUB_DISTRIBUTOR=", + sizeof ("GRUB_DISTRIBUTOR=") - 1) == 0) + { +diff --git a/util/grub-install.c b/util/grub-install.c +index 0fbe7f78c6..0f66f36d23 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -827,6 +827,8 @@ fill_core_services (const char *core_services) + free (sysv_plist); + } + ++extern int use_relative_path_on_btrfs; ++ + int + main (int argc, char *argv[]) + { +@@ -860,6 +862,9 @@ main (int argc, char *argv[]) + + grub_util_load_config (&config); + ++ if (config.is_suse_btrfs_snapshot_enabled) ++ use_relative_path_on_btrfs = 1; ++ + if (!bootloader_id && config.grub_distributor) + { + char *ptr; +@@ -1352,6 +1357,16 @@ main (int argc, char *argv[]) + fprintf (load_cfg_f, "set debug='%s'\n", + debug_image); + } ++ ++ if (config.is_suse_btrfs_snapshot_enabled ++ && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0) ++ { ++ if (!load_cfg_f) ++ load_cfg_f = grub_util_fopen (load_cfg, "wb"); ++ have_load_cfg = 1; ++ fprintf (load_cfg_f, "set btrfs_relative_path='y'\n"); ++ } ++ + char *prefix_drive = NULL; + char *install_drive = NULL; + +diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c +index 47a241a391..5db7a9a7d9 100644 +--- a/util/grub-mkrelpath.c ++++ b/util/grub-mkrelpath.c +@@ -40,9 +40,12 @@ struct arguments + }; + + static struct argp_option options[] = { ++ {"relative", 'r', 0, 0, "use relative path on btrfs", 0}, + { 0, 0, 0, 0, 0, 0 } + }; + ++extern int use_relative_path_on_btrfs; ++ + static error_t + argp_parser (int key, char *arg, struct argp_state *state) + { +@@ -52,6 +55,9 @@ argp_parser (int key, char *arg, struct argp_state *state) + + switch (key) + { ++ case 'r': ++ use_relative_path_on_btrfs = 1; ++ break; + case ARGP_KEY_ARG: + if (state->arg_num == 0) + arguments->pathname = xstrdup (arg); +diff --git a/include/grub/emu/config.h b/include/grub/emu/config.h +index 875d5896ce..c9a7e5f4ad 100644 +--- a/include/grub/emu/config.h ++++ b/include/grub/emu/config.h +@@ -37,6 +37,7 @@ struct grub_util_config + { + int is_cryptodisk_enabled; + char *grub_distributor; ++ int is_suse_btrfs_snapshot_enabled; + }; + + void diff --git a/SOURCES/0045-Try-prefix-if-fw_path-doesn-t-work.patch b/SOURCES/0045-Try-prefix-if-fw_path-doesn-t-work.patch deleted file mode 100644 index 59489bd..0000000 --- a/SOURCES/0045-Try-prefix-if-fw_path-doesn-t-work.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 9 Jul 2019 10:35:16 +0200 -Subject: [PATCH] Try $prefix if $fw_path doesn't work. - -Related: rhbz#1148652 - -Signed-off-by: Peter Jones ---- - grub-core/kern/ieee1275/init.c | 28 +++++---- - grub-core/net/net.c | 2 +- - grub-core/normal/main.c | 134 ++++++++++++++++++++--------------------- - 3 files changed, 82 insertions(+), 82 deletions(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index e71d1584164..0cd2a627231 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -127,23 +127,25 @@ grub_machine_get_bootlocation (char **device, char **path) - grub_free (canon); - } - else -- *device = grub_ieee1275_encode_devname (bootpath); -- grub_free (type); -- -- filename = grub_ieee1275_get_filename (bootpath); -- if (filename) - { -- char *lastslash = grub_strrchr (filename, '\\'); -- -- /* Truncate at last directory. */ -- if (lastslash) -+ filename = grub_ieee1275_get_filename (bootpath); -+ if (filename) - { -- *lastslash = '\0'; -- grub_translate_ieee1275_path (filename); -+ char *lastslash = grub_strrchr (filename, '\\'); - -- *path = filename; -- } -+ /* Truncate at last directory. */ -+ if (lastslash) -+ { -+ *lastslash = '\0'; -+ grub_translate_ieee1275_path (filename); -+ -+ *path = filename; -+ } -+ } -+ *device = grub_ieee1275_encode_devname (bootpath); - } -+ -+ grub_free (type); - grub_free (bootpath); - } - -diff --git a/grub-core/net/net.c b/grub-core/net/net.c -index 4d3eb5c1a52..0ef148f4adc 100644 ---- a/grub-core/net/net.c -+++ b/grub-core/net/net.c -@@ -1869,7 +1869,7 @@ grub_net_search_config_file (char *config) - /* Remove the remaining minus sign at the end. */ - config[config_len] = '\0'; - -- return GRUB_ERR_NONE; -+ return GRUB_ERR_FILE_NOT_FOUND; - } - - static struct grub_preboot *fini_hnd; -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 1e509fceb91..d5968797f4f 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -337,81 +337,79 @@ grub_enter_normal_mode (const char *config) - grub_boot_time ("Exiting normal mode"); - } - -+static grub_err_t -+grub_try_normal (const char *variable) -+{ -+ char *config; -+ const char *prefix; -+ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; -+ const char *net_search_cfg; -+ int disable_net_search = 0; -+ -+ prefix = grub_env_get (variable); -+ if (!prefix) -+ return GRUB_ERR_FILE_NOT_FOUND; -+ -+ net_search_cfg = grub_env_get ("feature_net_search_cfg"); -+ if (net_search_cfg && net_search_cfg[0] == 'n') -+ disable_net_search = 1; -+ -+ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 && -+ !disable_net_search) -+ { -+ grub_size_t config_len; -+ config_len = grub_strlen (prefix) + -+ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); -+ config = grub_malloc (config_len); -+ -+ if (! config) -+ return GRUB_ERR_FILE_NOT_FOUND; -+ -+ grub_snprintf (config, config_len, "%s/grub.cfg", prefix); -+ err = grub_net_search_config_file (config); -+ } -+ -+ if (err != GRUB_ERR_NONE) -+ { -+ config = grub_xasprintf ("%s/grub.cfg", prefix); -+ if (config) -+ { -+ grub_file_t file; -+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); -+ if (file) -+ { -+ grub_file_close (file); -+ err = GRUB_ERR_NONE; -+ } -+ } -+ } -+ -+ if (err == GRUB_ERR_NONE) -+ grub_enter_normal_mode (config); -+ -+ grub_errno = 0; -+ grub_free (config); -+ return err; -+} -+ - /* Enter normal mode from rescue mode. */ - static grub_err_t - grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), - int argc, char *argv[]) - { -- if (argc == 0) -- { -- /* Guess the config filename. It is necessary to make CONFIG static, -- so that it won't get broken by longjmp. */ -- char *config; -- const char *prefix; -- const char *net_search_cfg; -- int disable_net_search = 0; -- -- prefix = grub_env_get ("fw_path"); -- if (! prefix) -- prefix = grub_env_get ("prefix"); -- -- net_search_cfg = grub_env_get ("feature_net_search_cfg"); -- if (net_search_cfg && net_search_cfg[0] == 'n') -- disable_net_search = 1; -- -- if (prefix) -- { -- if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 && -- !disable_net_search) -- { -- grub_size_t config_len; -- config_len = grub_strlen (prefix) + -- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); -- config = grub_malloc (config_len); -- -- if (! config) -- goto quit; -- -- grub_snprintf (config, config_len, "%s/grub.cfg", prefix); -- -- grub_net_search_configfile (config); -- -- grub_enter_normal_mode (config); -- grub_free (config); -- config = NULL; -- } -- -- if (!config) -- { -- config = grub_xasprintf ("%s/grub.cfg", prefix); -- if (config) -- { -- grub_file_t file; -- -- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); -- if (file) -- { -- grub_file_close (file); -- grub_enter_normal_mode (config); -- } -- else -- { -- /* Ignore all errors. */ -- grub_errno = 0; -- } -- grub_free (config); -- } -- } -- } -- else -- { -- grub_enter_normal_mode (0); -- } -- } -- else -+ if (argc) - grub_enter_normal_mode (argv[0]); -+ else -+ { -+ /* Guess the config filename. */ -+ grub_err_t err; -+ err = grub_try_normal ("fw_path"); -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ err = grub_try_normal ("prefix"); -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ grub_enter_normal_mode (0); -+ } - --quit: - return 0; - } - diff --git a/SOURCES/0045-grub2-btrfs-05-grub2-mkconfig.patch b/SOURCES/0045-grub2-btrfs-05-grub2-mkconfig.patch new file mode 100644 index 0000000..ca3f86b --- /dev/null +++ b/SOURCES/0045-grub2-btrfs-05-grub2-mkconfig.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 21 Aug 2014 03:39:11 +0000 +Subject: [PATCH] grub2-btrfs-05-grub2-mkconfig + +Signed-off-by: Michael Chang +--- + util/grub-mkconfig.in | 3 ++- + util/grub-mkconfig_lib.in | 4 ++++ + util/grub.d/00_header.in | 25 ++++++++++++++++++++++++- + util/grub.d/10_linux.in | 4 ++++ + util/grub.d/20_linux_xen.in | 4 ++++ + 5 files changed, 38 insertions(+), 2 deletions(-) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index 005f093809..535c0f0249 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -252,7 +252,8 @@ export GRUB_DEFAULT \ + GRUB_BADRAM \ + GRUB_OS_PROBER_SKIP_LIST \ + GRUB_DISABLE_SUBMENU \ +- GRUB_DEFAULT_DTB ++ GRUB_DEFAULT_DTB \ ++ SUSE_BTRFS_SNAPSHOT_BOOTING + + if test "x${grub_cfg}" != "x"; then + rm -f "${grub_cfg}.new" +diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in +index 0f6505bf3b..5e96f6cc5d 100644 +--- a/util/grub-mkconfig_lib.in ++++ b/util/grub-mkconfig_lib.in +@@ -49,7 +49,11 @@ grub_warn () + + make_system_path_relative_to_its_root () + { ++ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] ; then ++ "${grub_mkrelpath}" -r "$1" ++ else + "${grub_mkrelpath}" "$1" ++ fi + } + + is_path_readable_by_grub () +diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in +index 858b526c92..de727e6ee6 100644 +--- a/util/grub.d/00_header.in ++++ b/util/grub.d/00_header.in +@@ -27,6 +27,14 @@ export TEXTDOMAINDIR="@localedir@" + + . "$pkgdatadir/grub-mkconfig_lib" + ++if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] && ++ [ "x${GRUB_FS}" = "xbtrfs" ] ; then ++ cat </dev/null || true` +diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in +index ada20775a1..e9e73b815f 100644 +--- a/util/grub.d/20_linux_xen.in ++++ b/util/grub.d/20_linux_xen.in +@@ -73,10 +73,14 @@ fi + + case x"$GRUB_FS" in + xbtrfs) ++ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then ++ GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}" ++ else + rootsubvol="`make_system_path_relative_to_its_root /`" + rootsubvol="${rootsubvol#/}" + if [ "x${rootsubvol}" != x ]; then + GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" ++ fi + fi;; + xzfs) + rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true` diff --git a/SOURCES/0046-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch b/SOURCES/0046-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch deleted file mode 100644 index 78a6fa1..0000000 --- a/SOURCES/0046-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch +++ /dev/null @@ -1,458 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robert Marshall -Date: Mon, 16 Mar 2015 14:14:19 -0400 -Subject: [PATCH] Use Distribution Package Sort for grub2-mkconfig (#1124074) - -Users reported that newly installed kernels on their systems installed -with grub-mkconfig would not appear on the grub boot list in order -starting with the most recent. Added an option for rpm-based systems to -use the rpm-sort library to sort kernels instead. - -Resolves rhbz#1124074 - -Signed-off-by: Robert Marshall -[pjones: fix --enable-rpm-sort configure option] -Signed-off-by: Peter Jones -[thierry.vignaud: fix build with rpm-4.16] -Signed-off-by: Thierry Vignaud ---- - configure.ac | 38 +++++++ - Makefile.util.def | 16 +++ - util/grub-rpm-sort.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++ - util/grub-mkconfig_lib.in | 11 +- - util/grub-rpm-sort.8 | 12 ++ - 5 files changed, 357 insertions(+), 1 deletion(-) - create mode 100644 util/grub-rpm-sort.c - create mode 100644 util/grub-rpm-sort.8 - -diff --git a/configure.ac b/configure.ac -index bec8535af70..fdcb452581c 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -72,6 +72,7 @@ grub_TRANSFORM([grub-mkrelpath]) - grub_TRANSFORM([grub-mkrescue]) - grub_TRANSFORM([grub-probe]) - grub_TRANSFORM([grub-reboot]) -+grub_TRANSFORM([grub-rpm-sort]) - grub_TRANSFORM([grub-script-check]) - grub_TRANSFORM([grub-set-default]) - grub_TRANSFORM([grub-sparc64-setup]) -@@ -95,6 +96,7 @@ grub_TRANSFORM([grub-mkrescue.1]) - grub_TRANSFORM([grub-mkstandalone.3]) - grub_TRANSFORM([grub-ofpathname.3]) - grub_TRANSFORM([grub-probe.3]) -+grub_TRANSFORM([grub-rpm-sort.8]) - grub_TRANSFORM([grub-reboot.3]) - grub_TRANSFORM([grub-render-label.3]) - grub_TRANSFORM([grub-script-check.3]) -@@ -1860,6 +1862,42 @@ fi - - AC_SUBST([LIBDEVMAPPER]) - -+AC_ARG_ENABLE([rpm-sort], -+ [AS_HELP_STRING([--enable-rpm-sort], -+ [enable native rpm sorting of kernels in grub (default=guessed)])]) -+if test x"$enable_rpm_sort" = xno ; then -+ rpm_sort_excuse="explicitly disabled" -+fi -+ -+if test x"$rpm_sort_excuse" = x ; then -+ # Check for rpmlib header. -+ AC_CHECK_HEADER([rpm/rpmlib.h], [], -+ [rpm_sort_excuse="need rpm/rpmlib header"]) -+fi -+ -+if test x"$rpm_sort_excuse" = x ; then -+ # Check for rpm library. -+ AC_CHECK_LIB([rpm], [rpmvercmp], [], -+ [rpm_sort_excuse="rpmlib missing rpmvercmp"]) -+fi -+ -+if test x"$rpm_sort_excuse" = x ; then -+ LIBRPM="-lrpm"; -+ AC_DEFINE([HAVE_RPM], [1], -+ [Define to 1 if you have the rpm library.]) -+fi -+ -+if test x"$LIBRPM" = x ; then -+ # Check for rpm library. -+ AC_CHECK_LIB([rpmio], [rpmvercmp], [], -+ [rpm_sort_excuse="rpmio missing rpmvercmp"]) -+ LIBRPM="-lrpmio"; -+ AC_DEFINE([HAVE_RPMIO], [1], -+ [Define to 1 if you have the rpm library.]) -+fi -+ -+AC_SUBST([LIBRPM]) -+ - LIBGEOM= - if test x$host_kernel = xkfreebsd; then - AC_CHECK_LIB([geom], [geom_gettree], [], -diff --git a/Makefile.util.def b/Makefile.util.def -index 2c9b283a230..ba4cf4b29b0 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -703,6 +703,22 @@ program = { - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - }; - -+program = { -+ name = grub-rpm-sort; -+ mansection = 8; -+ installdir = sbin; -+ -+ common = grub-core/kern/emu/misc.c; -+ common = grub-core/kern/emu/argp_common.c; -+ common = grub-core/osdep/init.c; -+ common = util/misc.c; -+ common = util/grub-rpm-sort.c; -+ -+ ldadd = libgrubkern.a; -+ ldadd = grub-core/lib/gnulib/libgnu.a; -+ ldadd = '$(LIBDEVMAPPER) $(LIBRPM)'; -+}; -+ - script = { - name = grub-mkconfig; - common = util/grub-mkconfig.in; -diff --git a/util/grub-rpm-sort.c b/util/grub-rpm-sort.c -new file mode 100644 -index 00000000000..f33bd1ed568 ---- /dev/null -+++ b/util/grub-rpm-sort.c -@@ -0,0 +1,281 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static size_t -+read_file (const char *input, char **ret) -+{ -+ FILE *in; -+ size_t s; -+ size_t sz = 2048; -+ size_t offset = 0; -+ char *text; -+ -+ if (!strcmp(input, "-")) -+ in = stdin; -+ else -+ in = grub_util_fopen(input, "r"); -+ -+ text = xmalloc (sz); -+ -+ if (!in) -+ grub_util_error (_("cannot open `%s': %s"), input, strerror (errno)); -+ -+ while ((s = fread (text + offset, 1, sz - offset, in)) != 0) -+ { -+ offset += s; -+ if (sz - offset == 0) -+ { -+ sz += 2048; -+ text = xrealloc (text, sz); -+ } -+ } -+ -+ text[offset] = '\0'; -+ *ret = text; -+ -+ if (in != stdin) -+ fclose(in); -+ -+ return offset + 1; -+} -+ -+/* returns name/version/release */ -+/* NULL string pointer returned if nothing found */ -+static void -+split_package_string (char *package_string, char **name, -+ char **version, char **release) -+{ -+ char *package_version, *package_release; -+ -+ /* Release */ -+ package_release = strrchr (package_string, '-'); -+ -+ if (package_release != NULL) -+ *package_release++ = '\0'; -+ -+ *release = package_release; -+ -+ /* Version */ -+ package_version = strrchr(package_string, '-'); -+ -+ if (package_version != NULL) -+ *package_version++ = '\0'; -+ -+ *version = package_version; -+ /* Name */ -+ *name = package_string; -+ -+ /* Bubble up non-null values from release to name */ -+ if (*name == NULL) -+ { -+ *name = (*version == NULL ? *release : *version); -+ *version = *release; -+ *release = NULL; -+ } -+ if (*version == NULL) -+ { -+ *version = *release; -+ *release = NULL; -+ } -+} -+ -+/* -+ * package name-version-release comparator for qsort -+ * expects p, q which are pointers to character strings (char *) -+ * which will not be altered in this function -+ */ -+static int -+package_version_compare (const void *p, const void *q) -+{ -+ char *local_p, *local_q; -+ char *lhs_name, *lhs_version, *lhs_release; -+ char *rhs_name, *rhs_version, *rhs_release; -+ int vercmpflag = 0; -+ -+ local_p = alloca (strlen (*(char * const *)p) + 1); -+ local_q = alloca (strlen (*(char * const *)q) + 1); -+ -+ /* make sure these allocated */ -+ assert (local_p); -+ assert (local_q); -+ -+ strcpy (local_p, *(char * const *)p); -+ strcpy (local_q, *(char * const *)q); -+ -+ split_package_string (local_p, &lhs_name, &lhs_version, &lhs_release); -+ split_package_string (local_q, &rhs_name, &rhs_version, &rhs_release); -+ -+ /* Check Name and return if unequal */ -+ vercmpflag = rpmvercmp ((lhs_name == NULL ? "" : lhs_name), -+ (rhs_name == NULL ? "" : rhs_name)); -+ if (vercmpflag != 0) -+ return vercmpflag; -+ -+ /* Check version and return if unequal */ -+ vercmpflag = rpmvercmp ((lhs_version == NULL ? "" : lhs_version), -+ (rhs_version == NULL ? "" : rhs_version)); -+ if (vercmpflag != 0) -+ return vercmpflag; -+ -+ /* Check release and return the version compare value */ -+ vercmpflag = rpmvercmp ((lhs_release == NULL ? "" : lhs_release), -+ (rhs_release == NULL ? "" : rhs_release)); -+ -+ return vercmpflag; -+} -+ -+static void -+add_input (const char *filename, char ***package_names, size_t *n_package_names) -+{ -+ char *orig_input_buffer = NULL; -+ char *input_buffer; -+ char *position_of_newline; -+ char **names = *package_names; -+ char **new_names = NULL; -+ size_t n_names = *n_package_names; -+ -+ if (!*package_names) -+ new_names = names = xmalloc (sizeof (char *) * 2); -+ -+ if (read_file (filename, &orig_input_buffer) < 2) -+ { -+ if (new_names) -+ free (new_names); -+ if (orig_input_buffer) -+ free (orig_input_buffer); -+ return; -+ } -+ -+ input_buffer = orig_input_buffer; -+ while (input_buffer && *input_buffer && -+ (position_of_newline = strchrnul (input_buffer, '\n'))) -+ { -+ size_t sz = position_of_newline - input_buffer; -+ char *new; -+ -+ if (sz == 0) -+ { -+ input_buffer = position_of_newline + 1; -+ continue; -+ } -+ -+ new = xmalloc (sz+1); -+ strncpy (new, input_buffer, sz); -+ new[sz] = '\0'; -+ -+ names = xrealloc (names, sizeof (char *) * (n_names + 1)); -+ names[n_names] = new; -+ n_names++; -+ -+ /* move buffer ahead to next line */ -+ input_buffer = position_of_newline + 1; -+ if (*position_of_newline == '\0') -+ input_buffer = NULL; -+ } -+ -+ free (orig_input_buffer); -+ -+ *package_names = names; -+ *n_package_names = n_names; -+} -+ -+static char * -+help_filter (int key, const char *text, void *input __attribute__ ((unused))) -+{ -+ return (char *)text; -+} -+ -+static struct argp_option options[] = { -+ { 0, } -+}; -+ -+struct arguments -+{ -+ size_t ninputs; -+ size_t input_max; -+ char **inputs; -+}; -+ -+static error_t -+argp_parser (int key, char *arg, struct argp_state *state) -+{ -+ struct arguments *arguments = state->input; -+ switch (key) -+ { -+ case ARGP_KEY_ARG: -+ assert (arguments->ninputs < arguments->input_max); -+ arguments->inputs[arguments->ninputs++] = xstrdup (arg); -+ break; -+ default: -+ return ARGP_ERR_UNKNOWN; -+ } -+ return 0; -+} -+ -+static struct argp argp = { -+ options, argp_parser, N_("[INPUT_FILES]"), -+ N_("Sort a list of strings in RPM version sort order."), -+ NULL, help_filter, NULL -+}; -+ -+int -+main (int argc, char *argv[]) -+{ -+ struct arguments arguments; -+ char **package_names = NULL; -+ size_t n_package_names = 0; -+ int i; -+ -+ grub_util_host_init (&argc, &argv); -+ -+ memset (&arguments, 0, sizeof (struct arguments)); -+ arguments.input_max = argc+1; -+ arguments.inputs = xmalloc ((arguments.input_max + 1) -+ * sizeof (arguments.inputs[0])); -+ memset (arguments.inputs, 0, (arguments.input_max + 1) -+ * sizeof (arguments.inputs[0])); -+ -+ /* Parse our arguments */ -+ if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) -+ grub_util_error ("%s", _("Error in parsing command line arguments\n")); -+ -+ /* If there's no inputs in argv, add one for stdin */ -+ if (!arguments.ninputs) -+ { -+ arguments.ninputs = 1; -+ arguments.inputs[0] = xmalloc (2); -+ strcpy(arguments.inputs[0], "-"); -+ } -+ -+ for (i = 0; i < arguments.ninputs; i++) -+ add_input(arguments.inputs[i], &package_names, &n_package_names); -+ -+ if (package_names == NULL || n_package_names < 1) -+ grub_util_error ("%s", _("Invalid input\n")); -+ -+ qsort (package_names, n_package_names, sizeof (char *), -+ package_version_compare); -+ -+ /* send sorted list to stdout */ -+ for (i = 0; i < n_package_names; i++) -+ { -+ fprintf (stdout, "%s\n", package_names[i]); -+ free (package_names[i]); -+ } -+ -+ free (package_names); -+ for (i = 0; i < arguments.ninputs; i++) -+ free (arguments.inputs[i]); -+ -+ free (arguments.inputs); -+ -+ return 0; -+} -diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in -index 0f6505bf3b6..42c2ea9ba50 100644 ---- a/util/grub-mkconfig_lib.in -+++ b/util/grub-mkconfig_lib.in -@@ -33,6 +33,9 @@ fi - if test "x$grub_mkrelpath" = x; then - grub_mkrelpath="${bindir}/@grub_mkrelpath@" - fi -+if test "x$grub_rpm_sort" = x; then -+ grub_rpm_sort="${sbindir}/@grub_rpm_sort@" -+fi - - if command -v gettext >/dev/null; then - : -@@ -218,6 +221,12 @@ version_sort () - esac - } - -+if [ "x$grub_rpm_sort" != x -a -x "$grub_rpm_sort" ]; then -+ kernel_sort="$grub_rpm_sort" -+else -+ kernel_sort=version_sort -+fi -+ - version_test_numeric () - { - version_test_numeric_a="$1" -@@ -234,7 +243,7 @@ version_test_numeric () - version_test_numeric_a="$version_test_numeric_b" - version_test_numeric_b="$version_test_numeric_c" - fi -- if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | version_sort | head -n 1 | grep -qx "$version_test_numeric_b" ; then -+ if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | "$kernel_sort" | head -n 1 | grep -qx "$version_test_numeric_b" ; then - return 0 - else - return 1 -diff --git a/util/grub-rpm-sort.8 b/util/grub-rpm-sort.8 -new file mode 100644 -index 00000000000..8ce21488448 ---- /dev/null -+++ b/util/grub-rpm-sort.8 -@@ -0,0 +1,12 @@ -+.TH GRUB-RPM-SORT 8 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-rpm-sort\fR \(em Sort input according to RPM version compare. -+ -+.SH SYNOPSIS -+\fBgrub-rpm-sort\fR [OPTIONS]. -+ -+.SH DESCRIPTION -+You should not normally run this program directly. Use grub-mkconfig instead. -+ -+.SH SEE ALSO -+.BR "info grub" diff --git a/SOURCES/0046-grub2-btrfs-06-subvol-mount.patch b/SOURCES/0046-grub2-btrfs-06-subvol-mount.patch new file mode 100644 index 0000000..8cdf247 --- /dev/null +++ b/SOURCES/0046-grub2-btrfs-06-subvol-mount.patch @@ -0,0 +1,539 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 9 Jul 2019 13:56:16 +0200 +Subject: [PATCH] grub2-btrfs-06-subvol-mount + +Signed-off-by: Michael Chang +Signed-off-by: Robbie Harwood +--- + grub-core/fs/btrfs.c | 195 +++++++++++++++++++++++++++++++++++++++- + grub-core/osdep/linux/getroot.c | 148 +++++++++++++++++++++++++++++- + util/grub-install.c | 49 ++++++++++ + include/grub/emu/getroot.h | 5 ++ + 4 files changed, 392 insertions(+), 5 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 113c1f746c..d323746ecf 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -266,6 +267,12 @@ static grub_err_t + grub_btrfs_read_logical (struct grub_btrfs_data *data, + grub_disk_addr_t addr, void *buf, grub_size_t size, + int recursion_depth); ++static grub_err_t ++get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key, ++ grub_uint64_t *tree, grub_uint8_t *type); ++ ++grub_uint64_t ++find_mtab_subvol_tree (const char *path, char **path_in_subvol); + + static grub_err_t + read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb) +@@ -1223,9 +1230,26 @@ lookup_root_by_name(struct grub_btrfs_data *data, const char *path) + grub_err_t err; + grub_uint64_t tree = 0; + grub_uint8_t type; ++ grub_uint64_t saved_tree; + struct grub_btrfs_key key; + ++ if (path[0] == '\0') ++ { ++ data->fs_tree = 0; ++ return GRUB_ERR_NONE; ++ } ++ ++ err = get_root (data, &key, &tree, &type); ++ if (err) ++ return err; ++ ++ saved_tree = data->fs_tree; ++ data->fs_tree = tree; ++ + err = find_path (data, path, &key, &tree, &type); ++ ++ data->fs_tree = saved_tree; ++ + if (err) + return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path); + +@@ -2199,11 +2223,20 @@ grub_btrfs_dir (grub_device_t device, const char *path, + int r = 0; + grub_uint64_t tree; + grub_uint8_t type; ++ char *new_path = NULL; + + if (!data) + return grub_errno; + +- err = find_path (data, path, &key_in, &tree, &type); ++ tree = find_mtab_subvol_tree (path, &new_path); ++ ++ if (tree) ++ data->fs_tree = tree; ++ ++ err = find_path (data, new_path ? new_path : path, &key_in, &tree, &type); ++ if (new_path) ++ grub_free (new_path); ++ + if (err) + { + grub_btrfs_unmount (data); +@@ -2305,11 +2338,21 @@ grub_btrfs_open (struct grub_file *file, const char *name) + struct grub_btrfs_inode inode; + grub_uint8_t type; + struct grub_btrfs_key key_in; ++ grub_uint64_t tree; ++ char *new_path = NULL; + + if (!data) + return grub_errno; + +- err = find_path (data, name, &key_in, &data->tree, &type); ++ tree = find_mtab_subvol_tree (name, &new_path); ++ ++ if (tree) ++ data->fs_tree = tree; ++ ++ err = find_path (data, new_path ? new_path : name, &key_in, &data->tree, &type); ++ if (new_path) ++ grub_free (new_path); ++ + if (err) + { + grub_btrfs_unmount (data); +@@ -2480,6 +2523,150 @@ grub_cmd_btrfs_info (grub_command_t cmd __attribute__ ((unused)), int argc, + return 0; + } + ++struct grub_btrfs_mtab ++{ ++ struct grub_btrfs_mtab *next; ++ struct grub_btrfs_mtab **prev; ++ char *path; ++ char *subvol; ++ grub_uint64_t tree; ++}; ++ ++typedef struct grub_btrfs_mtab* grub_btrfs_mtab_t; ++ ++static struct grub_btrfs_mtab *btrfs_mtab; ++ ++#define FOR_GRUB_MTAB(var) FOR_LIST_ELEMENTS (var, btrfs_mtab) ++#define FOR_GRUB_MTAB_SAFE(var, next) FOR_LIST_ELEMENTS_SAFE((var), (next), btrfs_mtab) ++ ++static void ++add_mountpoint (const char *path, const char *subvol, grub_uint64_t tree) ++{ ++ grub_btrfs_mtab_t m = grub_malloc (sizeof (*m)); ++ ++ m->path = grub_strdup (path); ++ m->subvol = grub_strdup (subvol); ++ m->tree = tree; ++ grub_list_push (GRUB_AS_LIST_P (&btrfs_mtab), GRUB_AS_LIST (m)); ++} ++ ++static grub_err_t ++grub_cmd_btrfs_mount_subvol (grub_command_t cmd __attribute__ ((unused)), int argc, ++ char **argv) ++{ ++ char *devname, *dirname, *subvol; ++ struct grub_btrfs_key key_in; ++ grub_uint8_t type; ++ grub_uint64_t tree; ++ grub_uint64_t saved_tree; ++ grub_err_t err; ++ struct grub_btrfs_data *data = NULL; ++ grub_device_t dev = NULL; ++ ++ if (argc < 3) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "required and "); ++ ++ devname = grub_file_get_device_name(argv[0]); ++ dev = grub_device_open (devname); ++ grub_free (devname); ++ ++ if (!dev) ++ { ++ err = grub_errno; ++ goto err_out; ++ } ++ ++ dirname = argv[1]; ++ subvol = argv[2]; ++ ++ data = grub_btrfs_mount (dev); ++ if (!data) ++ { ++ err = grub_errno; ++ goto err_out; ++ } ++ ++ err = find_path (data, dirname, &key_in, &tree, &type); ++ if (err) ++ goto err_out; ++ ++ if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) ++ { ++ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); ++ goto err_out; ++ } ++ ++ err = get_root (data, &key_in, &tree, &type); ++ ++ if (err) ++ goto err_out; ++ ++ saved_tree = data->fs_tree; ++ data->fs_tree = tree; ++ err = find_path (data, subvol, &key_in, &tree, &type); ++ data->fs_tree = saved_tree; ++ ++ if (err) ++ goto err_out; ++ ++ if (key_in.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0) ++ { ++ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", subvol); ++ goto err_out; ++ } ++ ++ grub_btrfs_unmount (data); ++ grub_device_close (dev); ++ add_mountpoint (dirname, subvol, tree); ++ ++ return GRUB_ERR_NONE; ++ ++err_out: ++ ++ if (data) ++ grub_btrfs_unmount (data); ++ ++ if (dev) ++ grub_device_close (dev); ++ ++ return err; ++} ++ ++grub_uint64_t ++find_mtab_subvol_tree (const char *path, char **path_in_subvol) ++{ ++ grub_btrfs_mtab_t m, cm; ++ grub_uint64_t tree; ++ ++ if (!path || !path_in_subvol) ++ return 0; ++ ++ *path_in_subvol = NULL; ++ tree = 0; ++ cm = NULL; ++ ++ FOR_GRUB_MTAB (m) ++ { ++ if (grub_strncmp (path, m->path, grub_strlen (m->path)) == 0) ++ { ++ if (!cm) ++ cm = m; ++ else ++ if (grub_strcmp (m->path, cm->path) > 0) ++ cm = m; ++ } ++ } ++ ++ if (cm) ++ { ++ const char *s = path + grub_strlen (cm->path); ++ *path_in_subvol = (s[0] == '\0') ? grub_strdup ("/") : grub_strdup (s); ++ tree = cm->tree; ++ } ++ ++ return tree; ++} ++ + static grub_err_t + get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree, + grub_uint64_t objectid, grub_uint64_t offset, +@@ -2686,6 +2873,7 @@ static struct grub_fs grub_btrfs_fs = { + }; + + static grub_command_t cmd_info; ++static grub_command_t cmd_mount_subvol; + static grub_extcmd_t cmd_list_subvols; + + static char * +@@ -2749,6 +2937,9 @@ GRUB_MOD_INIT (btrfs) + cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info, + "DEVICE", + "Print BtrFS info about DEVICE."); ++ cmd_mount_subvol = grub_register_command("btrfs-mount-subvol", grub_cmd_btrfs_mount_subvol, ++ "DEVICE DIRECTORY SUBVOL", ++ "Set btrfs DEVICE the DIRECTORY a mountpoint of SUBVOL."); + cmd_list_subvols = grub_register_extcmd("btrfs-list-subvols", + grub_cmd_btrfs_list_subvols, 0, + "[-p|-n] [-o var] DEVICE", +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index caf9b1ccd3..28790307e0 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -107,6 +107,14 @@ struct btrfs_ioctl_search_key + grub_uint32_t unused[9]; + }; + ++struct btrfs_ioctl_search_header { ++ grub_uint64_t transid; ++ grub_uint64_t objectid; ++ grub_uint64_t offset; ++ grub_uint32_t type; ++ grub_uint32_t len; ++}; ++ + struct btrfs_ioctl_search_args { + struct btrfs_ioctl_search_key key; + grub_uint64_t buf[(4096 - sizeof(struct btrfs_ioctl_search_key)) +@@ -378,6 +386,109 @@ get_btrfs_fs_prefix (const char *mount_path) + + int use_relative_path_on_btrfs = 0; + ++static char * ++get_btrfs_subvol (const char *path) ++{ ++ struct btrfs_ioctl_ino_lookup_args args; ++ grub_uint64_t tree_id; ++ int fd = -1; ++ char *ret = NULL; ++ ++ fd = open (path, O_RDONLY); ++ ++ if (fd < 0) ++ return NULL; ++ ++ memset (&args, 0, sizeof(args)); ++ args.objectid = GRUB_BTRFS_TREE_ROOT_OBJECTID; ++ ++ if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0) ++ goto error; ++ ++ tree_id = args.treeid; ++ ++ while (tree_id != GRUB_BTRFS_ROOT_VOL_OBJECTID) ++ { ++ struct btrfs_ioctl_search_args sargs; ++ struct grub_btrfs_root_backref *br; ++ struct btrfs_ioctl_search_header *search_header; ++ char *old; ++ grub_uint16_t len; ++ grub_uint64_t inode_id; ++ ++ memset (&sargs, 0, sizeof(sargs)); ++ ++ sargs.key.tree_id = 1; ++ sargs.key.min_objectid = tree_id; ++ sargs.key.max_objectid = tree_id; ++ ++ sargs.key.min_offset = 0; ++ sargs.key.max_offset = ~0ULL; ++ sargs.key.min_transid = 0; ++ sargs.key.max_transid = ~0ULL; ++ sargs.key.min_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF; ++ sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF; ++ ++ sargs.key.nr_items = 1; ++ ++ if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0) ++ goto error; ++ ++ if (sargs.key.nr_items == 0) ++ goto error; ++ ++ search_header = (struct btrfs_ioctl_search_header *)sargs.buf; ++ br = (struct grub_btrfs_root_backref *) (search_header + 1); ++ ++ len = grub_le_to_cpu16 (br->n); ++ inode_id = grub_le_to_cpu64 (br->inode_id); ++ tree_id = search_header->offset; ++ ++ old = ret; ++ ret = malloc (len + 1); ++ memcpy (ret, br->name, len); ++ ret[len] = '\0'; ++ ++ if (inode_id != GRUB_BTRFS_TREE_ROOT_OBJECTID) ++ { ++ char *s; ++ ++ memset(&args, 0, sizeof(args)); ++ args.treeid = search_header->offset; ++ args.objectid = inode_id; ++ ++ if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0) ++ goto error; ++ ++ s = xasprintf ("%s%s", args.name, ret); ++ free (ret); ++ ret = s; ++ } ++ ++ if (old) ++ { ++ char *s = xasprintf ("%s/%s", ret, old); ++ free (ret); ++ free (old); ++ ret = s; ++ } ++ } ++ ++ close (fd); ++ return ret; ++ ++error: ++ ++ if (fd >= 0) ++ close (fd); ++ if (ret) ++ free (ret); ++ ++ return NULL; ++} ++ ++void (*grub_find_root_btrfs_mount_path_hook)(const char *mount_path); ++ + char ** + grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) + { +@@ -519,12 +630,15 @@ again: + else if (grub_strcmp (entries[i].fstype, "btrfs") == 0) + { + ret = grub_find_root_devices_from_btrfs (dir); +- fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path); + if (use_relative_path_on_btrfs) + { +- if (fs_prefix) +- free (fs_prefix); + fs_prefix = xstrdup ("/"); ++ if (grub_find_root_btrfs_mount_path_hook) ++ grub_find_root_btrfs_mount_path_hook (entries[i].enc_path); ++ } ++ else ++ { ++ fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path); + } + } + else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0) +@@ -1150,6 +1264,34 @@ grub_util_get_grub_dev_os (const char *os_dev) + return grub_dev; + } + ++ ++char * ++grub_util_get_btrfs_subvol (const char *path, char **mount_path) ++{ ++ char *mp = NULL; ++ ++ if (mount_path) ++ *mount_path = NULL; ++ ++ auto void ++ mount_path_hook (const char *m) ++ { ++ mp = strdup (m); ++ } ++ ++ grub_find_root_btrfs_mount_path_hook = mount_path_hook; ++ grub_free (grub_find_root_devices_from_mountinfo (path, NULL)); ++ grub_find_root_btrfs_mount_path_hook = NULL; ++ ++ if (!mp) ++ return NULL; ++ ++ if (mount_path) ++ *mount_path = mp; ++ ++ return get_btrfs_subvol (mp); ++} ++ + char * + grub_make_system_path_relative_to_its_root_os (const char *path) + { +diff --git a/util/grub-install.c b/util/grub-install.c +index 0f66f36d23..84ed6e88ec 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -1569,6 +1569,55 @@ main (int argc, char *argv[]) + prefix_drive = xasprintf ("(%s)", grub_drives[0]); + } + ++#ifdef __linux__ ++ ++ if (config.is_suse_btrfs_snapshot_enabled ++ && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0) ++ { ++ char *subvol = NULL; ++ char *mount_path = NULL; ++ char **rootdir_devices = NULL; ++ char *rootdir_path = grub_util_path_concat (2, "/", rootdir); ++ ++ if (grub_util_is_directory (rootdir_path)) ++ rootdir_devices = grub_guess_root_devices (rootdir_path); ++ ++ free (rootdir_path); ++ ++ if (rootdir_devices && rootdir_devices[0]) ++ if (grub_strcmp (rootdir_devices[0], grub_devices[0]) == 0) ++ subvol = grub_util_get_btrfs_subvol (platdir, &mount_path); ++ ++ if (subvol && mount_path) ++ { ++ char *def_subvol; ++ ++ def_subvol = grub_util_get_btrfs_subvol ("/", NULL); ++ ++ if (def_subvol) ++ { ++ if (!load_cfg_f) ++ load_cfg_f = grub_util_fopen (load_cfg, "wb"); ++ have_load_cfg = 1; ++ ++ if (grub_strcmp (subvol, def_subvol) != 0) ++ fprintf (load_cfg_f, "btrfs-mount-subvol ($root) %s %s\n", mount_path, subvol); ++ free (def_subvol); ++ } ++ } ++ ++ for (curdev = rootdir_devices; *curdev; curdev++) ++ free (*curdev); ++ if (rootdir_devices) ++ free (rootdir_devices); ++ if (subvol) ++ free (subvol); ++ if (mount_path) ++ free (mount_path); ++ } ++ ++#endif ++ + char mkimage_target[200]; + const char *core_name = NULL; + +diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h +index 73fa2d34ab..9c642ae3fe 100644 +--- a/include/grub/emu/getroot.h ++++ b/include/grub/emu/getroot.h +@@ -53,6 +53,11 @@ char ** + grub_find_root_devices_from_mountinfo (const char *dir, char **relroot); + #endif + ++#ifdef __linux__ ++char * ++grub_util_get_btrfs_subvol (const char *path, char **mount_path); ++#endif ++ + /* Devmapper functions provided by getroot_devmapper.c. */ + void + grub_util_pull_devmapper (const char *os_dev); diff --git a/SOURCES/0047-Fallback-to-old-subvol-name-scheme-to-support-old-sn.patch b/SOURCES/0047-Fallback-to-old-subvol-name-scheme-to-support-old-sn.patch new file mode 100644 index 0000000..a5db09a --- /dev/null +++ b/SOURCES/0047-Fallback-to-old-subvol-name-scheme-to-support-old-sn.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Tue, 21 Jun 2016 16:44:17 +0000 +Subject: [PATCH] Fallback to old subvol name scheme to support old snapshot + config + +Ref: bsc#953538 +--- + grub-core/fs/btrfs.c | 32 +++++++++++++++++++++++++++++++- + 1 file changed, 31 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index d323746ecf..673ded0352 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -1260,11 +1260,41 @@ lookup_root_by_name(struct grub_btrfs_data *data, const char *path) + return GRUB_ERR_NONE; + } + ++static grub_err_t ++lookup_root_by_name_fallback(struct grub_btrfs_data *data, const char *path) ++{ ++ grub_err_t err; ++ grub_uint64_t tree = 0; ++ grub_uint8_t type; ++ struct grub_btrfs_key key; ++ ++ err = find_path (data, path, &key, &tree, &type); ++ if (err) ++ return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path); ++ ++ if (key.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0) ++ return grub_error(GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", path); ++ ++ data->fs_tree = tree; ++ return GRUB_ERR_NONE; ++} ++ + static grub_err_t + btrfs_handle_subvol(struct grub_btrfs_data *data __attribute__ ((unused))) + { + if (btrfs_default_subvol) +- return lookup_root_by_name(data, btrfs_default_subvol); ++ { ++ grub_err_t err; ++ err = lookup_root_by_name(data, btrfs_default_subvol); ++ ++ /* Fallback to old schemes */ ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ { ++ err = GRUB_ERR_NONE; ++ return lookup_root_by_name_fallback(data, btrfs_default_subvol); ++ } ++ return err; ++ } + + if (btrfs_default_subvolid) + return lookup_root_by_id(data, btrfs_default_subvolid); diff --git a/SOURCES/0047-Make-grub2-mkconfig-construct-titles-that-look-like-.patch b/SOURCES/0047-Make-grub2-mkconfig-construct-titles-that-look-like-.patch deleted file mode 100644 index 4c474e4..0000000 --- a/SOURCES/0047-Make-grub2-mkconfig-construct-titles-that-look-like-.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 28 Apr 2015 11:15:03 -0400 -Subject: [PATCH] Make grub2-mkconfig construct titles that look like the ones - we want elsewhere. - -Resolves: rhbz#1215839 - -Signed-off-by: Peter Jones ---- - util/grub.d/10_linux.in | 34 +++++++++++++++++++++++++++------- - 1 file changed, 27 insertions(+), 7 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index fed73271478..2e59f3b4197 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -78,6 +78,32 @@ case x"$GRUB_FS" in - ;; - esac - -+mktitle () -+{ -+ local title_type -+ local version -+ local OS_NAME -+ local OS_VERS -+ -+ title_type=$1 && shift -+ version=$1 && shift -+ -+ OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})" -+ OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})" -+ -+ case $title_type in -+ recovery) -+ title=$(printf '%s (%s) %s (recovery mode)' \ -+ "${OS_NAME}" "${version}" "${OS_VERS}") -+ ;; -+ *) -+ title=$(printf '%s (%s) %s' \ -+ "${OS_NAME}" "${version}" "${OS_VERS}") -+ ;; -+ esac -+ echo -n ${title} -+} -+ - title_correction_code= - - linux_entry () -@@ -91,17 +117,11 @@ linux_entry () - boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" - fi - if [ x$type != xsimple ] ; then -- case $type in -- recovery) -- title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;; -- *) -- title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;; -- esac -+ title=$(mktitle "$type" "$version") - if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then - replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')" - quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)" - title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" -- grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")" - fi - echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" - else diff --git a/SOURCES/0048-Add-friendly-grub2-password-config-tool-985962.patch b/SOURCES/0048-Add-friendly-grub2-password-config-tool-985962.patch deleted file mode 100644 index 9807d0e..0000000 --- a/SOURCES/0048-Add-friendly-grub2-password-config-tool-985962.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robert Marshall -Date: Thu, 25 Jun 2015 11:13:11 -0400 -Subject: [PATCH] Add friendly grub2 password config tool (#985962) - -Provided a tool for users to reset the grub2 root user password -without having to alter the grub.cfg. The hashed password now -lives in a root-only-readable configuration file. - -Resolves: rhbz#985962 - -Signed-off-by: Robert Marshall -[pjones: fix the efidir in grub-setpassword and rename tool] -Signed-off-by: Peter Jones -[luto: fix grub-setpassword -o's output path] -Andy Lutomirski ---- - configure.ac | 1 + - Makefile.util.def | 13 +++++ - util/grub-mkconfig.in | 2 + - util/grub-set-password.8 | 28 ++++++++++ - util/grub-set-password.in | 128 ++++++++++++++++++++++++++++++++++++++++++++++ - util/grub.d/01_users.in | 11 ++++ - 6 files changed, 183 insertions(+) - create mode 100644 util/grub-set-password.8 - create mode 100644 util/grub-set-password.in - create mode 100644 util/grub.d/01_users.in - -diff --git a/configure.ac b/configure.ac -index fdcb452581c..30fd84d8067 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -72,6 +72,7 @@ grub_TRANSFORM([grub-mkrelpath]) - grub_TRANSFORM([grub-mkrescue]) - grub_TRANSFORM([grub-probe]) - grub_TRANSFORM([grub-reboot]) -+grub_TRANSFORM([grub-set-password]) - grub_TRANSFORM([grub-rpm-sort]) - grub_TRANSFORM([grub-script-check]) - grub_TRANSFORM([grub-set-default]) -diff --git a/Makefile.util.def b/Makefile.util.def -index ba4cf4b29b0..1a7dd433e33 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -452,6 +452,12 @@ script = { - installdir = grubconf; - }; - -+script = { -+ name = '01_users'; -+ common = util/grub.d/01_users.in; -+ installdir = grubconf; -+}; -+ - script = { - name = '10_windows'; - common = util/grub.d/10_windows.in; -@@ -740,6 +746,13 @@ script = { - installdir = sbin; - }; - -+script = { -+ name = grub-set-password; -+ common = util/grub-set-password.in; -+ mansection = 8; -+ installdir = sbin; -+}; -+ - script = { - name = grub-mkconfig_lib; - common = util/grub-mkconfig_lib.in; -diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in -index 8ea2315ebc2..ba14cf6261c 100644 ---- a/util/grub-mkconfig.in -+++ b/util/grub-mkconfig.in -@@ -276,6 +276,8 @@ for i in "${grub_mkconfig_dir}"/* ; do - *~) ;; - # emacsen autosave files. FIXME: support other editors - */\#*\#) ;; -+ # rpm config files of yore. -+ *.rpmsave|*.rpmnew|*.rpmorig) ;; - *) - if grub_file_is_not_garbage "$i" && test -x "$i" ; then - echo -diff --git a/util/grub-set-password.8 b/util/grub-set-password.8 -new file mode 100644 -index 00000000000..9646546e43d ---- /dev/null -+++ b/util/grub-set-password.8 -@@ -0,0 +1,28 @@ -+.TH GRUB-SET-PASSWORD 3 "Thu Jun 25 2015" -+.SH NAME -+\fBgrub-set-password\fR \(em Generate the user.cfg file containing the hashed grub bootloader password. -+ -+.SH SYNOPSIS -+\fBgrub-set-password\fR [OPTION] -+ -+.SH DESCRIPTION -+\fBgrub-set-password\fR outputs the user.cfg file which contains the hashed GRUB bootloader password. This utility only supports configurations where there is a single root user. -+ -+The file has the format: -+GRUB2_PASSWORD=<\fIhashed password\fR>. -+ -+.SH OPTIONS -+.TP -+-h, --help -+Display program usage and exit. -+.TP -+-v, --version -+Display the current version. -+.TP -+-o, --output=<\fIDIRECTORY\fR> -+Choose the file path to which user.cfg will be written. -+ -+.SH SEE ALSO -+.BR "info grub" -+ -+.BR "info grub2-mkpasswd-pbkdf2" -diff --git a/util/grub-set-password.in b/util/grub-set-password.in -new file mode 100644 -index 00000000000..5ebf50576d6 ---- /dev/null -+++ b/util/grub-set-password.in -@@ -0,0 +1,128 @@ -+#!/bin/sh -e -+ -+EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/') -+if [ -d /sys/firmware/efi/efivars/ ]; then -+ grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` -+else -+ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` -+fi -+ -+PACKAGE_VERSION="@PACKAGE_VERSION@" -+PACKAGE_NAME="@PACKAGE_NAME@" -+self=`basename $0` -+bindir="@bindir@" -+grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@" -+ -+# Usage: usage -+# Print the usage. -+usage () { -+ cat < put user.cfg in a user-selected directory -+ -+Report bugs at https://bugzilla.redhat.com. -+EOF -+} -+ -+argument () { -+ opt=$1 -+ shift -+ -+ if test $# -eq 0; then -+ gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2 -+ exit 1 -+ fi -+ echo $1 -+} -+ -+# Ensure that it's the root user running this script -+if [ "${EUID}" -ne 0 ]; then -+ echo "The grub bootloader password may only be set by root." -+ usage -+ exit 2 -+fi -+ -+# Check the arguments. -+while test $# -gt 0 -+do -+ option=$1 -+ shift -+ -+ case "$option" in -+ -h | --help) -+ usage -+ exit 0 ;; -+ -v | --version) -+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" -+ exit 0 ;; -+ -o | --output) -+ OUTPUT_PATH=`argument $option "$@"`; shift ;; -+ --output=*) -+ OUTPUT_PATH=`echo "$option" | sed 's/--output=//'` ;; -+ -o=*) -+ OUTPUT_PATH=`echo "$option" | sed 's/-o=//'` ;; -+ esac -+done -+ -+# set user input or default path for user.cfg file -+if [ -z "${OUTPUT_PATH}" ]; then -+ OUTPUT_PATH="${grubdir}" -+fi -+ -+if [ ! -d "${OUTPUT_PATH}" ]; then -+ echo "${OUTPUT_PATH} does not exist." -+ usage -+ exit 2; -+fi -+ -+ttyopt=$(stty -g) -+fixtty() { -+ stty ${ttyopt} -+} -+ -+trap fixtty EXIT -+stty -echo -+ -+# prompt & confirm new grub2 root user password -+echo -n "Enter password: " -+read PASSWORD -+echo -+echo -n "Confirm password: " -+read PASSWORD_CONFIRM -+echo -+stty ${ttyopt} -+ -+getpass() { -+ local P0 -+ local P1 -+ P0="$1" && shift -+ P1="$1" && shift -+ -+ ( echo ${P0} ; echo ${P1} ) | \ -+ LC_ALL=C ${grub_mkpasswd} | \ -+ grep -v '[eE]nter password:' | \ -+ sed -e "s/PBKDF2 hash of your password is //" -+} -+ -+MYPASS="$(getpass "${PASSWORD}" "${PASSWORD_CONFIRM}")" -+if [ -z "${MYPASS}" ]; then -+ echo "${self}: error: empty password" 1>&2 -+ exit 1 -+fi -+ -+# on the ESP, these will fail to set the permissions, but it's okay because -+# the directory is protected. -+install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : -+chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : -+echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" -+ -+if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${OUTPUT_PATH}/grub.cfg"; then -+ echo "WARNING: The current configuration lacks password support!" -+ echo "Update your configuration with @grub_mkconfig@ to support this feature." -+fi -diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in -new file mode 100644 -index 00000000000..db2f44bfb78 ---- /dev/null -+++ b/util/grub.d/01_users.in -@@ -0,0 +1,11 @@ -+#!/bin/sh -e -+cat << EOF -+if [ -f \${prefix}/user.cfg ]; then -+ source \${prefix}/user.cfg -+ if [ -n "\${GRUB2_PASSWORD}" ]; then -+ set superusers="root" -+ export superusers -+ password_pbkdf2 root \${GRUB2_PASSWORD} -+ fi -+fi -+EOF diff --git a/SOURCES/0048-Grub-not-working-correctly-with-btrfs-snapshots-bsc-.patch b/SOURCES/0048-Grub-not-working-correctly-with-btrfs-snapshots-bsc-.patch new file mode 100644 index 0000000..99c106d --- /dev/null +++ b/SOURCES/0048-Grub-not-working-correctly-with-btrfs-snapshots-bsc-.patch @@ -0,0 +1,274 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 11 May 2017 08:56:57 +0000 +Subject: [PATCH] Grub not working correctly with btrfs snapshots (bsc#1026511) + +Signed-off-by: Michael Chang +Signed-off-by: Robbie Harwood +--- + grub-core/fs/btrfs.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 238 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 673ded0352..2b21cbaa67 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -2887,6 +2887,238 @@ out: + return 0; + } + ++static grub_err_t ++grub_btrfs_get_parent_subvol_path (struct grub_btrfs_data *data, ++ grub_uint64_t child_id, ++ const char *child_path, ++ grub_uint64_t *parent_id, ++ char **path_out) ++{ ++ grub_uint64_t fs_root = 0; ++ struct grub_btrfs_key key_in = { ++ .object_id = child_id, ++ .type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF, ++ .offset = 0, ++ }, key_out; ++ struct grub_btrfs_root_ref *ref; ++ char *buf; ++ struct grub_btrfs_leaf_descriptor desc; ++ grub_size_t elemsize; ++ grub_disk_addr_t elemaddr; ++ grub_err_t err; ++ char *parent_path; ++ ++ *parent_id = 0; ++ *path_out = 0; ++ ++ err = lower_bound(data, &key_in, &key_out, data->sblock.root_tree, ++ &elemaddr, &elemsize, &desc, 0); ++ if (err) ++ return err; ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF || elemaddr == 0) ++ next(data, &desc, &elemaddr, &elemsize, &key_out); ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF) ++ { ++ free_iterator(&desc); ++ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("can't find root backrefs")); ++ } ++ ++ buf = grub_malloc(elemsize + 1); ++ if (!buf) ++ { ++ free_iterator(&desc); ++ return grub_errno; ++ } ++ ++ err = grub_btrfs_read_logical(data, elemaddr, buf, elemsize, 0); ++ if (err) ++ { ++ grub_free(buf); ++ free_iterator(&desc); ++ return err; ++ } ++ ++ buf[elemsize] = 0; ++ ref = (struct grub_btrfs_root_ref *)buf; ++ ++ err = get_fs_root(data, data->sblock.root_tree, grub_le_to_cpu64 (key_out.offset), ++ 0, &fs_root); ++ if (err) ++ { ++ grub_free(buf); ++ free_iterator(&desc); ++ return err; ++ } ++ ++ find_pathname(data, grub_le_to_cpu64 (ref->dirid), fs_root, ref->name, &parent_path); ++ ++ if (child_path) ++ { ++ *path_out = grub_xasprintf ("%s/%s", parent_path, child_path); ++ grub_free (parent_path); ++ } ++ else ++ *path_out = parent_path; ++ ++ *parent_id = grub_le_to_cpu64 (key_out.offset); ++ ++ grub_free(buf); ++ free_iterator(&desc); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_btrfs_get_default_subvolume_id (struct grub_btrfs_data *data, grub_uint64_t *id) ++{ ++ grub_err_t err; ++ grub_disk_addr_t elemaddr; ++ grub_size_t elemsize; ++ struct grub_btrfs_key key, key_out; ++ struct grub_btrfs_dir_item *direl = NULL; ++ const char *ctoken = "default"; ++ grub_size_t ctokenlen = sizeof ("default") - 1; ++ ++ *id = 0; ++ key.object_id = data->sblock.root_dir_objectid; ++ key.type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key.offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen)); ++ err = lower_bound (data, &key, &key_out, data->sblock.root_tree, &elemaddr, &elemsize, ++ NULL, 0); ++ if (err) ++ return err; ++ ++ if (key_cmp (&key, &key_out) != 0) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); ++ ++ struct grub_btrfs_dir_item *cdirel; ++ direl = grub_malloc (elemsize + 1); ++ err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize, 0); ++ if (err) ++ { ++ grub_free (direl); ++ return err; ++ } ++ for (cdirel = direl; ++ (grub_uint8_t *) cdirel - (grub_uint8_t *) direl ++ < (grub_ssize_t) elemsize; ++ cdirel = (void *) ((grub_uint8_t *) (direl + 1) ++ + grub_le_to_cpu16 (cdirel->n) ++ + grub_le_to_cpu16 (cdirel->m))) ++ { ++ if (ctokenlen == grub_le_to_cpu16 (cdirel->n) ++ && grub_memcmp (cdirel->name, ctoken, ctokenlen) == 0) ++ break; ++ } ++ if ((grub_uint8_t *) cdirel - (grub_uint8_t *) direl ++ >= (grub_ssize_t) elemsize) ++ { ++ grub_free (direl); ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); ++ return err; ++ } ++ ++ if (cdirel->key.type != GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM) ++ { ++ grub_free (direl); ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); ++ return err; ++ } ++ ++ *id = grub_le_to_cpu64 (cdirel->key.object_id); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_btrfs_get_default_subvol (struct grub_extcmd_context *ctxt, ++ int argc, char **argv) ++{ ++ char *devname; ++ grub_device_t dev; ++ struct grub_btrfs_data *data; ++ grub_err_t err; ++ grub_uint64_t id; ++ char *subvol = NULL; ++ grub_uint64_t subvolid = 0; ++ char *varname = NULL; ++ char *output = NULL; ++ int path_only = ctxt->state[1].set; ++ int num_only = ctxt->state[2].set; ++ ++ if (ctxt->state[0].set) ++ varname = ctxt->state[0].arg; ++ ++ if (argc < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); ++ ++ devname = grub_file_get_device_name(argv[0]); ++ if (!devname) ++ return grub_errno; ++ ++ dev = grub_device_open (devname); ++ grub_free (devname); ++ if (!dev) ++ return grub_errno; ++ ++ data = grub_btrfs_mount(dev); ++ if (!data) ++ { ++ grub_device_close (dev); ++ grub_dprintf ("btrfs", "failed to open fs\n"); ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ ++ err = grub_btrfs_get_default_subvolume_id (data, &subvolid); ++ if (err) ++ { ++ grub_btrfs_unmount (data); ++ grub_device_close (dev); ++ return err; ++ } ++ ++ id = subvolid; ++ while (id != GRUB_BTRFS_ROOT_VOL_OBJECTID) ++ { ++ grub_uint64_t parent_id; ++ char *path_out; ++ ++ err = grub_btrfs_get_parent_subvol_path (data, grub_cpu_to_le64 (id), subvol, &parent_id, &path_out); ++ if (err) ++ { ++ grub_btrfs_unmount (data); ++ grub_device_close (dev); ++ return err; ++ } ++ ++ if (subvol) ++ grub_free (subvol); ++ subvol = path_out; ++ id = parent_id; ++ } ++ ++ if (num_only && path_only) ++ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T" /%s", subvolid, subvol); ++ else if (num_only) ++ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T, subvolid); ++ else ++ output = grub_xasprintf ("/%s", subvol); ++ ++ if (varname) ++ grub_env_set(varname, output); ++ else ++ grub_printf ("%s\n", output); ++ ++ grub_free (output); ++ grub_free (subvol); ++ ++ grub_btrfs_unmount (data); ++ grub_device_close (dev); ++ ++ return GRUB_ERR_NONE; ++} ++ + static struct grub_fs grub_btrfs_fs = { + .name = "btrfs", + .fs_dir = grub_btrfs_dir, +@@ -2905,6 +3137,7 @@ static struct grub_fs grub_btrfs_fs = { + static grub_command_t cmd_info; + static grub_command_t cmd_mount_subvol; + static grub_extcmd_t cmd_list_subvols; ++static grub_extcmd_t cmd_get_default_subvol; + + static char * + subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)), +@@ -2975,6 +3208,11 @@ GRUB_MOD_INIT (btrfs) + "[-p|-n] [-o var] DEVICE", + "Print list of BtrFS subvolumes on " + "DEVICE.", options); ++ cmd_get_default_subvol = grub_register_extcmd("btrfs-get-default-subvol", ++ grub_cmd_btrfs_get_default_subvol, 0, ++ "[-p|-n] [-o var] DEVICE", ++ "Print default BtrFS subvolume on " ++ "DEVICE.", options); + grub_register_variable_hook ("btrfs_subvol", subvol_get_env, + subvol_set_env); + grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env, diff --git a/SOURCES/0049-Add-grub_efi_allocate_pool-and-grub_efi_free_pool-wr.patch b/SOURCES/0049-Add-grub_efi_allocate_pool-and-grub_efi_free_pool-wr.patch new file mode 100644 index 0000000..d07dd27 --- /dev/null +++ b/SOURCES/0049-Add-grub_efi_allocate_pool-and-grub_efi_free_pool-wr.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 1 Jun 2017 09:59:56 -0400 +Subject: [PATCH] Add grub_efi_allocate_pool() and grub_efi_free_pool() + wrappers. + +Signed-off-by: Peter Jones +--- + include/grub/efi/efi.h | 36 ++++++++++++++++++++++++++++++++---- + 1 file changed, 32 insertions(+), 4 deletions(-) + +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 585fa6662b..03f9a9d011 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -24,6 +24,10 @@ + #include + #include + ++/* Variables. */ ++extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); ++extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); ++ + /* Functions. */ + void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol, + void *registration); +@@ -60,6 +64,33 @@ EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version); + void grub_efi_memory_fini (void); ++ ++static inline grub_efi_status_t ++__attribute__((__unused__)) ++grub_efi_allocate_pool (grub_efi_memory_type_t pool_type, ++ grub_efi_uintn_t buffer_size, ++ void **buffer) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_status_t status; ++ ++ b = grub_efi_system_table->boot_services; ++ status = efi_call_3 (b->allocate_pool, pool_type, buffer_size, buffer); ++ return status; ++} ++ ++static inline grub_efi_status_t ++__attribute__((__unused__)) ++grub_efi_free_pool (void *buffer) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_status_t status; ++ ++ b = grub_efi_system_table->boot_services; ++ status = efi_call_1 (b->free_pool, buffer); ++ return status; ++} ++ + grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (grub_efi_handle_t image_handle); + void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp); + char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); +@@ -115,10 +146,7 @@ void grub_efi_init (void); + void grub_efi_fini (void); + void grub_efi_set_prefix (void); + +-/* Variables. */ +-extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); +-extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); +- ++/* More variables. */ + extern int EXPORT_VAR(grub_efi_is_finished); + + struct grub_net_card; diff --git a/SOURCES/0049-tcp-add-window-scaling-support.patch b/SOURCES/0049-tcp-add-window-scaling-support.patch deleted file mode 100644 index 7d1996c..0000000 --- a/SOURCES/0049-tcp-add-window-scaling-support.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josef Bacik -Date: Wed, 12 Aug 2015 08:57:55 -0700 -Subject: [PATCH] tcp: add window scaling support - -Sometimes we have to provision boxes across regions, such as California to -Sweden. The http server has a 10 minute timeout, so if we can't get our 250mb -image transferred fast enough our provisioning fails, which is not ideal. So -add tcp window scaling on open connections and set the window size to 1mb. With -this change we're able to get higher sustained transfers between regions and can -transfer our image in well below 10 minutes. Without this patch we'd time out -every time halfway through the transfer. Thanks, - -Signed-off-by: Josef Bacik ---- - grub-core/net/tcp.c | 42 +++++++++++++++++++++++++++++------------- - 1 file changed, 29 insertions(+), 13 deletions(-) - -diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c -index e8ad34b84d4..7d4b822626d 100644 ---- a/grub-core/net/tcp.c -+++ b/grub-core/net/tcp.c -@@ -106,6 +106,18 @@ struct tcphdr - grub_uint16_t urgent; - } GRUB_PACKED; - -+struct tcp_scale_opt { -+ grub_uint8_t kind; -+ grub_uint8_t length; -+ grub_uint8_t scale; -+} GRUB_PACKED; -+ -+struct tcp_synhdr { -+ struct tcphdr tcphdr; -+ struct tcp_scale_opt scale_opt; -+ grub_uint8_t padding; -+}; -+ - struct tcp_pseudohdr - { - grub_uint32_t src; -@@ -566,7 +578,7 @@ grub_net_tcp_open (char *server, - grub_net_tcp_socket_t socket; - static grub_uint16_t in_port = 21550; - struct grub_net_buff *nb; -- struct tcphdr *tcph; -+ struct tcp_synhdr *tcph; - int i; - grub_uint8_t *nbd; - grub_net_link_level_address_t ll_target_addr; -@@ -635,20 +647,24 @@ grub_net_tcp_open (char *server, - } - - tcph = (void *) nb->data; -+ grub_memset(tcph, 0, sizeof (*tcph)); - socket->my_start_seq = grub_get_time_ms (); - socket->my_cur_seq = socket->my_start_seq + 1; -- socket->my_window = 8192; -- tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq); -- tcph->ack = grub_cpu_to_be32_compile_time (0); -- tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN); -- tcph->window = grub_cpu_to_be16 (socket->my_window); -- tcph->urgent = 0; -- tcph->src = grub_cpu_to_be16 (socket->in_port); -- tcph->dst = grub_cpu_to_be16 (socket->out_port); -- tcph->checksum = 0; -- tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, -- &socket->inf->address, -- &socket->out_nla); -+ socket->my_window = 32768; -+ tcph->tcphdr.seqnr = grub_cpu_to_be32 (socket->my_start_seq); -+ tcph->tcphdr.ack = grub_cpu_to_be32_compile_time (0); -+ tcph->tcphdr.flags = grub_cpu_to_be16_compile_time ((6 << 12) | TCP_SYN); -+ tcph->tcphdr.window = grub_cpu_to_be16 (socket->my_window); -+ tcph->tcphdr.urgent = 0; -+ tcph->tcphdr.src = grub_cpu_to_be16 (socket->in_port); -+ tcph->tcphdr.dst = grub_cpu_to_be16 (socket->out_port); -+ tcph->tcphdr.checksum = 0; -+ tcph->scale_opt.kind = 3; -+ tcph->scale_opt.length = 3; -+ tcph->scale_opt.scale = 5; -+ tcph->tcphdr.checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, -+ &socket->inf->address, -+ &socket->out_nla); - - tcp_socket_register (socket); - diff --git a/SOURCES/0050-Use-grub_efi_.-memory-helpers-where-reasonable.patch b/SOURCES/0050-Use-grub_efi_.-memory-helpers-where-reasonable.patch new file mode 100644 index 0000000..2a3d27b --- /dev/null +++ b/SOURCES/0050-Use-grub_efi_.-memory-helpers-where-reasonable.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 1 Jun 2017 10:06:38 -0400 +Subject: [PATCH] Use grub_efi_...() memory helpers where reasonable. + +This uses grub_efi_allocate_pool(), grub_efi_free_pool(), and +grub_efi_free_pages() instead of open-coded efi_call_N() calls, so we +get more reasonable type checking. + +Signed-off-by: Peter Jones +--- + grub-core/loader/efi/chainloader.c | 24 +++++++++--------------- + 1 file changed, 9 insertions(+), 15 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 07c4937898..89ac84cc66 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -65,7 +65,7 @@ grub_chainloader_unload (void) + + b = grub_efi_system_table->boot_services; + efi_call_1 (b->unload_image, image_handle); +- efi_call_2 (b->free_pages, address, pages); ++ grub_efi_free_pages (address, pages); + + grub_free (file_path); + grub_free (cmdline); +@@ -108,7 +108,7 @@ grub_chainloader_boot (void) + } + + if (exit_data) +- efi_call_1 (b->free_pool, exit_data); ++ grub_efi_free_pool (exit_data); + + grub_loader_unset (); + +@@ -527,10 +527,9 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp) + static grub_efi_boolean_t + handle_image (void *data, grub_efi_uint32_t datasize) + { +- grub_efi_boot_services_t *b; + grub_efi_loaded_image_t *li, li_bak; + grub_efi_status_t efi_status; +- char *buffer = NULL; ++ void *buffer = NULL; + char *buffer_aligned = NULL; + grub_efi_uint32_t i; + struct grub_pe32_section_table *section; +@@ -541,8 +540,6 @@ handle_image (void *data, grub_efi_uint32_t datasize) + int found_entry_point = 0; + int rc; + +- b = grub_efi_system_table->boot_services; +- + rc = read_header (data, datasize, &context); + if (rc < 0) + { +@@ -582,8 +579,8 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_dprintf ("chain", "image size is %08"PRIxGRUB_UINT64_T", datasize is %08x\n", + context.image_size, datasize); + +- efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, +- buffer_size, &buffer); ++ efi_status = grub_efi_allocate_pool (GRUB_EFI_LOADER_DATA, buffer_size, ++ &buffer); + + if (efi_status != GRUB_EFI_SUCCESS) + { +@@ -815,14 +812,14 @@ handle_image (void *data, grub_efi_uint32_t datasize) + + grub_dprintf ("chain", "entry_point returned %ld\n", efi_status); + grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); +- efi_status = efi_call_1 (b->free_pool, buffer); ++ efi_status = grub_efi_free_pool (buffer); + + return 1; + + error_exit: + grub_dprintf ("chain", "error_exit: grub_errno: %d\n", grub_errno); + if (buffer) +- efi_call_1 (b->free_pool, buffer); ++ grub_efi_free_pool (buffer); + + return 0; + } +@@ -830,10 +827,7 @@ error_exit: + static grub_err_t + grub_secureboot_chainloader_unload (void) + { +- grub_efi_boot_services_t *b; +- +- b = grub_efi_system_table->boot_services; +- efi_call_2 (b->free_pages, address, pages); ++ grub_efi_free_pages (address, pages); + grub_free (file_path); + grub_free (cmdline); + cmdline = 0; +@@ -1100,7 +1094,7 @@ fail: + grub_free (file_path); + + if (address) +- efi_call_2 (b->free_pages, address, pages); ++ grub_efi_free_pages (address, pages); + + if (cmdline) + grub_free (cmdline); diff --git a/SOURCES/0050-efinet-and-bootp-add-support-for-dhcpv6.patch b/SOURCES/0050-efinet-and-bootp-add-support-for-dhcpv6.patch deleted file mode 100644 index a9844b8..0000000 --- a/SOURCES/0050-efinet-and-bootp-add-support-for-dhcpv6.patch +++ /dev/null @@ -1,651 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 9 Jul 2019 11:47:37 +0200 -Subject: [PATCH] efinet and bootp: add support for dhcpv6 - -Signed-off-by: Peter Jones ---- - grub-core/net/bootp.c | 173 +++++++++++++++++++++++++++++++++++++ - grub-core/net/drivers/efi/efinet.c | 53 ++++++++++-- - grub-core/net/net.c | 72 +++++++++++++++ - grub-core/net/tftp.c | 4 + - include/grub/efi/api.h | 129 +++++++++++++++++++++++++-- - include/grub/net.h | 60 +++++++++++++ - 6 files changed, 477 insertions(+), 14 deletions(-) - -diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c -index 6fb5627025d..e28fb6a09f9 100644 ---- a/grub-core/net/bootp.c -+++ b/grub-core/net/bootp.c -@@ -902,6 +902,179 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), - - static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp; - -+struct grub_net_network_level_interface * -+grub_net_configure_by_dhcpv6_ack (const char *name, -+ struct grub_net_card *card, -+ grub_net_interface_flags_t flags -+ __attribute__((__unused__)), -+ const grub_net_link_level_address_t *hwaddr, -+ const struct grub_net_dhcpv6_packet *packet, -+ int is_def, char **device, char **path) -+{ -+ struct grub_net_network_level_interface *inter = NULL; -+ struct grub_net_network_level_address addr; -+ int mask = -1; -+ -+ if (!device || !path) -+ return NULL; -+ -+ *device = 0; -+ *path = 0; -+ -+ grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n", -+ hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2], -+ hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]); -+ -+ if (is_def) -+ grub_net_default_server = 0; -+ -+ if (is_def && !grub_net_default_server && packet) -+ { -+ const grub_uint8_t *options = packet->dhcp_options; -+ unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet); -+ unsigned int i; -+ -+ for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); ) -+ { -+ grub_uint16_t num, len; -+ grub_net_dhcpv6_option_t *opt = -+ (grub_net_dhcpv6_option_t *)(options + i); -+ -+ num = grub_be_to_cpu16(opt->option_num); -+ len = grub_be_to_cpu16(opt->option_len); -+ -+ grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len); -+ -+ if (len == 0) -+ break; -+ -+ if (len + i > 1024) -+ break; -+ -+ if (num == GRUB_NET_DHCP6_BOOTFILE_URL) -+ { -+ char *scheme, *userinfo, *host, *file; -+ char *tmp; -+ int hostlen; -+ int port; -+ int rc = extract_url_info ((const char *)opt->option_data, -+ (grub_size_t)len, -+ &scheme, &userinfo, &host, &port, -+ &file); -+ if (rc < 0) -+ continue; -+ -+ /* right now this only handles tftp. */ -+ if (grub_strcmp("tftp", scheme)) -+ { -+ grub_free (scheme); -+ grub_free (userinfo); -+ grub_free (host); -+ grub_free (file); -+ continue; -+ } -+ grub_free (userinfo); -+ -+ hostlen = grub_strlen (host); -+ if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']') -+ { -+ tmp = host+1; -+ host[hostlen-1] = '\0'; -+ } -+ else -+ tmp = host; -+ -+ *device = grub_xasprintf ("%s,%s", scheme, tmp); -+ grub_free (scheme); -+ grub_free (host); -+ -+ if (file && *file) -+ { -+ tmp = grub_strrchr (file, '/'); -+ if (tmp) -+ *(tmp+1) = '\0'; -+ else -+ file[0] = '\0'; -+ } -+ else if (!file) -+ file = grub_strdup (""); -+ -+ if (file[0] == '/') -+ { -+ *path = grub_strdup (file+1); -+ grub_free (file); -+ } -+ else -+ *path = file; -+ } -+ else if (num == GRUB_NET_DHCP6_IA_NA) -+ { -+ const grub_net_dhcpv6_option_t *ia_na_opt; -+ const grub_net_dhcpv6_opt_ia_na_t *ia_na = -+ (const grub_net_dhcpv6_opt_ia_na_t *)opt; -+ unsigned int left = len - OFFSET_OF (options, ia_na); -+ unsigned int j; -+ -+ if ((grub_uint8_t *)ia_na + left > -+ (grub_uint8_t *)options + option_max) -+ left -= ((grub_uint8_t *)ia_na + left) -+ - ((grub_uint8_t *)options + option_max); -+ -+ if (len < OFFSET_OF (option_data, opt) -+ + sizeof (grub_net_dhcpv6_option_t)) -+ { -+ grub_dprintf ("net", -+ "found dhcpv6 ia_na option with no address\n"); -+ continue; -+ } -+ -+ for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); ) -+ { -+ ia_na_opt = (const grub_net_dhcpv6_option_t *) -+ (ia_na->options + j); -+ grub_uint16_t ia_na_opt_num, ia_na_opt_len; -+ -+ ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num); -+ ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len); -+ if (ia_na_opt_len == 0) -+ break; -+ if (j + ia_na_opt_len > left) -+ break; -+ if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS) -+ { -+ const grub_net_dhcpv6_opt_ia_address_t *ia_addr; -+ -+ ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *) -+ ia_na_opt; -+ addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -+ grub_memcpy(addr.ipv6, ia_addr->ipv6_address, -+ sizeof (ia_addr->ipv6_address)); -+ inter = grub_net_add_addr (name, card, &addr, hwaddr, 0); -+ } -+ -+ j += ia_na_opt_len; -+ left -= ia_na_opt_len; -+ } -+ } -+ -+ i += len + 4; -+ } -+ -+ grub_print_error (); -+ } -+ -+ if (is_def) -+ { -+ grub_env_set ("net_default_interface", name); -+ grub_env_export ("net_default_interface"); -+ } -+ -+ if (inter) -+ grub_net_add_ipv6_local (inter, mask); -+ return inter; -+} -+ -+ - void - grub_bootp_init (void) - { -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index 5388f952ba9..173fb63153c 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -18,11 +18,14 @@ - - #include - #include -+#include - #include - #include - #include - #include - #include -+#include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -329,7 +332,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - char **path) - { - struct grub_net_card *card; -- grub_efi_device_path_t *dp; -+ grub_efi_device_path_t *dp, *ldp = NULL; - - dp = grub_efi_get_device_path (hnd); - if (! dp) -@@ -340,14 +343,19 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - grub_efi_device_path_t *cdp; - struct grub_efi_pxe *pxe; - struct grub_efi_pxe_mode *pxe_mode; -+ - if (card->driver != &efidriver) - continue; -+ - cdp = grub_efi_get_device_path (card->efi_handle); - if (! cdp) - continue; -+ -+ ldp = grub_efi_find_last_device_path (dp); -+ - if (grub_efi_compare_device_paths (dp, cdp) != 0) - { -- grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp; -+ grub_efi_device_path_t *dup_dp, *dup_ldp; - int match; - - /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6 -@@ -356,7 +364,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - devices. We skip them when enumerating cards, so here we need to - find matching MAC device. - */ -- ldp = grub_efi_find_last_device_path (dp); - if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE - || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE - && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) -@@ -373,16 +380,46 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - if (!match) - continue; - } -+ - pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, - GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (! pxe) - continue; -+ - pxe_mode = pxe->mode; -- grub_net_configure_by_dhcp_ack (card->name, card, 0, -- (struct grub_net_bootp_packet *) -- &pxe_mode->dhcp_ack, -- sizeof (pxe_mode->dhcp_ack), -- 1, device, path); -+ if (pxe_mode->using_ipv6) -+ { -+ grub_net_link_level_address_t hwaddr; -+ struct grub_net_network_level_interface *intf; -+ -+ grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); -+ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", -+ pxe_mode->dhcp_ack_received ? "yes" : "no", -+ pxe_mode->dhcp_ack_received ? "" : " cannot continue"); -+ if (!pxe_mode->dhcp_ack_received) -+ continue; -+ -+ hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -+ grub_memcpy (hwaddr.mac, -+ card->efi_net->mode->current_address, -+ sizeof (hwaddr.mac)); -+ -+ intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr, -+ (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6, -+ 1, device, path); -+ if (intf && device && path) -+ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); -+ } -+ else -+ { -+ grub_dprintf ("efinet", "using ipv4 and dhcp\n"); -+ grub_net_configure_by_dhcp_ack (card->name, card, 0, -+ (struct grub_net_bootp_packet *) -+ &pxe_mode->dhcp_ack, -+ sizeof (pxe_mode->dhcp_ack), -+ 1, device, path); -+ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); -+ } - return; - } - } -diff --git a/grub-core/net/net.c b/grub-core/net/net.c -index 0ef148f4adc..22f2689aaeb 100644 ---- a/grub-core/net/net.c -+++ b/grub-core/net/net.c -@@ -960,6 +960,78 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa - grub_net_network_level_interfaces = inter; - } - -+int -+grub_ipv6_get_masksize (grub_uint16_t be_mask[8]) -+{ -+ grub_uint8_t *mask; -+ grub_uint16_t mask16[8]; -+ int x, y; -+ int ret = 128; -+ -+ grub_memcpy (mask16, be_mask, sizeof (mask16)); -+ for (x = 0; x < 8; x++) -+ mask16[x] = grub_be_to_cpu16 (mask16[x]); -+ -+ mask = (grub_uint8_t *)mask16; -+ -+ for (x = 15; x >= 0; x--) -+ { -+ grub_uint8_t octet = mask[x]; -+ if (!octet) -+ { -+ ret -= 8; -+ continue; -+ } -+ for (y = 0; y < 8; y++) -+ { -+ if (octet & (1 << y)) -+ break; -+ else -+ ret--; -+ } -+ break; -+ } -+ -+ return ret; -+} -+ -+grub_err_t -+grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter, -+ int mask) -+{ -+ struct grub_net_route *route; -+ -+ if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) -+ return 0; -+ -+ if (mask == -1) -+ mask = grub_ipv6_get_masksize ((grub_uint16_t *)inter->address.ipv6); -+ -+ if (mask == -1) -+ return 0; -+ -+ route = grub_zalloc (sizeof (*route)); -+ if (!route) -+ return grub_errno; -+ -+ route->name = grub_xasprintf ("%s:local", inter->name); -+ if (!route->name) -+ { -+ grub_free (route); -+ return grub_errno; -+ } -+ -+ route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -+ grub_memcpy (route->target.ipv6.base, inter->address.ipv6, -+ sizeof (inter->address.ipv6)); -+ route->target.ipv6.masksize = mask; -+ route->is_gateway = 0; -+ route->interface = inter; -+ -+ grub_net_route_register (route); -+ -+ return 0; -+} - - grub_err_t - grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter, -diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c -index 7f44b30f521..4ab2f5c7357 100644 ---- a/grub-core/net/tftp.c -+++ b/grub-core/net/tftp.c -@@ -358,18 +358,22 @@ tftp_open (struct grub_file *file, const char *filename) - file->not_easily_seekable = 1; - file->data = data; - -+ grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server); - err = grub_net_resolve_address (file->device->net->server, &addr); - if (err) - { -+ grub_dprintf("tftp", "Address resolution failed: %d\n", err); - grub_free (data); - return err; - } - -+ grub_dprintf("tftp", "opening connection\n"); - data->sock = grub_net_udp_open (addr, - TFTP_SERVER_PORT, tftp_receive, - file); - if (!data->sock) - { -+ grub_dprintf("tftp", "connection failed\n"); - grub_free (data); - return grub_errno; - } -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index f1a52210c0c..117469450d3 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -592,10 +592,16 @@ typedef void *grub_efi_handle_t; - typedef void *grub_efi_event_t; - typedef grub_efi_uint64_t grub_efi_lba_t; - typedef grub_efi_uintn_t grub_efi_tpl_t; --typedef grub_uint8_t grub_efi_mac_address_t[32]; --typedef grub_uint8_t grub_efi_ipv4_address_t[4]; --typedef grub_uint16_t grub_efi_ipv6_address_t[8]; --typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4))); -+typedef grub_efi_uint8_t grub_efi_mac_address_t[32]; -+typedef grub_efi_uint8_t grub_efi_ipv4_address_t[4]; -+typedef grub_efi_uint8_t grub_efi_ipv6_address_t[16]; -+typedef union -+{ -+ grub_efi_uint32_t addr[4]; -+ grub_efi_ipv4_address_t v4; -+ grub_efi_ipv6_address_t v6; -+} grub_efi_ip_address_t __attribute__ ((aligned(4))); -+ - typedef grub_efi_uint64_t grub_efi_physical_address_t; - typedef grub_efi_uint64_t grub_efi_virtual_address_t; - -@@ -1474,16 +1480,127 @@ struct grub_efi_simple_text_output_interface - }; - typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t; - --typedef grub_uint8_t grub_efi_pxe_packet_t[1472]; -+typedef struct grub_efi_pxe_dhcpv4_packet -+{ -+ grub_efi_uint8_t bootp_opcode; -+ grub_efi_uint8_t bootp_hwtype; -+ grub_efi_uint8_t bootp_hwaddr_len; -+ grub_efi_uint8_t bootp_gate_hops; -+ grub_efi_uint32_t bootp_ident; -+ grub_efi_uint16_t bootp_seconds; -+ grub_efi_uint16_t bootp_flags; -+ grub_efi_uint8_t bootp_ci_addr[4]; -+ grub_efi_uint8_t bootp_yi_addr[4]; -+ grub_efi_uint8_t bootp_si_addr[4]; -+ grub_efi_uint8_t bootp_gi_addr[4]; -+ grub_efi_uint8_t bootp_hw_addr[16]; -+ grub_efi_uint8_t bootp_srv_name[64]; -+ grub_efi_uint8_t bootp_boot_file[128]; -+ grub_efi_uint32_t dhcp_magik; -+ grub_efi_uint8_t dhcp_options[56]; -+} grub_efi_pxe_dhcpv4_packet_t; -+ -+struct grub_efi_pxe_dhcpv6_packet -+{ -+ grub_efi_uint32_t message_type:8; -+ grub_efi_uint32_t transaction_id:24; -+ grub_efi_uint8_t dhcp_options[1024]; -+} GRUB_PACKED; -+typedef struct grub_efi_pxe_dhcpv6_packet grub_efi_pxe_dhcpv6_packet_t; -+ -+typedef union -+{ -+ grub_efi_uint8_t raw[1472]; -+ grub_efi_pxe_dhcpv4_packet_t dhcpv4; -+ grub_efi_pxe_dhcpv6_packet_t dhcpv6; -+} grub_efi_pxe_packet_t; -+ -+#define GRUB_EFI_PXE_MAX_IPCNT 8 -+#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8 -+#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8 -+ -+typedef struct grub_efi_pxe_ip_filter -+{ -+ grub_efi_uint8_t filters; -+ grub_efi_uint8_t ip_count; -+ grub_efi_uint8_t reserved; -+ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; -+} grub_efi_pxe_ip_filter_t; -+ -+typedef struct grub_efi_pxe_arp_entry -+{ -+ grub_efi_ip_address_t ip_addr; -+ grub_efi_mac_address_t mac_addr; -+} grub_efi_pxe_arp_entry_t; -+ -+typedef struct grub_efi_pxe_route_entry -+{ -+ grub_efi_ip_address_t ip_addr; -+ grub_efi_ip_address_t subnet_mask; -+ grub_efi_ip_address_t gateway_addr; -+} grub_efi_pxe_route_entry_t; -+ -+typedef struct grub_efi_pxe_icmp_error -+{ -+ grub_efi_uint8_t type; -+ grub_efi_uint8_t code; -+ grub_efi_uint16_t checksum; -+ union -+ { -+ grub_efi_uint32_t reserved; -+ grub_efi_uint32_t mtu; -+ grub_efi_uint32_t pointer; -+ struct -+ { -+ grub_efi_uint16_t identifier; -+ grub_efi_uint16_t sequence; -+ } echo; -+ } u; -+ grub_efi_uint8_t data[494]; -+} grub_efi_pxe_icmp_error_t; -+ -+typedef struct grub_efi_pxe_tftp_error -+{ -+ grub_efi_uint8_t error_code; -+ grub_efi_char8_t error_string[127]; -+} grub_efi_pxe_tftp_error_t; - - typedef struct grub_efi_pxe_mode - { -- grub_uint8_t unused[52]; -+ grub_efi_boolean_t started; -+ grub_efi_boolean_t ipv6_available; -+ grub_efi_boolean_t ipv6_supported; -+ grub_efi_boolean_t using_ipv6; -+ grub_efi_boolean_t bis_supported; -+ grub_efi_boolean_t bis_detected; -+ grub_efi_boolean_t auto_arp; -+ grub_efi_boolean_t send_guid; -+ grub_efi_boolean_t dhcp_discover_valid; -+ grub_efi_boolean_t dhcp_ack_received; -+ grub_efi_boolean_t proxy_offer_received; -+ grub_efi_boolean_t pxe_discover_valid; -+ grub_efi_boolean_t pxe_reply_received; -+ grub_efi_boolean_t pxe_bis_reply_received; -+ grub_efi_boolean_t icmp_error_received; -+ grub_efi_boolean_t tftp_error_received; -+ grub_efi_boolean_t make_callbacks; -+ grub_efi_uint8_t ttl; -+ grub_efi_uint8_t tos; -+ grub_efi_ip_address_t station_ip; -+ grub_efi_ip_address_t subnet_mask; - grub_efi_pxe_packet_t dhcp_discover; - grub_efi_pxe_packet_t dhcp_ack; - grub_efi_pxe_packet_t proxy_offer; - grub_efi_pxe_packet_t pxe_discover; - grub_efi_pxe_packet_t pxe_reply; -+ grub_efi_pxe_packet_t pxe_bis_reply; -+ grub_efi_pxe_ip_filter_t ip_filter; -+ grub_efi_uint32_t arp_cache_entries; -+ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES]; -+ grub_efi_uint32_t route_table_entries; -+ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES]; -+ grub_efi_pxe_icmp_error_t icmp_error; -+ grub_efi_pxe_tftp_error_t tftp_error; - } grub_efi_pxe_mode_t; - - typedef struct grub_efi_pxe -diff --git a/include/grub/net.h b/include/grub/net.h -index 7ae4b6bd805..8a05ec4fe7a 100644 ---- a/include/grub/net.h -+++ b/include/grub/net.h -@@ -447,6 +447,51 @@ struct grub_net_bootp_packet - grub_uint8_t vendor[0]; - } GRUB_PACKED; - -+enum -+ { -+ GRUB_NET_DHCP6_IA_NA = 3, -+ GRUB_NET_DHCP6_IA_ADDRESS = 5, -+ GRUB_NET_DHCP6_BOOTFILE_URL = 59, -+ }; -+ -+struct grub_net_dhcpv6_option -+{ -+ grub_uint16_t option_num; -+ grub_uint16_t option_len; -+ grub_uint8_t option_data[]; -+} GRUB_PACKED; -+typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t; -+ -+struct grub_net_dhcpv6_opt_ia_na -+{ -+ grub_uint16_t option_num; -+ grub_uint16_t option_len; -+ grub_uint32_t iaid; -+ grub_uint32_t t1; -+ grub_uint32_t t2; -+ grub_uint8_t options[]; -+} GRUB_PACKED; -+typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t; -+ -+struct grub_net_dhcpv6_opt_ia_address -+{ -+ grub_uint16_t option_num; -+ grub_uint16_t option_len; -+ grub_uint64_t ipv6_address[2]; -+ grub_uint32_t preferred_lifetime; -+ grub_uint32_t valid_lifetime; -+ grub_uint8_t options[]; -+} GRUB_PACKED; -+typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t; -+ -+struct grub_net_dhcpv6_packet -+{ -+ grub_uint32_t message_type:8; -+ grub_uint32_t transaction_id:24; -+ grub_uint8_t dhcp_options[1024]; -+} GRUB_PACKED; -+typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t; -+ - #define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 - #define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 - #define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 -@@ -482,6 +527,21 @@ grub_net_configure_by_dhcp_ack (const char *name, - grub_size_t size, - int is_def, char **device, char **path); - -+struct grub_net_network_level_interface * -+grub_net_configure_by_dhcpv6_ack (const char *name, -+ struct grub_net_card *card, -+ grub_net_interface_flags_t flags, -+ const grub_net_link_level_address_t *hwaddr, -+ const struct grub_net_dhcpv6_packet *packet, -+ int is_def, char **device, char **path); -+ -+int -+grub_ipv6_get_masksize(grub_uint16_t *mask); -+ -+grub_err_t -+grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf, -+ int mask); -+ - grub_err_t - grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf, - int mask); diff --git a/SOURCES/0051-Add-PRIxGRUB_EFI_STATUS-and-use-it.patch b/SOURCES/0051-Add-PRIxGRUB_EFI_STATUS-and-use-it.patch new file mode 100644 index 0000000..f649c8c --- /dev/null +++ b/SOURCES/0051-Add-PRIxGRUB_EFI_STATUS-and-use-it.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 1 Jun 2017 10:07:50 -0400 +Subject: [PATCH] Add PRIxGRUB_EFI_STATUS and use it. + +This avoids syntax checkers getting confused about if it's llx or lx. + +Signed-off-by: Peter Jones +--- + grub-core/loader/efi/chainloader.c | 3 ++- + include/grub/efi/api.h | 9 +++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 89ac84cc66..ac8dfd40c6 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -810,7 +810,8 @@ handle_image (void *data, grub_efi_uint32_t datasize) + efi_status = efi_call_2 (entry_point, grub_efi_image_handle, + grub_efi_system_table); + +- grub_dprintf ("chain", "entry_point returned %ld\n", efi_status); ++ grub_dprintf ("chain", "entry_point returned 0x%"PRIxGRUB_EFI_STATUS"\n", ++ efi_status); + grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); + efi_status = grub_efi_free_pool (buffer); + +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 117469450d..9962880147 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -546,7 +546,16 @@ typedef grub_uint64_t grub_efi_uint64_t; + typedef grub_uint8_t grub_efi_char8_t; + typedef grub_uint16_t grub_efi_char16_t; + ++ + typedef grub_efi_uintn_t grub_efi_status_t; ++/* Make grub_efi_status_t reasonably printable. */ ++#if GRUB_CPU_SIZEOF_VOID_P == 8 ++#define PRIxGRUB_EFI_STATUS "lx" ++#define PRIdGRUB_EFI_STATUS "ld" ++#else ++#define PRIxGRUB_EFI_STATUS "llx" ++#define PRIdGRUB_EFI_STATUS "lld" ++#endif + + #define GRUB_EFI_ERROR_CODE(value) \ + ((((grub_efi_status_t) 1) << (sizeof (grub_efi_status_t) * 8 - 1)) | (value)) diff --git a/SOURCES/0051-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch b/SOURCES/0051-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch deleted file mode 100644 index e799ac1..0000000 --- a/SOURCES/0051-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 23 Jun 2016 11:01:39 -0400 -Subject: [PATCH] Add grub-get-kernel-settings and use it in 10_linux - -This patch adds grub-get-kernel-settings, which reads the system kernel -installation configuration from /etc/sysconfig/kernel, and outputs -${GRUB_...} variables suitable for evaluation by grub-mkconfig. Those -variables are then used by 10_linux to choose whether or not to create -debug stanzas. - -Resolves: rhbz#1226325 ---- - configure.ac | 2 + - Makefile.util.def | 7 ++ - util/bash-completion.d/grub-completion.bash.in | 22 +++++++ - util/grub-get-kernel-settings.3 | 20 ++++++ - util/grub-get-kernel-settings.in | 88 ++++++++++++++++++++++++++ - util/grub-mkconfig.in | 3 + - util/grub.d/10_linux.in | 23 +++++-- - 7 files changed, 160 insertions(+), 5 deletions(-) - create mode 100644 util/grub-get-kernel-settings.3 - create mode 100644 util/grub-get-kernel-settings.in - -diff --git a/configure.ac b/configure.ac -index 30fd84d8067..ed31ea457d2 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-install]) - grub_TRANSFORM([grub-mkconfig]) - grub_TRANSFORM([grub-mkfont]) - grub_TRANSFORM([grub-mkimage]) -+grub_TRANSFORM([grub-get-kernel-settings]) - grub_TRANSFORM([grub-glue-efi]) - grub_TRANSFORM([grub-mklayout]) - grub_TRANSFORM([grub-mkpasswd-pbkdf2]) -@@ -82,6 +83,7 @@ grub_TRANSFORM([grub-file]) - grub_TRANSFORM([grub-bios-setup.3]) - grub_TRANSFORM([grub-editenv.1]) - grub_TRANSFORM([grub-fstest.3]) -+grub_TRANSFORM([grub-get-kernel-settings.3]) - grub_TRANSFORM([grub-glue-efi.3]) - grub_TRANSFORM([grub-install.1]) - grub_TRANSFORM([grub-kbdcomp.3]) -diff --git a/Makefile.util.def b/Makefile.util.def -index 1a7dd433e33..cdd2f51fe4b 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -732,6 +732,13 @@ script = { - installdir = sbin; - }; - -+script = { -+ name = grub-get-kernel-settings; -+ common = util/grub-get-kernel-settings.in; -+ mansection = 3; -+ installdir = sbin; -+}; -+ - script = { - name = grub-set-default; - common = util/grub-set-default.in; -diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in -index 44bf135b9f8..5c4acd496d4 100644 ---- a/util/bash-completion.d/grub-completion.bash.in -+++ b/util/bash-completion.d/grub-completion.bash.in -@@ -264,6 +264,28 @@ have ${__grub_sparc64_setup_program} && \ - unset __grub_sparc64_setup_program - - -+# -+# grub-get-kernel-settings -+# -+_grub_get_kernel_settings () { -+ local cur -+ -+ COMPREPLY=() -+ cur=`_get_cword` -+ -+ if [[ "$cur" == -* ]]; then -+ __grubcomp "$(__grub_get_options_from_help)" -+ else -+ # Default complete with a filename -+ _filedir -+ fi -+} -+__grub_get_kernel_settings_program="@grub_get_kernel_settings@" -+have ${__grub_get_kernel_settings_program} && \ -+ complete -F _grub_get_kernel_settings -o filenames ${__grub_get_kernel_settings_program} -+unset __grub_get_kernel_settings_program -+ -+ - # - # grub-install - # -diff --git a/util/grub-get-kernel-settings.3 b/util/grub-get-kernel-settings.3 -new file mode 100644 -index 00000000000..ba33330e28d ---- /dev/null -+++ b/util/grub-get-kernel-settings.3 -@@ -0,0 +1,20 @@ -+.TH GRUB-GET-KERNEL-SETTINGS 3 "Thu Jun 25 2015" -+.SH NAME -+\fBgrub-get-kernel-settings\fR \(em Evaluate the system's kernel installation settings for use while making a grub configuration file. -+ -+.SH SYNOPSIS -+\fBgrub-get-kernel-settings\fR [OPTION] -+ -+.SH DESCRIPTION -+\fBgrub-get-kernel-settings\fR reads the kernel installation settings on the host system, and emits a set of grub settings suitable for use when creating a grub configuration file. -+ -+.SH OPTIONS -+.TP -+-h, --help -+Display program usage and exit. -+.TP -+-v, --version -+Display the current version. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in -new file mode 100644 -index 00000000000..7e87dfccc0e ---- /dev/null -+++ b/util/grub-get-kernel-settings.in -@@ -0,0 +1,88 @@ -+#!/bin/sh -+set -e -+ -+# Evaluate new-kernel-pkg's configuration file. -+# Copyright (C) 2016 Free Software Foundation, Inc. -+# -+# GRUB is free software: you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation, either version 3 of the License, or -+# (at your option) any later version. -+# -+# GRUB is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with GRUB. If not, see . -+ -+PACKAGE_NAME=@PACKAGE_NAME@ -+PACKAGE_VERSION=@PACKAGE_VERSION@ -+datadir="@datadir@" -+if [ "x$pkgdatadir" = x ]; then -+ pkgdatadir="${datadir}/@PACKAGE@" -+fi -+ -+self=`basename $0` -+ -+export TEXTDOMAIN=@PACKAGE@ -+export TEXTDOMAINDIR="@localedir@" -+ -+. "${pkgdatadir}/grub-mkconfig_lib" -+ -+# Usage: usage -+# Print the usage. -+usage () { -+ gettext_printf "Usage: %s [OPTION]\n" "$self" -+ gettext "Evaluate new-kernel-pkg configuration"; echo -+ echo -+ print_option_help "-h, --help" "$(gettext "print this message and exit")" -+ print_option_help "-v, --version" "$(gettext "print the version information and exit")" -+ echo -+} -+ -+# Check the arguments. -+while test $# -gt 0 -+do -+ option=$1 -+ shift -+ -+ case "$option" in -+ -h | --help) -+ usage -+ exit 0 ;; -+ -v | --version) -+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" -+ exit 0 ;; -+ -*) -+ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 -+ usage -+ exit 1 -+ ;; -+ # Explicitly ignore non-option arguments, for compatibility. -+ esac -+done -+ -+if test -f /etc/sysconfig/kernel ; then -+ . /etc/sysconfig/kernel -+fi -+ -+if [ "$MAKEDEBUG" = "yes" ]; then -+ echo GRUB_LINUX_MAKE_DEBUG=true -+ echo export GRUB_LINUX_MAKE_DEBUG -+ echo GRUB_CMDLINE_LINUX_DEBUG=\"systemd.log_level=debug systemd.log_target=kmsg\" -+ echo export GRUB_CMDLINE_LINUX_DEBUG -+ echo GRUB_LINUX_DEBUG_TITLE_POSTFIX=\" with debugging\" -+ echo export GRUB_LINUX_DEBUG_TITLE_POSTFIX -+fi -+if [ "$DEFAULTDEBUG" = "yes" ]; then -+ echo GRUB_DEFAULT_TO_DEBUG=true -+else -+ echo GRUB_DEFAULT_TO_DEBUG=false -+fi -+echo export GRUB_DEFAULT_TO_DEBUG -+if [ "$UPDATEDEFAULT" = "yes" ]; then -+ echo GRUB_UPDATE_DEFAULT_KERNEL=true -+ echo export GRUB_UPDATE_DEFAULT_KERNEL -+fi -diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in -index ba14cf6261c..005f093809b 100644 ---- a/util/grub-mkconfig.in -+++ b/util/grub-mkconfig.in -@@ -45,6 +45,7 @@ grub_probe="${sbindir}/@grub_probe@" - grub_file="${bindir}/@grub_file@" - grub_editenv="${bindir}/@grub_editenv@" - grub_script_check="${bindir}/@grub_script_check@" -+grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@" - - export TEXTDOMAIN=@PACKAGE@ - export TEXTDOMAINDIR="@localedir@" -@@ -158,6 +159,8 @@ if test -f ${sysconfdir}/default/grub ; then - . ${sysconfdir}/default/grub - fi - -+eval "$("${grub_get_kernel_settings}")" || true -+ - if [ "x${GRUB_DISABLE_UUID}" = "xtrue" ]; then - if [ -z "${GRUB_DISABLE_LINUX_UUID}" ]; then - GRUB_DISABLE_LINUX_UUID="true" -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 2e59f3b4197..0f3c19e30cc 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -111,7 +111,8 @@ linux_entry () - os="$1" - version="$2" - type="$3" -- args="$4" -+ isdebug="$4" -+ args="$5" - - if [ -z "$boot_device_id" ]; then - boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" -@@ -123,6 +124,9 @@ linux_entry () - quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)" - title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" - fi -+ if [ x$isdebug = xdebug ]; then -+ title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}" -+ fi - echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" - else - echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" -@@ -299,11 +303,15 @@ while [ "x$list" != "x" ] ; do - fi - - if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then -- linux_entry "${OS}" "${version}" simple \ -+ linux_entry "${OS}" "${version}" simple standard \ - "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" -+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then -+ linux_entry "${OS}" "${version}" simple debug \ -+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}" -+ fi - - submenu_indentation="$grub_tab" -- -+ - if [ -z "$boot_device_id" ]; then - boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" - fi -@@ -312,10 +320,15 @@ while [ "x$list" != "x" ] ; do - is_top_level=false - fi - -- linux_entry "${OS}" "${version}" advanced \ -+ linux_entry "${OS}" "${version}" advanced standard \ - "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" -+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then -+ linux_entry "${OS}" "${version}" advanced debug \ -+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}" -+ fi -+ - if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then -- linux_entry "${OS}" "${version}" recovery \ -+ linux_entry "${OS}" "${version}" recovery standard \ - "single ${GRUB_CMDLINE_LINUX}" - fi - diff --git a/SOURCES/0052-bz1374141-fix-incorrect-mask-for-ppc64.patch b/SOURCES/0052-bz1374141-fix-incorrect-mask-for-ppc64.patch deleted file mode 100644 index 1bb2658..0000000 --- a/SOURCES/0052-bz1374141-fix-incorrect-mask-for-ppc64.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Masahiro Matsuya -Date: Sat, 29 Oct 2016 08:35:26 +0900 -Subject: [PATCH] bz1374141 fix incorrect mask for ppc64 - -The netmask configured in firmware is not respected on ppc64 (big endian). -When 255.255.252.0 is set as netmask in firmware, the following is the value of bootpath string in grub_ieee1275_parse_bootpath(). - - /vdevice/l-lan@30000002:speed=auto,duplex=auto,192.168.88.10,,192.168.89.113,192.168.88.1,5,5,255.255.252.0,512 - -The netmask in this bootpath is no problem, since it's a value specified in firmware. But, -The value of 'subnet_mask.ipv4' was set with 0xfffffc00, and __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)) returned 16 (not 22). -As a result, 16 was used for netmask wrongly. - -1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00) -0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4) -1111 1111 0000 0011 0000 0000 0000 0000 # ~grub_le_to_cpu32 (subnet_mask.ipv4) - -And, the count of zero with __builtin_ctz can be 16. -This patch changes it as below. - -1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00) -0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4) -1111 1111 1111 1111 1111 1100 0000 0000 # grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)) -0000 0000 0000 0000 0000 0011 1111 1111 # ~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)) - -The count of zero with __builtin_clz can be 22. (clz counts the number of one bits preceding the most significant zero bit) ---- - grub-core/net/drivers/ieee1275/ofnet.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c -index ac4e62a95c9..3860b6f78d8 100644 ---- a/grub-core/net/drivers/ieee1275/ofnet.c -+++ b/grub-core/net/drivers/ieee1275/ofnet.c -@@ -220,8 +220,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath, - flags); - inter->vlantag = vlantag; - grub_net_add_ipv4_local (inter, -- __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4))); -- -+ __builtin_clz (~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)))); - } - - if (gateway_addr.ipv4 != 0) diff --git a/SOURCES/0052-don-t-use-int-for-efi-status.patch b/SOURCES/0052-don-t-use-int-for-efi-status.patch new file mode 100644 index 0000000..4d48e37 --- /dev/null +++ b/SOURCES/0052-don-t-use-int-for-efi-status.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 26 Jun 2017 12:44:59 -0400 +Subject: [PATCH] don't use int for efi status + +--- + grub-core/kern/efi/efi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 05d8237a9b..ae9885edb8 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -167,7 +167,7 @@ grub_reboot (void) + void + grub_exit (int retval) + { +- int rc = GRUB_EFI_LOAD_ERROR; ++ grub_efi_status_t rc = GRUB_EFI_LOAD_ERROR; + + if (retval == 0) + rc = GRUB_EFI_SUCCESS; diff --git a/SOURCES/0053-Make-grub_fatal-also-backtrace.patch b/SOURCES/0053-Make-grub_fatal-also-backtrace.patch deleted file mode 100644 index 3534b05..0000000 --- a/SOURCES/0053-Make-grub_fatal-also-backtrace.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 27 Jan 2016 09:22:42 -0500 -Subject: [PATCH] Make grub_fatal() also backtrace. - ---- - grub-core/Makefile.core.def | 3 ++ - grub-core/kern/misc.c | 8 +++++- - grub-core/lib/arm64/backtrace.c | 62 +++++++++++++++++++++++++++++++++++++++++ - grub-core/lib/backtrace.c | 2 ++ - grub-core/lib/i386/backtrace.c | 14 +++++++++- - 5 files changed, 87 insertions(+), 2 deletions(-) - create mode 100644 grub-core/lib/arm64/backtrace.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index c15e91943b9..058c88ac3af 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -188,6 +188,9 @@ kernel = { - - softdiv = lib/division.c; - -+ x86 = lib/i386/backtrace.c; -+ x86 = lib/backtrace.c; -+ - i386 = kern/i386/dl.c; - i386_xen = kern/i386/dl.c; - i386_xen_pvh = kern/i386/dl.c; -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index 63b586d09cb..a3e215155bd 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - union printf_arg - { -@@ -1199,8 +1200,13 @@ grub_printf_fmt_check (const char *fmt, const char *fmt_expected) - static void __attribute__ ((noreturn)) - grub_abort (void) - { -+#ifndef GRUB_UTIL -+#if defined(__i386__) || defined(__x86_64__) -+ grub_backtrace(); -+#endif -+#endif - grub_printf ("\nAborted."); -- -+ - #ifndef GRUB_UTIL - if (grub_term_inputs) - #endif -diff --git a/grub-core/lib/arm64/backtrace.c b/grub-core/lib/arm64/backtrace.c -new file mode 100644 -index 00000000000..1079b5380e1 ---- /dev/null -+++ b/grub-core/lib/arm64/backtrace.c -@@ -0,0 +1,62 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2009 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_STACK_FRAME 102400 -+ -+void -+grub_backtrace_pointer (int frame) -+{ -+ while (1) -+ { -+ void *lp = __builtin_return_address (frame); -+ if (!lp) -+ break; -+ -+ lp = __builtin_extract_return_addr (lp); -+ -+ grub_printf ("%p: ", lp); -+ grub_backtrace_print_address (lp); -+ grub_printf (" ("); -+ for (i = 0; i < 2; i++) -+ grub_printf ("%p,", ((void **)ptr) [i + 2]); -+ grub_printf ("%p)\n", ((void **)ptr) [i + 2]); -+ nptr = *(void **)ptr; -+ if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME -+ || nptr == ptr) -+ { -+ grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr); -+ break; -+ } -+ ptr = nptr; -+ } -+} -+ -+void -+grub_backtrace (void) -+{ -+ grub_backtrace_pointer (1); -+} -+ -diff --git a/grub-core/lib/backtrace.c b/grub-core/lib/backtrace.c -index 825a8800e25..c0ad6ab8be1 100644 ---- a/grub-core/lib/backtrace.c -+++ b/grub-core/lib/backtrace.c -@@ -29,6 +29,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - void - grub_backtrace_print_address (void *addr) - { -+#ifndef GRUB_UTIL - grub_dl_t mod; - - FOR_DL_MODULES (mod) -@@ -44,6 +45,7 @@ grub_backtrace_print_address (void *addr) - } - } - -+#endif - grub_printf ("%p", addr); - } - -diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c -index c3e03c7275c..c67273db3ae 100644 ---- a/grub-core/lib/i386/backtrace.c -+++ b/grub-core/lib/i386/backtrace.c -@@ -15,11 +15,23 @@ - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ -+#include -+#ifdef GRUB_UTIL -+#define REALLY_GRUB_UTIL GRUB_UTIL -+#undef GRUB_UTIL -+#endif -+ -+#include -+#include -+ -+#ifdef REALLY_GRUB_UTIL -+#define GRUB_UTIL REALLY_GRUB_UTIL -+#undef REALLY_GRUB_UTIL -+#endif - - #include - #include - #include --#include - #include - #include - #include diff --git a/SOURCES/0053-make-GRUB_MOD_INIT-declare-its-function-prototypes.patch b/SOURCES/0053-make-GRUB_MOD_INIT-declare-its-function-prototypes.patch new file mode 100644 index 0000000..fb71ea5 --- /dev/null +++ b/SOURCES/0053-make-GRUB_MOD_INIT-declare-its-function-prototypes.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 26 Jun 2017 12:46:23 -0400 +Subject: [PATCH] make GRUB_MOD_INIT() declare its function prototypes. + +--- + include/grub/dl.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/grub/dl.h b/include/grub/dl.h +index b3753c9ca2..91933b85f2 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -54,6 +54,7 @@ grub_mod_fini (void) + + #define GRUB_MOD_INIT(name) \ + static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \ ++extern void grub_##name##_init (void); \ + void \ + grub_##name##_init (void) { grub_mod_init (0); } \ + static void \ +@@ -61,6 +62,7 @@ grub_mod_init (grub_dl_t mod __attribute__ ((unused))) + + #define GRUB_MOD_FINI(name) \ + static void grub_mod_fini (void) __attribute__ ((used)); \ ++extern void grub_##name##_fini (void); \ + void \ + grub_##name##_fini (void) { grub_mod_fini (); } \ + static void \ diff --git a/SOURCES/0054-Don-t-guess-boot-efi-as-HFS-on-ppc-machines-in-grub-.patch b/SOURCES/0054-Don-t-guess-boot-efi-as-HFS-on-ppc-machines-in-grub-.patch new file mode 100644 index 0000000..ae8a8c6 --- /dev/null +++ b/SOURCES/0054-Don-t-guess-boot-efi-as-HFS-on-ppc-machines-in-grub-.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 20 Apr 2017 13:29:06 -0400 +Subject: [PATCH] Don't guess /boot/efi/ as HFS+ on ppc machines in + grub-install + +This should never be trying this, and since we've consolidated the +grubenv to always be on /boot/efi/EFI/fedora/, this code causes it to +always make the wrong decision. + +Resolves: rhbz#1484474 + +Signed-off-by: Peter Jones +--- + util/grub-install.c | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 84ed6e88ec..a2bec7446c 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -1190,18 +1190,8 @@ main (int argc, char *argv[]) + char *d; + + is_guess = 1; +- d = grub_util_path_concat (2, bootdir, "macppc"); +- if (!grub_util_is_directory (d)) +- { +- free (d); +- d = grub_util_path_concat (2, bootdir, "efi"); +- } + /* Find the Mac HFS(+) System Partition. */ +- if (!grub_util_is_directory (d)) +- { +- free (d); +- d = grub_util_path_concat (2, bootdir, "EFI"); +- } ++ d = grub_util_path_concat (2, bootdir, "macppc"); + if (!grub_util_is_directory (d)) + { + free (d); diff --git a/SOURCES/0054-Fix-up-some-man-pages-rpmdiff-noticed.patch b/SOURCES/0054-Fix-up-some-man-pages-rpmdiff-noticed.patch deleted file mode 100644 index 8016a62..0000000 --- a/SOURCES/0054-Fix-up-some-man-pages-rpmdiff-noticed.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 23 Sep 2014 09:58:49 -0400 -Subject: [PATCH] Fix up some man pages rpmdiff noticed. - ---- - configure.ac | 2 ++ - util/grub-macbless.8 | 26 +++++++++++++++++++ - util/grub-mkimage.1 | 2 +- - util/grub-syslinux2cfg.1 | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 94 insertions(+), 1 deletion(-) - create mode 100644 util/grub-macbless.8 - create mode 100644 util/grub-syslinux2cfg.1 - -diff --git a/configure.ac b/configure.ac -index ed31ea457d2..537ed411469 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -87,6 +87,7 @@ grub_TRANSFORM([grub-get-kernel-settings.3]) - grub_TRANSFORM([grub-glue-efi.3]) - grub_TRANSFORM([grub-install.1]) - grub_TRANSFORM([grub-kbdcomp.3]) -+grub_TRANSFORM([grub-macbless.8]) - grub_TRANSFORM([grub-menulst2cfg.1]) - grub_TRANSFORM([grub-mkconfig.1]) - grub_TRANSFORM([grub-mkfont.3]) -@@ -105,6 +106,7 @@ grub_TRANSFORM([grub-render-label.3]) - grub_TRANSFORM([grub-script-check.3]) - grub_TRANSFORM([grub-set-default.1]) - grub_TRANSFORM([grub-sparc64-setup.3]) -+grub_TRANSFORM([grub-syslinux2cfg.1]) - - # Optimization flag. Allow user to override. - if test "x$TARGET_CFLAGS" = x; then -diff --git a/util/grub-macbless.8 b/util/grub-macbless.8 -new file mode 100644 -index 00000000000..ae842f3a606 ---- /dev/null -+++ b/util/grub-macbless.8 -@@ -0,0 +1,26 @@ -+.TH GRUB-MACBLESS 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-macbless\fR \(em Mac-style bless utility for HFS or HFS+ -+ -+.SH SYNOPSIS -+\fBgrub-macbless\fR [-p | --ppc] [-v | --verbose] [-x | --x86] \fIFILE\fR -+ -+.SH DESCRIPTION -+\fBgrub-mkimage\fR blesses a file on an HFS or HFS+ file system, so that it -+can be used to boot a Mac. -+ -+.SH OPTIONS -+.TP -+--ppc -+Bless the file for use on PPC-based Macs. -+ -+.TP -+--verbose -+Print verbose messages. -+ -+.TP -+--x86 -+Bless the file for use on x86-based Macs. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-mkimage.1 b/util/grub-mkimage.1 -index 4dea4f54597..0eaaafe505b 100644 ---- a/util/grub-mkimage.1 -+++ b/util/grub-mkimage.1 -@@ -17,7 +17,7 @@ - [-v | --verbose] \fIMODULES\fR - - .SH DESCRIPTION --\fBgrub-mkimage\fI builds a bootable image of GRUB. -+\fBgrub-mkimage\fR builds a bootable image of GRUB. - - .SH OPTIONS - .TP -diff --git a/util/grub-syslinux2cfg.1 b/util/grub-syslinux2cfg.1 -new file mode 100644 -index 00000000000..85309482718 ---- /dev/null -+++ b/util/grub-syslinux2cfg.1 -@@ -0,0 +1,65 @@ -+.TH GRUB-SYSLINUX2CFG 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-syslinux2cfg\fR \(em Transform a syslinux config file into a GRUB config. -+ -+.SH SYNOPSIS -+\fBgrub-syslinux2cfg\fR [-c | --cwd=\fRDIR\fI] [-r | --root=\fIDIR\fR] [-v | --verbose] -+.RE -+.RS 25 -+[-t | --target-root=\fIDIR\fR] [-T | --target-cwd=\fIDIR\fR] -+.RE -+.RS 25 -+[-o | --output=\fIFILE\fR] [[-i | --isolinux] | -+.RE -+.RS 46 -+ [-s | --syslinux] | -+.RE -+.RS 46 -+ [-p | --pxelinux]] \fIFILE\fR -+ -+.SH DESCRIPTION -+\fBgrub-syslinux2cfg\fR builds a GRUB configuration file out of an existing -+syslinux configuration file. -+ -+.SH OPTIONS -+.TP -+--cwd=\fIDIR\fR -+Set \fIDIR\fR as syslinux's working directory. The default is to use the -+parent directory of the input file. -+ -+.TP -+--root=\fIDIR\fR -+Set \fIDIR\fR as the root directory of the syslinux disk. The default value -+is "/". -+ -+.TP -+--verbose -+Print verbose messages. -+ -+.TP -+--target-root=\fIDIR\fR -+Root directory as it will be seen at runtime. The default value is "/". -+ -+.TP -+--target-cwd=\fIDIR\fR -+Working directory of syslinux as it will be seen at runtime. The default -+value is the parent directory of the input file. -+ -+.TP -+--output=\fIFILE\fR -+Write the new config file to \fIFILE\fR. The default value is standard output. -+ -+.TP -+--isolinux -+Assume that the input file is an isolinux configuration file. -+ -+.TP -+--pxelinux -+Assume that the input file is a pxelinux configuration file. -+ -+.TP -+--syslinux -+Assume that the input file is a syslinux configuration file. -+ -+.SH SEE ALSO -+.BR "info grub" diff --git a/SOURCES/0055-20_linux_xen-load-xen-or-multiboot-2-modules-as-need.patch b/SOURCES/0055-20_linux_xen-load-xen-or-multiboot-2-modules-as-need.patch new file mode 100644 index 0000000..cd58ff4 --- /dev/null +++ b/SOURCES/0055-20_linux_xen-load-xen-or-multiboot-2-modules-as-need.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 9 Jul 2019 14:31:19 +0200 +Subject: [PATCH] 20_linux_xen: load xen or multiboot{,2} modules as needed. + +Signed-off-by: Peter Jones +--- + util/grub.d/20_linux_xen.in | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in +index e9e73b815f..c23b064be6 100644 +--- a/util/grub.d/20_linux_xen.in ++++ b/util/grub.d/20_linux_xen.in +@@ -153,6 +153,7 @@ linux_entry_xsm () + else + xen_rm_opts="no-real-mode edd=off" + fi ++ insmod ${xen_module} + ${xen_loader} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts} + echo '$(echo "$lmessage" | grub_quote)' + ${module_loader} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args} +@@ -166,6 +167,7 @@ EOF + done + sed "s/^/$submenu_indentation/" << EOF + echo '$(echo "$message" | grub_quote)' ++ insmod ${xen_module} + ${module_loader} --nounzip $(echo $initrd_path) + EOF + fi +@@ -253,13 +255,16 @@ while [ "x${xen_list}" != "x" ] ; do + echo " submenu '$(gettext_printf "Xen hypervisor, version %s" "${xen_version}" | grub_quote)' \$menuentry_id_option 'xen-hypervisor-$xen_version-$boot_device_id' {" + fi + if ($grub_file --is-arm64-efi $current_xen); then ++ xen_module="xen_boot" + xen_loader="xen_hypervisor" + module_loader="xen_module" + else + if ($grub_file --is-x86-multiboot2 $current_xen); then ++ xen_module="multiboot2" + xen_loader="multiboot2" + module_loader="module2" + else ++ xen_module="multiboot" + xen_loader="multiboot" + module_loader="module" + fi diff --git a/SOURCES/0055-Make-our-info-pages-say-grub2-where-appropriate.patch b/SOURCES/0055-Make-our-info-pages-say-grub2-where-appropriate.patch deleted file mode 100644 index be28efd..0000000 --- a/SOURCES/0055-Make-our-info-pages-say-grub2-where-appropriate.patch +++ /dev/null @@ -1,1008 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 9 Jul 2019 12:59:58 +0200 -Subject: [PATCH] Make our info pages say "grub2" where appropriate. - -This needs to be hooked up to --program-transform=, but I haven't had -time. - -Signed-off-by: Peter Jones ---- - docs/grub-dev.texi | 4 +- - docs/grub.texi | 321 ++++++++++++++++++++++++++++------------------------- - 2 files changed, 171 insertions(+), 154 deletions(-) - -diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi -index 6c629a23e2d..19f708ee662 100644 ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -1,7 +1,7 @@ - \input texinfo - @c -*-texinfo-*- - @c %**start of header --@setfilename grub-dev.info -+@setfilename grub2-dev.info - @include version-dev.texi - @settitle GNU GRUB Developers Manual @value{VERSION} - @c Unify all our little indices for now. -@@ -32,7 +32,7 @@ Invariant Sections. - - @dircategory Kernel - @direntry --* grub-dev: (grub-dev). The GRand Unified Bootloader Dev -+* grub2-dev: (grub2-dev). The GRand Unified Bootloader Dev - @end direntry - - @setchapternewpage odd -diff --git a/docs/grub.texi b/docs/grub.texi -index 69f08d289f9..0615d0ed97e 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -1,7 +1,7 @@ - \input texinfo - @c -*-texinfo-*- - @c %**start of header --@setfilename grub.info -+@setfilename grub2.info - @include version.texi - @settitle GNU GRUB Manual @value{VERSION} - @c Unify all our little indices for now. -@@ -32,15 +32,15 @@ Invariant Sections. - - @dircategory Kernel - @direntry --* GRUB: (grub). The GRand Unified Bootloader --* grub-install: (grub)Invoking grub-install. Install GRUB on your drive --* grub-mkconfig: (grub)Invoking grub-mkconfig. Generate GRUB configuration --* grub-mkpasswd-pbkdf2: (grub)Invoking grub-mkpasswd-pbkdf2. --* grub-mkrelpath: (grub)Invoking grub-mkrelpath. --* grub-mkrescue: (grub)Invoking grub-mkrescue. Make a GRUB rescue image --* grub-mount: (grub)Invoking grub-mount. Mount a file system using GRUB --* grub-probe: (grub)Invoking grub-probe. Probe device information --* grub-script-check: (grub)Invoking grub-script-check. -+* GRUB2: (grub2). The GRand Unified Bootloader -+* grub2-install: (grub2)Invoking grub2-install. Install GRUB on your drive -+* grub2-mkconfig: (grub2)Invoking grub2-mkconfig. Generate GRUB configuration -+* grub2-mkpasswd-pbkdf2: (grub2)Invoking grub2-mkpasswd-pbkdf2. -+* grub2-mkrelpath: (grub2)Invoking grub2-mkrelpath. -+* grub2-mkrescue: (grub2)Invoking grub2-mkrescue. Make a GRUB rescue image -+* grub2-mount: (grub2)Invoking grub2-mount. Mount a file system using GRUB -+* grub2-probe: (grub2)Invoking grub2-probe. Probe device information -+* grub2-script-check: (grub2)Invoking grub2-script-check. - @end direntry - - @setchapternewpage odd -@@ -103,15 +103,15 @@ This edition documents version @value{VERSION}. - * Platform-specific operations:: Platform-specific operations - * Supported kernels:: The list of supported kernels - * Troubleshooting:: Error messages produced by GRUB --* Invoking grub-install:: How to use the GRUB installer --* Invoking grub-mkconfig:: Generate a GRUB configuration file --* Invoking grub-mkpasswd-pbkdf2:: -+* Invoking grub2-install:: How to use the GRUB installer -+* Invoking grub2-mkconfig:: Generate a GRUB configuration file -+* Invoking grub2-mkpasswd-pbkdf2:: - Generate GRUB password hashes --* Invoking grub-mkrelpath:: Make system path relative to its root --* Invoking grub-mkrescue:: Make a GRUB rescue image --* Invoking grub-mount:: Mount a file system using GRUB --* Invoking grub-probe:: Probe device information for GRUB --* Invoking grub-script-check:: Check GRUB script file for syntax errors -+* Invoking grub2-mkrelpath:: Make system path relative to its root -+* Invoking grub2-mkrescue:: Make a GRUB rescue image -+* Invoking grub2-mount:: Mount a file system using GRUB -+* Invoking grub2-probe:: Probe device information for GRUB -+* Invoking grub2-script-check:: Check GRUB script file for syntax errors - * Obtaining and Building GRUB:: How to obtain and build GRUB - * Reporting bugs:: Where you should send a bug report - * Future:: Some future plans on GRUB -@@ -230,7 +230,7 @@ surprising. - - @item - @file{grub.cfg} is typically automatically generated by --@command{grub-mkconfig} (@pxref{Simple configuration}). This makes it -+@command{grub2-mkconfig} (@pxref{Simple configuration}). This makes it - easier to handle versioned kernel upgrades. - - @item -@@ -244,7 +244,7 @@ scripting language: variables, conditionals, and loops are available. - @item - A small amount of persistent storage is available across reboots, using the - @command{save_env} and @command{load_env} commands in GRUB and the --@command{grub-editenv} utility. This is not available in all configurations -+@command{grub2-editenv} utility. This is not available in all configurations - (@pxref{Environment block}). - - @item -@@ -549,7 +549,7 @@ On OS which have device nodes similar to Unix-like OS GRUB tools use the - OS name. E.g. for GNU/Linux: - - @example --# @kbd{grub-install /dev/sda} -+# @kbd{grub2-install /dev/sda} - @end example - - On AROS we use another syntax. For volumes: -@@ -572,7 +572,7 @@ For disks we use syntax: - E.g. - - @example --# @kbd{grub-install //:ata.device/0/0} -+# @kbd{grub2-install //:ata.device/0/0} - @end example - - On Windows we use UNC path. For volumes it's typically -@@ -599,7 +599,7 @@ For disks it's - E.g. - - @example --# @kbd{grub-install \\?\PhysicalDrive0} -+# @kbd{grub2-install \\?\PhysicalDrive0} - @end example - - Beware that you may need to further escape the backslashes depending on your -@@ -609,7 +609,7 @@ When compiled with cygwin support then cygwin drive names are automatically - when needed. E.g. - - @example --# @kbd{grub-install /dev/sda} -+# @kbd{grub2-install /dev/sda} - @end example - - @node Installation -@@ -622,7 +622,7 @@ from the source tarball, or as a package for your OS. - - After you have done that, you need to install the boot loader on a - drive (floppy or hard disk) by using the utility --@command{grub-install} (@pxref{Invoking grub-install}) on a UNIX-like OS. -+@command{grub2-install} (@pxref{Invoking grub2-install}) on a UNIX-like OS. - - GRUB comes with boot images, which are normally put in the directory - @file{/usr/lib/grub/-} (for BIOS-based machines -@@ -633,22 +633,22 @@ loader needs to find them (usually @file{/boot}) will be called - the @dfn{boot directory}. - - @menu --* Installing GRUB using grub-install:: -+* Installing GRUB using grub2-install:: - * Making a GRUB bootable CD-ROM:: - * Device map:: - * BIOS installation:: - @end menu - - --@node Installing GRUB using grub-install --@section Installing GRUB using grub-install -+@node Installing GRUB using grub2-install -+@section Installing GRUB using grub2-install - - For information on where GRUB should be installed on PC BIOS platforms, - @pxref{BIOS installation}. - - In order to install GRUB under a UNIX-like OS (such --as @sc{gnu}), invoke the program @command{grub-install} (@pxref{Invoking --grub-install}) as the superuser (@dfn{root}). -+as @sc{gnu}), invoke the program @command{grub2-install} (@pxref{Invoking -+grub2-install}) as the superuser (@dfn{root}). - - The usage is basically very simple. You only need to specify one - argument to the program, namely, where to install the boot loader. The -@@ -657,13 +657,13 @@ For example, under Linux the following will install GRUB into the MBR - of the first IDE disk: - - @example --# @kbd{grub-install /dev/sda} -+# @kbd{grub2-install /dev/sda} - @end example - - Likewise, under GNU/Hurd, this has the same effect: - - @example --# @kbd{grub-install /dev/hd0} -+# @kbd{grub2-install /dev/hd0} - @end example - - But all the above examples assume that GRUB should put images under -@@ -677,7 +677,7 @@ boot floppy with a filesystem. Here is an example: - # @kbd{mke2fs /dev/fd0} - # @kbd{mount -t ext2 /dev/fd0 /mnt} - # @kbd{mkdir /mnt/boot} --# @kbd{grub-install --boot-directory=/mnt/boot /dev/fd0} -+# @kbd{grub2-install --boot-directory=/mnt/boot /dev/fd0} - # @kbd{umount /mnt} - @end group - @end example -@@ -689,30 +689,37 @@ floppy instead of exposing the USB drive as a hard disk (they call it - @example - # @kbd{losetup /dev/loop0 /dev/sdb1} - # @kbd{mount /dev/loop0 /mnt/usb} --# @kbd{grub-install --boot-directory=/mnt/usb/bugbios --force --allow-floppy /dev/loop0} -+# @kbd{grub2-install --boot-directory=/mnt/usb/bugbios --force --allow-floppy /dev/loop0} - @end example - - This install doesn't conflict with standard install as long as they are in - separate directories. - -+Note that @command{grub2-install} is actually just a shell script and the -+real task is done by other tools such as @command{grub2-mkimage}. Therefore, -+you may run those commands directly to install GRUB, without using -+@command{grub2-install}. Don't do that, however, unless you are very familiar -+with the internals of GRUB. Installing a boot loader on a running OS may be -+extremely dangerous. -+ - On EFI systems for fixed disk install you have to mount EFI System Partition. - If you mount it at @file{/boot/efi} then you don't need any special arguments: - - @example --# @kbd{grub-install} -+# @kbd{grub2-install} - @end example - - Otherwise you need to specify where your EFI System partition is mounted: - - @example --# @kbd{grub-install --efi-directory=/mnt/efi} -+# @kbd{grub2-install --efi-directory=/mnt/efi} - @end example - - For removable installs you have to use @option{--removable} and specify both - @option{--boot-directory} and @option{--efi-directory}: - - @example --# @kbd{grub-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable} -+# @kbd{grub2-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable} - @end example - - @node Making a GRUB bootable CD-ROM -@@ -732,10 +739,10 @@ usually also need to include a configuration file @file{grub.cfg} and some - other GRUB modules. - - To make a simple generic GRUB rescue CD, you can use the --@command{grub-mkrescue} program (@pxref{Invoking grub-mkrescue}): -+@command{grub2-mkrescue} program (@pxref{Invoking grub2-mkrescue}): - - @example --$ @kbd{grub-mkrescue -o grub.iso} -+$ @kbd{grub2-mkrescue -o grub.iso} - @end example - - You will often need to include other files in your image. To do this, first -@@ -758,7 +765,7 @@ directory @file{iso/}. - Finally, make the image: - - @example --$ @kbd{grub-mkrescue -o grub.iso iso} -+$ @kbd{grub2-mkrescue -o grub.iso iso} - @end example - - This produces a file named @file{grub.iso}, which then can be burned -@@ -774,7 +781,7 @@ storage devices. - @node Device map - @section The map between BIOS drives and OS devices - --If the device map file exists, the GRUB utilities (@command{grub-probe}, -+If the device map file exists, the GRUB utilities (@command{grub2-probe}, - etc.) read it to map BIOS drives to OS devices. This file consists of lines - like this: - -@@ -1254,23 +1261,23 @@ need to write the whole thing by hand. - @node Simple configuration - @section Simple configuration handling - --The program @command{grub-mkconfig} (@pxref{Invoking grub-mkconfig}) -+The program @command{grub2-mkconfig} (@pxref{Invoking grub2-mkconfig}) - generates @file{grub.cfg} files suitable for most cases. It is suitable for - use when upgrading a distribution, and will discover available kernels and - attempt to generate menu entries for them. - --@command{grub-mkconfig} does have some limitations. While adding extra -+@command{grub2-mkconfig} does have some limitations. While adding extra - custom menu entries to the end of the list can be done by editing --@file{/etc/grub.d/40_custom} or creating @file{/boot/grub/custom.cfg}, -+@file{/etc/grub.d/40_custom} or creating @file{/boot/grub2/custom.cfg}, - changing the order of menu entries or changing their titles may require - making complex changes to shell scripts stored in @file{/etc/grub.d/}. This - may be improved in the future. In the meantime, those who feel that it - would be easier to write @file{grub.cfg} directly are encouraged to do so - (@pxref{Booting}, and @ref{Shell-like scripting}), and to disable any system --provided by their distribution to automatically run @command{grub-mkconfig}. -+provided by their distribution to automatically run @command{grub2-mkconfig}. - - The file @file{/etc/default/grub} controls the operation of --@command{grub-mkconfig}. It is sourced by a shell script, and so must be -+@command{grub2-mkconfig}. It is sourced by a shell script, and so must be - valid POSIX shell input; normally, it will just be a sequence of - @samp{KEY=value} lines, but if the value contains spaces or other special - characters then it must be quoted. For example: -@@ -1308,7 +1315,7 @@ works it's not recommended since titles often contain unstable device names - and may be translated - - If you set this to @samp{saved}, then the default menu entry will be that --saved by @samp{GRUB_SAVEDEFAULT} or @command{grub-set-default}. This relies on -+saved by @samp{GRUB_SAVEDEFAULT} or @command{grub2-set-default}. This relies on - the environment block, which may not be available in all situations - (@pxref{Environment block}). - -@@ -1319,7 +1326,7 @@ If this option is set to @samp{true}, then, when an entry is selected, save - it as a new default entry for use by future runs of GRUB. This is only - useful if @samp{GRUB_DEFAULT=saved}; it is a separate option because - @samp{GRUB_DEFAULT=saved} is useful without this option, in conjunction with --@command{grub-set-default}. Unset by default. -+@command{grub2-set-default}. Unset by default. - This option relies on the environment block, which may not be available in - all situations (@pxref{Environment block}). - -@@ -1449,7 +1456,7 @@ intel-uc.img intel-ucode.img amd-uc.img amd-ucode.img early_ucode.cpio microcode - @end example - - @item GRUB_DISABLE_LINUX_UUID --Normally, @command{grub-mkconfig} will generate menu entries that use -+Normally, @command{grub2-mkconfig} will generate menu entries that use - universally-unique identifiers (UUIDs) to identify the root filesystem to - the Linux kernel, using a @samp{root=UUID=...} kernel parameter. This is - usually more reliable, but in some cases it may not be appropriate. To -@@ -1471,7 +1478,7 @@ If this option is set to @samp{true}, disable the generation of recovery - mode menu entries. - - @item GRUB_DISABLE_UUID --Normally, @command{grub-mkconfig} will generate menu entries that use -+Normally, @command{grub2-mkconfig} will generate menu entries that use - universally-unique identifiers (UUIDs) to identify various filesystems to - search for files. This is usually more reliable, but in some cases it may - not be appropriate. To disable this use of UUIDs, set this option to -@@ -1482,12 +1489,12 @@ not be appropriate. To disable this use of UUIDs, set this option to - @item GRUB_VIDEO_BACKEND - If graphical video support is required, either because the @samp{gfxterm} - graphical terminal is in use or because @samp{GRUB_GFXPAYLOAD_LINUX} is set, --then @command{grub-mkconfig} will normally load all available GRUB video -+then @command{grub2-mkconfig} will normally load all available GRUB video - drivers and use the one most appropriate for your hardware. If you need to - override this for some reason, then you can set this option. - --After @command{grub-install} has been run, the available video drivers are --listed in @file{/boot/grub/video.lst}. -+After @command{grub2-install} has been run, the available video drivers are -+listed in @file{/boot/grub2/video.lst}. - - @item GRUB_GFXMODE - Set the resolution used on the @samp{gfxterm} graphical terminal. Note that -@@ -1519,7 +1526,7 @@ boot sequence. If you have problems, set this option to @samp{text} and - GRUB will tell Linux to boot in normal text mode. - - @item GRUB_DISABLE_OS_PROBER --Normally, @command{grub-mkconfig} will try to use the external -+Normally, @command{grub2-mkconfig} will try to use the external - @command{os-prober} program, if installed, to discover other operating - systems installed on the same system and generate appropriate menu entries - for them. Set this option to @samp{true} to disable this. -@@ -1529,7 +1536,7 @@ List of space-separated FS UUIDs of filesystems to be ignored from os-prober - output. For efi chainloaders it's @@ - - @item GRUB_DISABLE_SUBMENU --Normally, @command{grub-mkconfig} will generate top level menu entry for -+Normally, @command{grub2-mkconfig} will generate top level menu entry for - the kernel with highest version number and put all other found kernels - or alternative menu entries for recovery mode in submenu. For entries returned - by @command{os-prober} first entry will be put on top level and all others -@@ -1537,11 +1544,11 @@ in submenu. If this option is set to @samp{true}, flat menu with all entries - on top level will be generated instead. Changing this option will require - changing existing values of @samp{GRUB_DEFAULT}, @samp{fallback} (@pxref{fallback}) - and @samp{default} (@pxref{default}) environment variables as well as saved --default entry using @command{grub-set-default} and value used with --@command{grub-reboot}. -+default entry using @command{grub2-set-default} and value used with -+@command{grub2-reboot}. - - @item GRUB_ENABLE_CRYPTODISK --If set to @samp{y}, @command{grub-mkconfig} and @command{grub-install} will -+If set to @samp{y}, @command{grub2-mkconfig} and @command{grub2-install} will - check for encrypted disks and generate additional commands needed to access - them during boot. Note that in this case unattended boot is not possible - because GRUB will wait for passphrase to unlock encrypted container. -@@ -1600,7 +1607,7 @@ confusing @samp{GRUB_TIMEOUT_STYLE=countdown} or - - @end table - --For more detailed customisation of @command{grub-mkconfig}'s output, you may -+For more detailed customisation of @command{grub2-mkconfig}'s output, you may - edit the scripts in @file{/etc/grub.d} directly. - @file{/etc/grub.d/40_custom} is particularly useful for adding entire custom - menu entries; simply type the menu entries you want to add at the end of -@@ -1862,7 +1869,7 @@ images as well. - Mount this partition on/mnt/boot and disable GRUB in all OSes and manually - install self-compiled latest GRUB with: - --@code{grub-install --boot-directory=/mnt/boot /dev/sda} -+@code{grub2-install --boot-directory=/mnt/boot /dev/sda} - - In all the OSes install GRUB tools but disable installing GRUB in bootsector, - so you'll have menu.lst and grub.cfg available for use. Also disable os-prober -@@ -1872,20 +1879,20 @@ use by setting: - - in /etc/default/grub - --Then write a grub.cfg (/mnt/boot/grub/grub.cfg): -+Then write a grub.cfg (/mnt/boot/grub2/grub.cfg): - - @example - - menuentry "OS using grub2" @{ - insmod xfs - search --set=root --label OS1 --hint hd0,msdos8 -- configfile /boot/grub/grub.cfg -+ configfile /boot/grub2/grub.cfg - @} - - menuentry "OS using grub2-legacy" @{ - insmod ext2 - search --set=root --label OS2 --hint hd0,msdos6 -- legacy_configfile /boot/grub/menu.lst -+ legacy_configfile /boot/grub2/menu.lst - @} - - menuentry "Windows XP" @{ -@@ -1948,15 +1955,15 @@ GRUB supports embedding a configuration file directly into the core image, - so that it is loaded before entering normal mode. This is useful, for - example, when it is not straightforward to find the real configuration file, - or when you need to debug problems with loading that file. --@command{grub-install} uses this feature when it is not using BIOS disk -+@command{grub2-install} uses this feature when it is not using BIOS disk - functions or when installing to a different disk from the one containing - @file{/boot/grub}, in which case it needs to use the @command{search} - command (@pxref{search}) to find @file{/boot/grub}. - - To embed a configuration file, use the @option{-c} option to --@command{grub-mkimage}. The file is copied into the core image, so it may -+@command{grub2-mkimage}. The file is copied into the core image, so it may - reside anywhere on the file system, and may be removed after running --@command{grub-mkimage}. -+@command{grub2-mkimage}. - - After the embedded configuration file (if any) is executed, GRUB will load - the @samp{normal} module (@pxref{normal}), which will then read the real -@@ -1991,13 +1998,13 @@ included in the core image: - @example - @group - search.fs_label grub root --if [ -e /boot/grub/example/test1.cfg ]; then -+if [ -e /boot/grub2/example/test1.cfg ]; then - set prefix=($root)/boot/grub -- configfile /boot/grub/example/test1.cfg -+ configfile /boot/grub2/example/test1.cfg - else -- if [ -e /boot/grub/example/test2.cfg ]; then -+ if [ -e /boot/grub2/example/test2.cfg ]; then - set prefix=($root)/boot/grub -- configfile /boot/grub/example/test2.cfg -+ configfile /boot/grub2/example/test2.cfg - else - echo "Could not find an example configuration file!" - fi -@@ -2521,7 +2528,7 @@ grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/i38 - @end group - @end example - --Then follow instructions printed out by grub-mknetdir on configuring your DHCP -+Then follow instructions printed out by grub2-mknetdir on configuring your DHCP - server. - - The grub.cfg file is placed in the same directory as the path output by -@@ -2715,7 +2722,7 @@ team are: - @end table - - To take full advantage of this function, install GRUB into the MBR --(@pxref{Installing GRUB using grub-install}). -+(@pxref{Installing GRUB using grub2-install}). - - If you have a laptop which has a similar feature and not in the above list - could you figure your address and contribute? -@@ -2776,7 +2783,7 @@ bytes. - The sole function of @file{boot.img} is to read the first sector of the core - image from a local disk and jump to it. Because of the size restriction, - @file{boot.img} cannot understand any file system structure, so --@command{grub-install} hardcodes the location of the first sector of the -+@command{grub2-install} hardcodes the location of the first sector of the - core image into @file{boot.img} when installing GRUB. - - @item diskboot.img -@@ -2806,7 +2813,7 @@ images. - - @item core.img - This is the core image of GRUB. It is built dynamically from the kernel --image and an arbitrary list of modules by the @command{grub-mkimage} -+image and an arbitrary list of modules by the @command{grub2-mkimage} - program. Usually, it contains enough modules to access @file{/boot/grub}, - and loads everything else (including menu handling, the ability to load - target operating systems, and so on) from the file system at run-time. The -@@ -2858,7 +2865,7 @@ GRUB 2 has no single Stage 2 image. Instead, it loads modules from - In GRUB 2, images for booting from CD-ROM drives are now constructed using - @file{cdboot.img} and @file{core.img}, making sure that the core image - contains the @samp{iso9660} module. It is usually best to use the --@command{grub-mkrescue} program for this. -+@command{grub2-mkrescue} program for this. - - @item nbgrub - There is as yet no equivalent for @file{nbgrub} in GRUB 2; it was used by -@@ -3014,8 +3021,8 @@ There are two ways to specify files, by @dfn{absolute file name} and by - - An absolute file name resembles a Unix absolute file name, using - @samp{/} for the directory separator (not @samp{\} as in DOS). One --example is @samp{(hd0,1)/boot/grub/grub.cfg}. This means the file --@file{/boot/grub/grub.cfg} in the first partition of the first hard -+example is @samp{(hd0,1)/boot/grub2/grub.cfg}. This means the file -+@file{/boot/grub2/grub.cfg} in the first partition of the first hard - disk. If you omit the device name in an absolute file name, GRUB uses - GRUB's @dfn{root device} implicitly. So if you set the root device to, - say, @samp{(hd1,1)} by the command @samp{set root=(hd1,1)} (@pxref{set}), -@@ -3023,8 +3030,8 @@ then @code{/boot/kernel} is the same as @code{(hd1,1)/boot/kernel}. - - On ZFS filesystem the first path component must be - @var{volume}@samp{@@}[@var{snapshot}]. --So @samp{/rootvol@@snap-129/boot/grub/grub.cfg} refers to file --@samp{/boot/grub/grub.cfg} in snapshot of volume @samp{rootvol} with name -+So @samp{/rootvol@@snap-129/boot/grub2/grub.cfg} refers to file -+@samp{/boot/grub2/grub.cfg} in snapshot of volume @samp{rootvol} with name - @samp{snap-129}. Trailing @samp{@@} after volume name is mandatory even if - snapshot name is omitted. - -@@ -3427,7 +3434,7 @@ The more recent release of Minix would then be identified as - @samp{other>minix>minix-3.4.0}. - - This variable is often set by @samp{GRUB_DEFAULT} (@pxref{Simple --configuration}), @command{grub-set-default}, or @command{grub-reboot}. -+configuration}), @command{grub2-set-default}, or @command{grub2-reboot}. - - - @node fallback -@@ -3517,7 +3524,7 @@ If this variable is set, it names the language code that the - example, French would be named as @samp{fr}, and Simplified Chinese as - @samp{zh_CN}. - --@command{grub-mkconfig} (@pxref{Simple configuration}) will try to set a -+@command{grub2-mkconfig} (@pxref{Simple configuration}) will try to set a - reasonable default for this variable based on the system locale. - - -@@ -3525,10 +3532,10 @@ reasonable default for this variable based on the system locale. - @subsection locale_dir - - If this variable is set, it names the directory where translation files may --be found (@pxref{gettext}), usually @file{/boot/grub/locale}. Otherwise, -+be found (@pxref{gettext}), usually @file{/boot/grub2/locale}. Otherwise, - internationalization is disabled. - --@command{grub-mkconfig} (@pxref{Simple configuration}) will set a reasonable -+@command{grub2-mkconfig} (@pxref{Simple configuration}) will set a reasonable - default for this variable if internationalization is needed and any - translation files are available. - -@@ -3646,7 +3653,7 @@ input. The default is not to pause output. - - The location of the @samp{/boot/grub} directory as an absolute file name - (@pxref{File name syntax}). This is normally set by GRUB at startup based --on information provided by @command{grub-install}. GRUB modules are -+on information provided by @command{grub2-install}. GRUB modules are - dynamically loaded from this directory, so it must be set correctly in order - for many parts of GRUB to work. - -@@ -3737,17 +3744,17 @@ GRUB provides an ``environment block'' which can be used to save a small - amount of state. - - The environment block is a preallocated 1024-byte file, which normally lives --in @file{/boot/grub/grubenv} (although you should not assume this). At boot -+in @file{/boot/grub2/grubenv} (although you should not assume this). At boot - time, the @command{load_env} command (@pxref{load_env}) loads environment - variables from it, and the @command{save_env} (@pxref{save_env}) command - saves environment variables to it. From a running system, the --@command{grub-editenv} utility can be used to edit the environment block. -+@command{grub2-editenv} utility can be used to edit the environment block. - - For safety reasons, this storage is only available when installed on a plain - disk (no LVM or RAID), using a non-checksumming filesystem (no ZFS), and - using BIOS or EFI functions (no ATA, USB or IEEE1275). - --@command{grub-mkconfig} uses this facility to implement -+@command{grub2-mkconfig} uses this facility to implement - @samp{GRUB_SAVEDEFAULT} (@pxref{Simple configuration}). - - -@@ -4476,7 +4483,7 @@ Translate @var{string} into the current language. - - The current language code is stored in the @samp{lang} variable in GRUB's - environment (@pxref{lang}). Translation files in MO format are read from --@samp{locale_dir} (@pxref{locale_dir}), usually @file{/boot/grub/locale}. -+@samp{locale_dir} (@pxref{locale_dir}), usually @file{/boot/grub2/locale}. - @end deffn - - -@@ -4871,7 +4878,7 @@ Define a user named @var{user} with password @var{clear-password}. - - @deffn Command password_pbkdf2 user hashed-password - Define a user named @var{user} with password hash @var{hashed-password}. --Use @command{grub-mkpasswd-pbkdf2} (@pxref{Invoking grub-mkpasswd-pbkdf2}) -+Use @command{grub2-mkpasswd-pbkdf2} (@pxref{Invoking grub2-mkpasswd-pbkdf2}) - to generate password hashes. @xref{Security}. - @end deffn - -@@ -5814,8 +5821,8 @@ The @samp{password} (@pxref{password}) and @samp{password_pbkdf2} - which has an associated password. @samp{password} sets the password in - plain text, requiring @file{grub.cfg} to be secure; @samp{password_pbkdf2} - sets the password hashed using the Password-Based Key Derivation Function --(RFC 2898), requiring the use of @command{grub-mkpasswd-pbkdf2} --(@pxref{Invoking grub-mkpasswd-pbkdf2}) to generate password hashes. -+(RFC 2898), requiring the use of @command{grub2-mkpasswd-pbkdf2} -+(@pxref{Invoking grub2-mkpasswd-pbkdf2}) to generate password hashes. - - In order to enable authentication support, the @samp{superusers} environment - variable must be set to a list of usernames, separated by any of spaces, -@@ -5860,7 +5867,7 @@ menuentry "May be run by user1 or a superuser" --users user1 @{ - @end group - @end example - --The @command{grub-mkconfig} program does not yet have built-in support for -+The @command{grub2-mkconfig} program does not yet have built-in support for - generating configuration files with authentication. You can use - @file{/etc/grub.d/40_custom} to add simple superuser authentication, by - adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} -@@ -5887,7 +5894,17 @@ may halt or otherwise impact the boot process. - - An initial trusted public key can be embedded within the GRUB @file{core.img} - using the @code{--pubkey} option to @command{grub-install} --(@pxref{Invoking grub-install}). -+(@pxref{Invoking grub2-install}). -+ -+@comment Unfortunately --pubkey is not yet supported by grub2-install, -+@comment but we should not bring up internal detail grub2-mkimage here -+@comment in the user guide (as opposed to developer's manual). -+ -+@comment An initial trusted public key can be embedded within the GRUB -+@comment @file{core.img} using the @code{--pubkey} option to -+@comment @command{grub2-mkimage} (@pxref{Invoking grub2-install}). Presently it -+@comment is necessary to write a custom wrapper around @command{grub2-mkimage} -+@comment using the @code{--grub-mkimage} flag to @command{grub2-install}. - - GRUB uses GPG-style detached signatures (meaning that a file - @file{foo.sig} will be produced when file @file{foo} is signed), and -@@ -5907,8 +5924,8 @@ gpg --detach-sign /path/to/file - For successful validation of all of GRUB's subcomponents and the - loaded OS kernel, they must all be signed. One way to accomplish this - is the following (after having already produced the desired --@file{grub.cfg} file, e.g., by running @command{grub-mkconfig} --(@pxref{Invoking grub-mkconfig}): -+@file{grub.cfg} file, e.g., by running @command{grub2-mkconfig} -+(@pxref{Invoking grub2-mkconfig}): - - @example - @group -@@ -5930,7 +5947,7 @@ See also: @ref{check_signatures}, @ref{verify_detached}, @ref{trust}, - Note that internally signature enforcement is controlled by setting - the environment variable @code{check_signatures} equal to - @code{enforce}. Passing one or more @code{--pubkey} options to --@command{grub-mkimage} implicitly defines @code{check_signatures} -+@command{grub2-mkimage} implicitly defines @code{check_signatures} - equal to @code{enforce} in @file{core.img} prior to processing any - configuration files. - -@@ -6388,10 +6405,10 @@ Required files are: - - GRUB's normal start-up procedure involves setting the @samp{prefix} - environment variable to a value set in the core image by --@command{grub-install}, setting the @samp{root} variable to match, loading -+@command{grub2-install}, setting the @samp{root} variable to match, loading - the @samp{normal} module from the prefix, and running the @samp{normal} - command (@pxref{normal}). This command is responsible for reading --@file{/boot/grub/grub.cfg}, running the menu, and doing all the useful -+@file{/boot/grub2/grub.cfg}, running the menu, and doing all the useful - things GRUB is supposed to do. - - If, instead, you only get a rescue shell, this usually means that GRUB -@@ -6417,8 +6434,8 @@ normal - - However, any problem that leaves you in the rescue shell probably means that - GRUB was not correctly installed. It may be more useful to try to reinstall --it properly using @kbd{grub-install @var{device}} (@pxref{Invoking --grub-install}). When doing this, there are a few things to remember: -+it properly using @kbd{grub2-install @var{device}} (@pxref{Invoking -+grub2-install}). When doing this, there are a few things to remember: - - @itemize @bullet{} - @item -@@ -6430,7 +6447,7 @@ is usually better to use UUIDs or file system labels and avoid depending on - drive ordering entirely. - - @item --At least on BIOS systems, if you tell @command{grub-install} to install GRUB -+At least on BIOS systems, if you tell @command{grub2-install} to install GRUB - to a partition but GRUB has already been installed in the master boot - record, then the GRUB installation in the partition will be ignored. - -@@ -6461,21 +6478,21 @@ entry which claims partition start at block 0. This change will not hamper - bootability on other machines. - - --@node Invoking grub-install --@chapter Invoking grub-install -+@node Invoking grub2-install -+@chapter Invoking grub2-install - --The program @command{grub-install} generates a GRUB core image using --@command{grub-mkimage} and installs it on your system. You must specify the -+The program @command{grub2-install} generates a GRUB core image using -+@command{grub2-mkimage} and installs it on your system. You must specify the - device name on which you want to install GRUB, like this: - - @example --grub-install @var{install_device} -+grub2-install @var{install_device} - @end example - - The device name @var{install_device} is an OS device name or a GRUB - device name. - --@command{grub-install} accepts the following options: -+@command{grub2-install} accepts the following options: - - @table @option - @item --help -@@ -6491,13 +6508,13 @@ separate partition or a removable disk. - If this option is not specified then it defaults to @file{/boot}, so - - @example --@kbd{grub-install /dev/sda} -+@kbd{grub2-install /dev/sda} - @end example - - is equivalent to - - @example --@kbd{grub-install --boot-directory=/boot/ /dev/sda} -+@kbd{grub2-install --boot-directory=/boot/ /dev/sda} - @end example - - Here is an example in which you have a separate @dfn{boot} partition which is -@@ -6505,16 +6522,16 @@ mounted on - @file{/mnt/boot}: - - @example --@kbd{grub-install --boot-directory=/mnt/boot /dev/sdb} -+@kbd{grub2-install --boot-directory=/mnt/boot /dev/sdb} - @end example - - @item --recheck --Recheck the device map, even if @file{/boot/grub/device.map} already -+Recheck the device map, even if @file{/boot/grub2/device.map} already - exists. You should use this option whenever you add/remove a disk - into/from your computer. - - @item --no-rs-codes --By default on x86 BIOS systems, @command{grub-install} will use some -+By default on x86 BIOS systems, @command{grub2-install} will use some - extra space in the bootloader embedding area for Reed-Solomon - error-correcting codes. This enables GRUB to still boot successfully - if some blocks are corrupted. The exact amount of protection offered -@@ -6527,17 +6544,17 @@ installation}) where GRUB does not reside in any unpartitioned space - outside of the MBR. Disable the Reed-Solomon codes with this option. - @end table - --@node Invoking grub-mkconfig --@chapter Invoking grub-mkconfig -+@node Invoking grub2-mkconfig -+@chapter Invoking grub2-mkconfig - --The program @command{grub-mkconfig} generates a configuration file for GRUB -+The program @command{grub2-mkconfig} generates a configuration file for GRUB - (@pxref{Simple configuration}). - - @example --grub-mkconfig -o /boot/grub/grub.cfg -+grub-mkconfig -o /boot/grub2/grub.cfg - @end example - --@command{grub-mkconfig} accepts the following options: -+@command{grub2-mkconfig} accepts the following options: - - @table @option - @item --help -@@ -6553,17 +6570,17 @@ it to standard output. - @end table - - --@node Invoking grub-mkpasswd-pbkdf2 --@chapter Invoking grub-mkpasswd-pbkdf2 -+@node Invoking grub2-mkpasswd-pbkdf2 -+@chapter Invoking grub2-mkpasswd-pbkdf2 - --The program @command{grub-mkpasswd-pbkdf2} generates password hashes for -+The program @command{grub2-mkpasswd-pbkdf2} generates password hashes for - GRUB (@pxref{Security}). - - @example - grub-mkpasswd-pbkdf2 - @end example - --@command{grub-mkpasswd-pbkdf2} accepts the following options: -+@command{grub2-mkpasswd-pbkdf2} accepts the following options: - - @table @option - @item -c @var{number} -@@ -6581,23 +6598,23 @@ Length of the salt. Defaults to 64. - @end table - - --@node Invoking grub-mkrelpath --@chapter Invoking grub-mkrelpath -+@node Invoking grub2-mkrelpath -+@chapter Invoking grub2-mkrelpath - --The program @command{grub-mkrelpath} makes a file system path relative to -+The program @command{grub2-mkrelpath} makes a file system path relative to - the root of its containing file system. For instance, if @file{/usr} is a - mount point, then: - - @example --$ @kbd{grub-mkrelpath /usr/share/grub/unicode.pf2} -+$ @kbd{grub2-mkrelpath /usr/share/grub/unicode.pf2} - @samp{/share/grub/unicode.pf2} - @end example - - This is mainly used internally by other GRUB utilities such as --@command{grub-mkconfig} (@pxref{Invoking grub-mkconfig}), but may -+@command{grub2-mkconfig} (@pxref{Invoking grub2-mkconfig}), but may - occasionally also be useful for debugging. - --@command{grub-mkrelpath} accepts the following options: -+@command{grub2-mkrelpath} accepts the following options: - - @table @option - @item --help -@@ -6608,17 +6625,17 @@ Print the version number of GRUB and exit. - @end table - - --@node Invoking grub-mkrescue --@chapter Invoking grub-mkrescue -+@node Invoking grub2-mkrescue -+@chapter Invoking grub2-mkrescue - --The program @command{grub-mkrescue} generates a bootable GRUB rescue image -+The program @command{grub2-mkrescue} generates a bootable GRUB rescue image - (@pxref{Making a GRUB bootable CD-ROM}). - - @example - grub-mkrescue -o grub.iso - @end example - --All arguments not explicitly listed as @command{grub-mkrescue} options are -+All arguments not explicitly listed as @command{grub2-mkrescue} options are - passed on directly to @command{xorriso} in @command{mkisofs} emulation mode. - Options passed to @command{xorriso} will normally be interpreted as - @command{mkisofs} options; if the option @samp{--} is used, then anything -@@ -6633,7 +6650,7 @@ mkdir -p disk/boot/grub - grub-mkrescue -o grub.iso disk - @end example - --@command{grub-mkrescue} accepts the following options: -+@command{grub2-mkrescue} accepts the following options: - - @table @option - @item --help -@@ -6661,15 +6678,15 @@ Use @var{file} as the @command{xorriso} program, rather than the built-in - default. - - @item --grub-mkimage=@var{file} --Use @var{file} as the @command{grub-mkimage} program, rather than the -+Use @var{file} as the @command{grub2-mkimage} program, rather than the - built-in default. - @end table - - --@node Invoking grub-mount --@chapter Invoking grub-mount -+@node Invoking grub2-mount -+@chapter Invoking grub2-mount - --The program @command{grub-mount} performs a read-only mount of any file -+The program @command{grub2-mount} performs a read-only mount of any file - system or file system image that GRUB understands, using GRUB's file system - drivers via FUSE. (It is only available if FUSE development files were - present when GRUB was built.) This has a number of uses: -@@ -6701,13 +6718,13 @@ even if nobody has yet written a FUSE module specifically for that file - system type. - @end itemize - --Using @command{grub-mount} is normally as simple as: -+Using @command{grub2-mount} is normally as simple as: - - @example - grub-mount /dev/sda1 /mnt - @end example - --@command{grub-mount} must be given one or more images and a mount point as -+@command{grub2-mount} must be given one or more images and a mount point as - non-option arguments (if it is given more than one image, it will treat them - as a RAID set), and also accepts the following options: - -@@ -6729,13 +6746,13 @@ Show debugging output for conditions matching @var{string}. - @item -K prompt|@var{file} - @itemx --zfs-key=prompt|@var{file} - Load a ZFS encryption key. If you use @samp{prompt} as the argument, --@command{grub-mount} will read a passphrase from the terminal; otherwise, it -+@command{grub2-mount} will read a passphrase from the terminal; otherwise, it - will read key material from the specified file. - - @item -r @var{device} - @itemx --root=@var{device} - Set the GRUB root device to @var{device}. You do not normally need to set --this; @command{grub-mount} will automatically set the root device to the -+this; @command{grub2-mount} will automatically set the root device to the - root of the supplied file system. - - If @var{device} is just a number, then it will be treated as a partition -@@ -6753,10 +6770,10 @@ Print verbose messages. - @end table - - --@node Invoking grub-probe --@chapter Invoking grub-probe -+@node Invoking grub2-probe -+@chapter Invoking grub2-probe - --The program @command{grub-probe} probes device information for a given path -+The program @command{grub2-probe} probes device information for a given path - or device. - - @example -@@ -6764,7 +6781,7 @@ grub-probe --target=fs /boot/grub - grub-probe --target=drive --device /dev/sda1 - @end example - --@command{grub-probe} must be given a path or device as a non-option -+@command{grub2-probe} must be given a path or device as a non-option - argument, and also accepts the following options: - - @table @option -@@ -6777,16 +6794,16 @@ Print the version number of GRUB and exit. - @item -d - @itemx --device - If this option is given, then the non-option argument is a system device --name (such as @samp{/dev/sda1}), and @command{grub-probe} will print -+name (such as @samp{/dev/sda1}), and @command{grub2-probe} will print - information about that device. If it is not given, then the non-option - argument is a filesystem path (such as @samp{/boot/grub}), and --@command{grub-probe} will print information about the device containing that -+@command{grub2-probe} will print information about the device containing that - part of the filesystem. - - @item -m @var{file} - @itemx --device-map=@var{file} - Use @var{file} as the device map (@pxref{Device map}) rather than the --default, usually @samp{/boot/grub/device.map}. -+default, usually @samp{/boot/grub2/device.map}. - - @item -t @var{target} - @itemx --target=@var{target} -@@ -6839,19 +6856,19 @@ Print verbose messages. - @end table - - --@node Invoking grub-script-check --@chapter Invoking grub-script-check -+@node Invoking grub2-script-check -+@chapter Invoking grub2-script-check - --The program @command{grub-script-check} takes a GRUB script file -+The program @command{grub2-script-check} takes a GRUB script file - (@pxref{Shell-like scripting}) and checks it for syntax errors, similar to - commands such as @command{sh -n}. It may take a @var{path} as a non-option - argument; if none is supplied, it will read from standard input. - - @example --grub-script-check /boot/grub/grub.cfg -+grub-script-check /boot/grub2/grub.cfg - @end example - --@command{grub-script-check} accepts the following options: -+@command{grub2-script-check} accepts the following options: - - @table @option - @item --help diff --git a/SOURCES/0056-Make-pmtimer-tsc-calibration-not-take-51-seconds-to-.patch b/SOURCES/0056-Make-pmtimer-tsc-calibration-not-take-51-seconds-to-.patch new file mode 100644 index 0000000..beef0f3 --- /dev/null +++ b/SOURCES/0056-Make-pmtimer-tsc-calibration-not-take-51-seconds-to-.patch @@ -0,0 +1,211 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 7 Nov 2017 17:12:17 -0500 +Subject: [PATCH] Make pmtimer tsc calibration not take 51 seconds to fail. + +On my laptop running at 2.4GHz, if I run a VM where tsc calibration +using pmtimer will fail presuming a broken pmtimer, it takes ~51 seconds +to do so (as measured with the stopwatch on my phone), with a tsc delta +of 0x1cd1c85300, or around 125 billion cycles. + +If instead of trying to wait for 5-200ms to show up on the pmtimer, we try +to wait for 5-200us, it decides it's broken in ~0x2626aa0 TSCs, aka ~2.4 +million cycles, or more or less instantly. + +Additionally, this reading the pmtimer was returning 0xffffffff anyway, +and that's obviously an invalid return. I've added a check for that and +0 so we don't bother waiting for the test if what we're seeing is dead +pins with no response at all. + +If "debug" is includes "pmtimer", you will see one of the following +three outcomes. If pmtimer gives all 0 or all 1 bits, you will see: + +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 1 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 2 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 3 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 4 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 5 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 6 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 7 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 8 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 9 +kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 10 +kern/i386/tsc_pmtimer.c:78: timer is broken; giving up. + +This outcome was tested using qemu+kvm with UEFI (OVMF) firmware and +these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX + +If pmtimer gives any other bit patterns but is not actually marching +forward fast enough to use for clock calibration, you will see: + +kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations) +kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0 + +This outcome was tested using grub compiled with GRUB_PMTIMER_IGNORE_BAD_READS +defined (so as not to trip the bad read test) using qemu+kvm with UEFI +(OVMF) firmware, and these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX + +If pmtimer actually works, you'll see something like: + +kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations) +kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0 + +This outcome was tested using qemu+kvm with UEFI (OVMF) firmware, and +these options: -machine pc-i440fx-2.4 -cpu Broadwell-noTSX + +I've also tested this outcome on a real Intel Xeon E3-1275v3 on an Intel +Server Board S1200V3RPS using the SDV.RP.B8 "Release" build here: +https://firmware.intel.com/sites/default/files/UEFIDevKit_S1200RP_vB8.zip + +Signed-off-by: Peter Jones +--- + grub-core/kern/i386/tsc_pmtimer.c | 109 +++++++++++++++++++++++++++++++------- + 1 file changed, 89 insertions(+), 20 deletions(-) + +diff --git a/grub-core/kern/i386/tsc_pmtimer.c b/grub-core/kern/i386/tsc_pmtimer.c +index c9c3616997..ca15c3aacd 100644 +--- a/grub-core/kern/i386/tsc_pmtimer.c ++++ b/grub-core/kern/i386/tsc_pmtimer.c +@@ -28,40 +28,101 @@ + #include + #include + ++/* ++ * Define GRUB_PMTIMER_IGNORE_BAD_READS if you're trying to test a timer that's ++ * present but doesn't keep time well. ++ */ ++// #define GRUB_PMTIMER_IGNORE_BAD_READS ++ + grub_uint64_t + grub_pmtimer_wait_count_tsc (grub_port_t pmtimer, + grub_uint16_t num_pm_ticks) + { + grub_uint32_t start; +- grub_uint32_t last; +- grub_uint32_t cur, end; ++ grub_uint64_t cur, end; + grub_uint64_t start_tsc; + grub_uint64_t end_tsc; +- int num_iter = 0; ++ unsigned int num_iter = 0; ++#ifndef GRUB_PMTIMER_IGNORE_BAD_READS ++ int bad_reads = 0; ++#endif + +- start = grub_inl (pmtimer) & 0xffffff; +- last = start; ++ /* ++ * Some timers are 24-bit and some are 32-bit, but it doesn't make much ++ * difference to us. Caring which one we have isn't really worth it since ++ * the low-order digits will give us enough data to calibrate TSC. So just ++ * mask the top-order byte off. ++ */ ++ cur = start = grub_inl (pmtimer) & 0xffffffUL; + end = start + num_pm_ticks; + start_tsc = grub_get_tsc (); + while (1) + { +- cur = grub_inl (pmtimer) & 0xffffff; +- if (cur < last) +- cur |= 0x1000000; +- num_iter++; ++ cur &= 0xffffffffff000000ULL; ++ cur |= grub_inl (pmtimer) & 0xffffffUL; ++ ++ end_tsc = grub_get_tsc(); ++ ++#ifndef GRUB_PMTIMER_IGNORE_BAD_READS ++ /* ++ * If we get 10 reads in a row that are obviously dead pins, there's no ++ * reason to do this thousands of times. ++ */ ++ if (cur == 0xffffffUL || cur == 0) ++ { ++ bad_reads++; ++ grub_dprintf ("pmtimer", ++ "pmtimer: 0x%"PRIxGRUB_UINT64_T" bad_reads: %d\n", ++ cur, bad_reads); ++ grub_dprintf ("pmtimer", "timer is broken; giving up.\n"); ++ ++ if (bad_reads == 10) ++ return 0; ++ } ++#endif ++ ++ if (cur < start) ++ cur += 0x1000000; ++ + if (cur >= end) + { +- end_tsc = grub_get_tsc (); ++ grub_dprintf ("pmtimer", "pmtimer delta is 0x%"PRIxGRUB_UINT64_T"\n", ++ cur - start); ++ grub_dprintf ("pmtimer", "tsc delta is 0x%"PRIxGRUB_UINT64_T"\n", ++ end_tsc - start_tsc); + return end_tsc - start_tsc; + } +- /* Check for broken PM timer. +- 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz) +- if after this time we still don't have 1 ms on pmtimer, then +- pmtimer is broken. ++ ++ /* ++ * Check for broken PM timer. 1ms at 10GHz should be 1E+7 TSCs; at ++ * 250MHz it should be 2.5E6. So if after 4E+7 TSCs on a 10GHz machine, ++ * we should have seen pmtimer show 4ms of change (i.e. cur =~ ++ * start+14320); on a 250MHz machine that should be 16ms (start+57280). ++ * If after this a time we still don't have 1ms on pmtimer, then pmtimer ++ * is broken. ++ * ++ * Likewise, if our code is perfectly efficient and introduces no delays ++ * whatsoever, on a 10GHz system we should see a TSC delta of 3580 in ++ * ~3580 iterations. On a 250MHz machine that should be ~900 iterations. ++ * ++ * With those factors in mind, there are two limits here. There's a hard ++ * limit here at 8x our desired pm timer delta, picked as an arbitrarily ++ * large value that's still not a lot of time to humans, because if we ++ * get that far this is either an implausibly fast machine or the pmtimer ++ * is not running. And there's another limit on 4x our 10GHz tsc delta ++ * without seeing cur converge on our target value. + */ +- if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) { +- return 0; +- } ++ if ((++num_iter > (grub_uint32_t)num_pm_ticks << 3UL) || ++ end_tsc - start_tsc > 40000000) ++ { ++ grub_dprintf ("pmtimer", ++ "pmtimer delta is 0x%"PRIxGRUB_UINT64_T" (%u iterations)\n", ++ cur - start, num_iter); ++ grub_dprintf ("pmtimer", ++ "tsc delta is implausible: 0x%"PRIxGRUB_UINT64_T"\n", ++ end_tsc - start_tsc); ++ return 0; ++ } + } + } + +@@ -74,12 +135,20 @@ grub_tsc_calibrate_from_pmtimer (void) + + fadt = grub_acpi_find_fadt (); + if (!fadt) +- return 0; ++ { ++ grub_dprintf ("pmtimer", "No FADT found; not using pmtimer.\n"); ++ return 0; ++ } + pmtimer = fadt->pmtimer; + if (!pmtimer) +- return 0; ++ { ++ grub_dprintf ("pmtimer", "FADT does not specify pmtimer; skipping.\n"); ++ return 0; ++ } + +- /* It's 3.579545 MHz clock. Wait 1 ms. */ ++ /* ++ * It's 3.579545 MHz clock. Wait 1 ms. ++ */ + tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580); + if (tsc_diff == 0) + return 0; diff --git a/SOURCES/0056-macos-just-build-chainloader-entries-don-t-try-any-x.patch b/SOURCES/0056-macos-just-build-chainloader-entries-don-t-try-any-x.patch deleted file mode 100644 index 574d117..0000000 --- a/SOURCES/0056-macos-just-build-chainloader-entries-don-t-try-any-x.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 24 May 2017 12:42:32 -0400 -Subject: [PATCH] macos: just build chainloader entries, don't try any xnu xnu. - -Since our bugs tell us that the xnu boot entries really just don't work -most of the time, and they create piles of extra boot entries, because -they can't quite figure out 32-vs-64 and other stuff like that. - -It's rediculous, and we should just boot their bootloader through the -chainloader instead. - -So this patch does that. - -Resolves: rhbz#893179 - -Signed-off-by: Peter Jones ---- - util/grub.d/30_os-prober.in | 78 +++++++++++---------------------------------- - 1 file changed, 18 insertions(+), 60 deletions(-) - -diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in -index 1b91c102f35..4b27bd20153 100644 ---- a/util/grub.d/30_os-prober.in -+++ b/util/grub.d/30_os-prober.in -@@ -42,68 +42,25 @@ if [ -z "${OSPROBED}" ] ; then - fi - - osx_entry() { -- if [ x$2 = x32 ]; then -- # TRANSLATORS: it refers to kernel architecture (32-bit) -- bitstr="$(gettext "(32-bit)")" -- else -- # TRANSLATORS: it refers to kernel architecture (64-bit) -- bitstr="$(gettext "(64-bit)")" -- fi - # TRANSLATORS: it refers on the OS residing on device %s - onstr="$(gettext_printf "(on %s)" "${DEVICE}")" -- cat << EOF --menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' { -+ hints="" -+ for hint in `"${grub_probe}" --device ${device} --target=efi_hints 2> /dev/null` ; do -+ hints="${hints} --hint=${hint}" -+ done -+ cat << EOF -+menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' { - EOF - save_default_entry | grub_add_tab - prepare_grub_to_access_device ${DEVICE} | grub_add_tab - cat << EOF -+ set gfxpayload=keep - load_video -- set do_resume=0 -- if [ /var/vm/sleepimage -nt10 / ]; then -- if xnu_resume /var/vm/sleepimage; then -- set do_resume=1 -- fi -- fi -- if [ \$do_resume = 0 ]; then -- xnu_uuid ${OSXUUID} uuid -- if [ -f /Extra/DSDT.aml ]; then -- acpi -e /Extra/DSDT.aml -- fi -- if [ /kernelcache -nt /System/Library/Extensions ]; then -- $1 /kernelcache boot-uuid=\${uuid} rd=*uuid -- elif [ -f /System/Library/Kernels/kernel ]; then -- $1 /System/Library/Kernels/kernel boot-uuid=\${uuid} rd=*uuid -- xnu_kextdir /System/Library/Extensions -- else -- $1 /mach_kernel boot-uuid=\${uuid} rd=*uuid -- if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then -- xnu_mkext /System/Library/Extensions.mkext -- else -- xnu_kextdir /System/Library/Extensions -- fi -- fi -- if [ -f /Extra/Extensions.mkext ]; then -- xnu_mkext /Extra/Extensions.mkext -- fi -- if [ -d /Extra/Extensions ]; then -- xnu_kextdir /Extra/Extensions -- fi -- if [ -f /Extra/devprop.bin ]; then -- xnu_devprop_load /Extra/devprop.bin -- fi -- if [ -f /Extra/splash.jpg ]; then -- insmod jpeg -- xnu_splash /Extra/splash.jpg -- fi -- if [ -f /Extra/splash.png ]; then -- insmod png -- xnu_splash /Extra/splash.png -- fi -- if [ -f /Extra/splash.tga ]; then -- insmod tga -- xnu_splash /Extra/splash.tga -- fi -- fi -+ insmod part_gpt -+ insmod hfsplus -+ search --no-floppy --fs-uuid --set=root ${hints} $(grub_get_device_id "${DEVICE}") -+ chainloader (\$root)/System/Library/CoreServices/boot.efi -+ boot - } - EOF - } -@@ -292,11 +249,12 @@ EOF - echo "$title_correction_code" - ;; - macosx) -- if [ "${UUID}" ]; then -- OSXUUID="${UUID}" -- osx_entry xnu_kernel 32 -- osx_entry xnu_kernel64 64 -- fi -+ for subdevice in ${DEVICE%[[:digit:]]*}* ; do -+ parttype="`"${grub_probe}" --device ${device} --target=gpt_parttype "${subdevice}" 2> /dev/null`" -+ if [[ "$parttype" = "426f6f74-0000-11aa-aa11-00306543ecac" ]]; then -+ DEVICE="${subdevice}" osx_entry -+ fi -+ done - ;; - hurd) - onstr="$(gettext_printf "(on %s)" "${DEVICE}")" diff --git a/SOURCES/0057-align-struct-efi_variable-better.patch b/SOURCES/0057-align-struct-efi_variable-better.patch new file mode 100644 index 0000000..361cb13 --- /dev/null +++ b/SOURCES/0057-align-struct-efi_variable-better.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 27 Feb 2018 13:55:35 -0500 +Subject: [PATCH] align struct efi_variable better... + +--- + include/grub/efiemu/runtime.h | 2 +- + include/grub/types.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/grub/efiemu/runtime.h b/include/grub/efiemu/runtime.h +index 36d2dedf47..9d93ba88ba 100644 +--- a/include/grub/efiemu/runtime.h ++++ b/include/grub/efiemu/runtime.h +@@ -33,5 +33,5 @@ struct efi_variable + grub_uint32_t namelen; + grub_uint32_t size; + grub_efi_uint32_t attributes; +-} GRUB_PACKED; ++} GRUB_PACKED GRUB_ALIGNED(8); + #endif /* ! GRUB_EFI_EMU_RUNTIME_HEADER */ +diff --git a/include/grub/types.h b/include/grub/types.h +index 0a3ff15913..ba446d9904 100644 +--- a/include/grub/types.h ++++ b/include/grub/types.h +@@ -29,6 +29,7 @@ + #else + #define GRUB_PACKED __attribute__ ((packed)) + #endif ++#define GRUB_ALIGNED(x) __attribute__((aligned (x))) + + #ifdef GRUB_BUILD + # define GRUB_CPU_SIZEOF_VOID_P BUILD_SIZEOF_VOID_P diff --git a/SOURCES/0057-grub2-btrfs-Add-ability-to-boot-from-subvolumes.patch b/SOURCES/0057-grub2-btrfs-Add-ability-to-boot-from-subvolumes.patch deleted file mode 100644 index 68dfc1d..0000000 --- a/SOURCES/0057-grub2-btrfs-Add-ability-to-boot-from-subvolumes.patch +++ /dev/null @@ -1,703 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jeff Mahoney -Date: Tue, 9 Jul 2019 13:39:45 +0200 -Subject: [PATCH] grub2/btrfs: Add ability to boot from subvolumes - -This patch adds the ability to specify a different root on a btrfs -filesystem too boot from other than the default one. - -btrfs-list-snapshots will list the subvolumes available on the -filesystem. - -set btrfs_subvol= and set btrfs_subvolid= will specify -which subvolume to use and any pathnames provided with either of those -variables set will start using that root. If the subvolume or subvolume id -doesn't exist, then an error case will result. - -It is possible to boot into a separate GRUB instance by exporting the -variable and loading the config file from the subvolume. - -Signed-off-by: Jeff Mahoney ---- - grub-core/fs/btrfs.c | 552 +++++++++++++++++++++++++++++++++++++++++++++++++-- - include/grub/btrfs.h | 1 + - 2 files changed, 533 insertions(+), 20 deletions(-) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 63203034dfc..f1fff7385b5 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -38,6 +38,9 @@ - #include - #include - #include -+#include -+#include -+#include - #include - #include - #include -@@ -79,9 +82,11 @@ struct grub_btrfs_superblock - grub_uint64_t generation; - grub_uint64_t root_tree; - grub_uint64_t chunk_tree; -- grub_uint8_t dummy2[0x20]; -+ grub_uint8_t dummy2[0x18]; -+ grub_uint64_t bytes_used; - grub_uint64_t root_dir_objectid; -- grub_uint8_t dummy3[0x41]; -+ grub_uint64_t num_devices; -+ grub_uint8_t dummy3[0x39]; - struct grub_btrfs_device this_device; - char label[0x100]; - grub_uint8_t dummy4[0x100]; -@@ -121,6 +126,7 @@ struct grub_btrfs_data - grub_uint64_t exttree; - grub_size_t extsize; - struct grub_btrfs_extent_data *extent; -+ grub_uint64_t fs_tree; - }; - - struct grub_btrfs_chunk_item -@@ -191,6 +197,14 @@ struct grub_btrfs_leaf_descriptor - } *data; - }; - -+struct grub_btrfs_root_ref -+{ -+ grub_uint64_t dirid; -+ grub_uint64_t sequence; -+ grub_uint16_t name_len; -+ const char name[0]; -+} __attribute__ ((packed)); -+ - struct grub_btrfs_time - { - grub_int64_t sec; -@@ -236,6 +250,14 @@ struct grub_btrfs_extent_data - - #define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100 - -+#define GRUB_BTRFS_ROOT_TREE_OBJECTID 1ULL -+#define GRUB_BTRFS_FS_TREE_OBJECTID 5ULL -+#define GRUB_BTRFS_ROOT_REF_KEY 156 -+#define GRUB_BTRFS_ROOT_ITEM_KEY 132 -+ -+static grub_uint64_t btrfs_default_subvolid = 0; -+static char *btrfs_default_subvol = NULL; -+ - static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2, - 256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2 - }; -@@ -1173,6 +1195,62 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - return GRUB_ERR_NONE; - } - -+static grub_err_t -+get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree, -+ grub_uint64_t objectid, grub_uint64_t offset, -+ grub_uint64_t *fs_root); -+ -+static grub_err_t -+lookup_root_by_id(struct grub_btrfs_data *data, grub_uint64_t id) -+{ -+ grub_err_t err; -+ grub_uint64_t tree; -+ -+ err = get_fs_root(data, data->sblock.root_tree, id, -1, &tree); -+ if (!err) -+ data->fs_tree = tree; -+ return err; -+} -+ -+static grub_err_t -+find_path (struct grub_btrfs_data *data, -+ const char *path, struct grub_btrfs_key *key, -+ grub_uint64_t *tree, grub_uint8_t *type); -+ -+static grub_err_t -+lookup_root_by_name(struct grub_btrfs_data *data, const char *path) -+{ -+ grub_err_t err; -+ grub_uint64_t tree = 0; -+ grub_uint8_t type; -+ struct grub_btrfs_key key; -+ -+ err = find_path (data, path, &key, &tree, &type); -+ if (err) -+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path); -+ -+ if (key.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0) -+ return grub_error(GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", path); -+ -+ data->fs_tree = tree; -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+btrfs_handle_subvol(struct grub_btrfs_data *data __attribute__ ((unused))) -+{ -+ if (btrfs_default_subvol) -+ return lookup_root_by_name(data, btrfs_default_subvol); -+ -+ if (btrfs_default_subvolid) -+ return lookup_root_by_id(data, btrfs_default_subvolid); -+ -+ data->fs_tree = 0; -+ -+ return GRUB_ERR_NONE; -+} -+ -+ - static struct grub_btrfs_data * - grub_btrfs_mount (grub_device_t dev) - { -@@ -1208,6 +1286,13 @@ grub_btrfs_mount (grub_device_t dev) - data->devices_attached[0].dev = dev; - data->devices_attached[0].id = data->sblock.this_device.device_id; - -+ err = btrfs_handle_subvol (data); -+ if (err) -+ { -+ grub_free (data); -+ return NULL; -+ } -+ - return data; - } - -@@ -1673,6 +1758,91 @@ get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key, - return GRUB_ERR_NONE; - } - -+static grub_err_t -+find_pathname(struct grub_btrfs_data *data, grub_uint64_t objectid, -+ grub_uint64_t fs_root, const char *name, char **pathname) -+{ -+ grub_err_t err; -+ struct grub_btrfs_key key = { -+ .object_id = objectid, -+ .type = GRUB_BTRFS_ITEM_TYPE_INODE_REF, -+ .offset = 0, -+ }; -+ struct grub_btrfs_key key_out; -+ struct grub_btrfs_leaf_descriptor desc; -+ char *p = grub_strdup (name); -+ grub_disk_addr_t elemaddr; -+ grub_size_t elemsize; -+ grub_size_t alloc = grub_strlen(name) + 1; -+ -+ err = lower_bound(data, &key, &key_out, fs_root, -+ &elemaddr, &elemsize, &desc, 0); -+ if (err) -+ return grub_error(err, "lower_bound caught %d\n", err); -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF) -+ next(data, &desc, &elemaddr, &elemsize, &key_out); -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF) -+ { -+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, -+ "Can't find inode ref for {%"PRIuGRUB_UINT64_T -+ ", %u, %"PRIuGRUB_UINT64_T"} %"PRIuGRUB_UINT64_T -+ "/%"PRIuGRUB_SIZE"\n", -+ key_out.object_id, key_out.type, -+ key_out.offset, elemaddr, elemsize); -+ } -+ -+ -+ while (key_out.type == GRUB_BTRFS_ITEM_TYPE_INODE_REF && -+ key_out.object_id != key_out.offset) { -+ struct grub_btrfs_inode_ref *inode_ref; -+ char *new; -+ -+ inode_ref = grub_malloc(elemsize + 1); -+ if (!inode_ref) -+ return grub_error(GRUB_ERR_OUT_OF_MEMORY, -+ "couldn't allocate memory for inode_ref (%"PRIuGRUB_SIZE")\n", elemsize); -+ -+ err = grub_btrfs_read_logical(data, elemaddr, inode_ref, elemsize, 0); -+ if (err) -+ return grub_error(err, "read_logical caught %d\n", err); -+ -+ alloc += grub_le_to_cpu16 (inode_ref->n) + 2; -+ new = grub_malloc(alloc); -+ if (!new) -+ return grub_error(GRUB_ERR_OUT_OF_MEMORY, -+ "couldn't allocate memory for name (%"PRIuGRUB_SIZE")\n", alloc); -+ -+ grub_memcpy(new, inode_ref->name, grub_le_to_cpu16 (inode_ref->n)); -+ if (p) -+ { -+ new[grub_le_to_cpu16 (inode_ref->n)] = '/'; -+ grub_strcpy (new + grub_le_to_cpu16 (inode_ref->n) + 1, p); -+ grub_free(p); -+ } -+ else -+ new[grub_le_to_cpu16 (inode_ref->n)] = 0; -+ grub_free(inode_ref); -+ -+ p = new; -+ -+ key.object_id = key_out.offset; -+ -+ err = lower_bound(data, &key, &key_out, fs_root, &elemaddr, -+ &elemsize, &desc, 0); -+ if (err) -+ return grub_error(err, "lower_bound caught %d\n", err); -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF) -+ next(data, &desc, &elemaddr, &elemsize, &key_out); -+ -+ } -+ -+ *pathname = p; -+ return 0; -+} -+ - static grub_err_t - find_path (struct grub_btrfs_data *data, - const char *path, struct grub_btrfs_key *key, -@@ -1691,14 +1861,26 @@ find_path (struct grub_btrfs_data *data, - char *origpath = NULL; - unsigned symlinks_max = 32; - -- err = get_root (data, key, tree, type); -- if (err) -- return err; -- - origpath = grub_strdup (path); - if (!origpath) - return grub_errno; - -+ if (data->fs_tree) -+ { -+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -+ *tree = data->fs_tree; -+ /* This is a tree root, so everything starts at objectid 256 */ -+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); -+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -+ key->offset = 0; -+ } -+ else -+ { -+ err = get_root (data, key, tree, type); -+ if (err) -+ return err; -+ } -+ - while (1) - { - while (path[0] == '/') -@@ -1871,9 +2053,21 @@ find_path (struct grub_btrfs_data *data, - path = path_alloc = tmp; - if (path[0] == '/') - { -- err = get_root (data, key, tree, type); -- if (err) -- return err; -+ if (data->fs_tree) -+ { -+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -+ *tree = data->fs_tree; -+ /* This is a tree root, so everything starts at objectid 256 */ -+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); -+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -+ key->offset = 0; -+ } -+ else -+ { -+ err = get_root (data, key, tree, type); -+ if (err) -+ return err; -+ } - } - continue; - } -@@ -2114,18 +2308,10 @@ grub_btrfs_read (grub_file_t file, char *buf, grub_size_t len) - data->tree, file->offset, buf, len); - } - --static grub_err_t --grub_btrfs_uuid (grub_device_t device, char **uuid) -+static char * -+btrfs_unparse_uuid(struct grub_btrfs_data *data) - { -- struct grub_btrfs_data *data; -- -- *uuid = NULL; -- -- data = grub_btrfs_mount (device); -- if (!data) -- return grub_errno; -- -- *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", -+ return grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", - grub_be_to_cpu16 (data->sblock.uuid[0]), - grub_be_to_cpu16 (data->sblock.uuid[1]), - grub_be_to_cpu16 (data->sblock.uuid[2]), -@@ -2134,6 +2320,20 @@ grub_btrfs_uuid (grub_device_t device, char **uuid) - grub_be_to_cpu16 (data->sblock.uuid[5]), - grub_be_to_cpu16 (data->sblock.uuid[6]), - grub_be_to_cpu16 (data->sblock.uuid[7])); -+} -+ -+static grub_err_t -+grub_btrfs_uuid (grub_device_t device, char **uuid) -+{ -+ struct grub_btrfs_data *data; -+ -+ *uuid = NULL; -+ -+ data = grub_btrfs_mount (device); -+ if (!data) -+ return grub_errno; -+ -+ *uuid = btrfs_unparse_uuid(data); - - grub_btrfs_unmount (data); - -@@ -2190,6 +2390,242 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), - } - #endif - -+static grub_err_t -+grub_cmd_btrfs_info (grub_command_t cmd __attribute__ ((unused)), int argc, -+ char **argv) -+{ -+ grub_device_t dev; -+ char *devname; -+ struct grub_btrfs_data *data; -+ char *uuid; -+ -+ if (argc < 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); -+ -+ devname = grub_file_get_device_name(argv[0]); -+ -+ if (!devname) -+ return grub_errno; -+ -+ dev = grub_device_open (devname); -+ grub_free (devname); -+ if (!dev) -+ return grub_errno; -+ -+ data = grub_btrfs_mount (dev); -+ if (!data) -+ { -+ grub_device_close(dev); -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to open fs"); -+ } -+ -+ if (data->sblock.label) -+ grub_printf("Label: '%s' ", data->sblock.label); -+ else -+ grub_printf("Label: none "); -+ -+ uuid = btrfs_unparse_uuid(data); -+ -+ grub_printf(" uuid: %s\n\tTotal devices %" PRIuGRUB_UINT64_T -+ " FS bytes used %" PRIuGRUB_UINT64_T "\n", -+ uuid, grub_cpu_to_le64(data->sblock.num_devices), -+ grub_cpu_to_le64(data->sblock.bytes_used)); -+ -+ grub_btrfs_unmount (data); -+ -+ return 0; -+} -+ -+static grub_err_t -+get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree, -+ grub_uint64_t objectid, grub_uint64_t offset, -+ grub_uint64_t *fs_root) -+{ -+ grub_err_t err; -+ struct grub_btrfs_key key_in = { -+ .object_id = objectid, -+ .type = GRUB_BTRFS_ROOT_ITEM_KEY, -+ .offset = offset, -+ }, key_out; -+ struct grub_btrfs_leaf_descriptor desc; -+ grub_disk_addr_t elemaddr; -+ grub_size_t elemsize; -+ struct grub_btrfs_root_item ri; -+ -+ err = lower_bound(data, &key_in, &key_out, tree, -+ &elemaddr, &elemsize, &desc, 0); -+ -+ if (err) -+ return err; -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM || elemaddr == 0) -+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, -+ N_("can't find fs root for subvol %"PRIuGRUB_UINT64_T"\n"), -+ key_in.object_id); -+ -+ err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri), 0); -+ if (err) -+ return err; -+ -+ *fs_root = ri.tree; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static const struct grub_arg_option options[] = { -+ {"output", 'o', 0, N_("Output to a variable instead of the console."), -+ N_("VARNAME"), ARG_TYPE_STRING}, -+ {"path-only", 'p', 0, N_("Show only the path of the subvolume."), 0, 0}, -+ {"id-only", 'i', 0, N_("Show only the id of the subvolume."), 0, 0}, -+ {0, 0, 0, 0, 0, 0} -+}; -+ -+static grub_err_t -+grub_cmd_btrfs_list_subvols (struct grub_extcmd_context *ctxt, -+ int argc, char **argv) -+{ -+ struct grub_btrfs_data *data; -+ grub_device_t dev; -+ char *devname; -+ grub_uint64_t tree; -+ struct grub_btrfs_key key_in = { -+ .object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_FS_TREE_OBJECTID), -+ .type = GRUB_BTRFS_ROOT_REF_KEY, -+ .offset = 0, -+ }, key_out; -+ struct grub_btrfs_leaf_descriptor desc; -+ grub_disk_addr_t elemaddr; -+ grub_uint64_t fs_root = 0; -+ grub_size_t elemsize; -+ grub_size_t allocated = 0; -+ int r = 0; -+ grub_err_t err; -+ char *buf = NULL; -+ int print = 1; -+ int path_only = ctxt->state[1].set; -+ int num_only = ctxt->state[2].set; -+ char *varname = NULL; -+ char *output = NULL; -+ -+ if (ctxt->state[0].set) { -+ varname = ctxt->state[0].arg; -+ print = 0; -+ } -+ -+ if (argc < 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); -+ -+ devname = grub_file_get_device_name(argv[0]); -+ if (!devname) -+ return grub_errno; -+ -+ dev = grub_device_open (devname); -+ grub_free (devname); -+ if (!dev) -+ return grub_errno; -+ -+ data = grub_btrfs_mount(dev); -+ if (!data) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "could not open device"); -+ -+ tree = data->sblock.root_tree; -+ err = get_fs_root(data, tree, grub_cpu_to_le64_compile_time (GRUB_BTRFS_FS_TREE_OBJECTID), -+ 0, &fs_root); -+ if (err) -+ goto out; -+ -+ err = lower_bound(data, &key_in, &key_out, tree, -+ &elemaddr, &elemsize, &desc, 0); -+ -+ if (err) -+ { -+ grub_btrfs_unmount(data); -+ return err; -+ } -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF || elemaddr == 0) -+ { -+ r = next(data, &desc, &elemaddr, &elemsize, &key_out); -+ } -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF) { -+ err = GRUB_ERR_FILE_NOT_FOUND; -+ grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("can't find root refs")); -+ goto out; -+ } -+ -+ do -+ { -+ struct grub_btrfs_root_ref *ref; -+ char *p = NULL; -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF) -+ { -+ r = 0; -+ break; -+ } -+ -+ if (elemsize > allocated) -+ { -+ grub_free(buf); -+ allocated = 2 * elemsize; -+ buf = grub_malloc(allocated + 1); -+ if (!buf) -+ { -+ r = -grub_errno; -+ break; -+ } -+ } -+ ref = (struct grub_btrfs_root_ref *)buf; -+ -+ err = grub_btrfs_read_logical(data, elemaddr, buf, elemsize, 0); -+ if (err) -+ { -+ r = -err; -+ break; -+ } -+ buf[elemsize] = 0; -+ -+ find_pathname(data, ref->dirid, fs_root, ref->name, &p); -+ -+ if (print) -+ { -+ if (num_only) -+ grub_printf("ID %"PRIuGRUB_UINT64_T"\n", key_out.offset); -+ else if (path_only) -+ grub_printf("%s\n", p); -+ else -+ grub_printf("ID %"PRIuGRUB_UINT64_T" path %s\n", key_out.offset, p); -+ } else { -+ char *old = output; -+ if (num_only) -+ output = grub_xasprintf("%s%"PRIuGRUB_UINT64_T"\n", -+ old ?: "", key_out.offset); -+ else if (path_only) -+ output = grub_xasprintf("%s%s\n", old ?: "", p); -+ else -+ output = grub_xasprintf("%sID %"PRIuGRUB_UINT64_T" path %s\n", -+ old ?: "", key_out.offset, p); -+ -+ if (old) -+ grub_free(old); -+ } -+ -+ r = next(data, &desc, &elemaddr, &elemsize, &key_out); -+ } while(r > 0); -+ -+ if (output) -+ grub_env_set(varname, output); -+ -+out: -+ free_iterator(&desc); -+ grub_btrfs_unmount(data); -+ -+ grub_device_close (dev); -+ -+ return 0; -+} -+ - static struct grub_fs grub_btrfs_fs = { - .name = "btrfs", - .fs_dir = grub_btrfs_dir, -@@ -2205,12 +2641,88 @@ static struct grub_fs grub_btrfs_fs = { - #endif - }; - -+static grub_command_t cmd_info; -+static grub_extcmd_t cmd_list_subvols; -+ -+static char * -+subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val) -+{ -+ unsigned long long result = 0; -+ -+ grub_errno = GRUB_ERR_NONE; -+ if (*val) -+ { -+ result = grub_strtoull(val, NULL, 10); -+ if (grub_errno) -+ return NULL; -+ } -+ -+ grub_free (btrfs_default_subvol); -+ btrfs_default_subvol = NULL; -+ btrfs_default_subvolid = result; -+ return grub_strdup(val); -+} -+ -+static const char * -+subvolid_get_env (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val __attribute__ ((unused))) -+{ -+ if (btrfs_default_subvol) -+ return grub_xasprintf("subvol:%s", btrfs_default_subvol); -+ else if (btrfs_default_subvolid) -+ return grub_xasprintf("%"PRIuGRUB_UINT64_T, btrfs_default_subvolid); -+ else -+ return ""; -+} -+ -+static char * -+subvol_set_env (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val) -+{ -+ grub_free (btrfs_default_subvol); -+ btrfs_default_subvol = grub_strdup (val); -+ btrfs_default_subvolid = 0; -+ return grub_strdup(val); -+} -+ -+static const char * -+subvol_get_env (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val __attribute__ ((unused))) -+{ -+ if (btrfs_default_subvol) -+ return btrfs_default_subvol; -+ else if (btrfs_default_subvolid) -+ return grub_xasprintf("subvolid:%" PRIuGRUB_UINT64_T, -+ btrfs_default_subvolid); -+ else -+ return ""; -+} -+ - GRUB_MOD_INIT (btrfs) - { - grub_fs_register (&grub_btrfs_fs); -+ cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info, -+ "DEVICE", -+ "Print BtrFS info about DEVICE."); -+ cmd_list_subvols = grub_register_extcmd("btrfs-list-subvols", -+ grub_cmd_btrfs_list_subvols, 0, -+ "[-p|-n] [-o var] DEVICE", -+ "Print list of BtrFS subvolumes on " -+ "DEVICE.", options); -+ grub_register_variable_hook ("btrfs_subvol", subvol_get_env, -+ subvol_set_env); -+ grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env, -+ subvolid_set_env); - } - - GRUB_MOD_FINI (btrfs) - { -+ grub_register_variable_hook ("btrfs_subvol", NULL, NULL); -+ grub_register_variable_hook ("btrfs_subvolid", NULL, NULL); -+ grub_unregister_command (cmd_info); -+ grub_unregister_extcmd (cmd_list_subvols); - grub_fs_unregister (&grub_btrfs_fs); - } -+ -+// vim: si et sw=2: -diff --git a/include/grub/btrfs.h b/include/grub/btrfs.h -index 9d93fb6c182..234ad976771 100644 ---- a/include/grub/btrfs.h -+++ b/include/grub/btrfs.h -@@ -29,6 +29,7 @@ enum - GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM = 0x84, - GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF = 0x90, - GRUB_BTRFS_ITEM_TYPE_DEVICE = 0xd8, -+ GRUB_BTRFS_ITEM_TYPE_ROOT_REF = 0x9c, - GRUB_BTRFS_ITEM_TYPE_CHUNK = 0xe4 - }; - diff --git a/SOURCES/0058-Add-BLS-support-to-grub-mkconfig.patch b/SOURCES/0058-Add-BLS-support-to-grub-mkconfig.patch new file mode 100644 index 0000000..3e5b230 --- /dev/null +++ b/SOURCES/0058-Add-BLS-support-to-grub-mkconfig.patch @@ -0,0 +1,382 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 9 Dec 2016 15:40:29 -0500 +Subject: [PATCH] Add BLS support to grub-mkconfig + +GRUB now has BootLoaderSpec support, the user can choose to use this by +setting GRUB_ENABLE_BLSCFG to true in /etc/default/grub. On this setup, +the boot menu entries are not added to the grub.cfg, instead BLS config +files are parsed by blscfg command and the entries created dynamically. + +A 10_linux_bls grub.d snippet to generate menu entries from BLS files +is also added that can be used on platforms where the bootloader doesn't +have BLS support and only can parse a normal grub configuration file. + +Portions of the 10_linux_bls were taken from the ostree-grub-generator +script that's included in the OSTree project. + +Fixes to support multi-devices and generate a BLS section even if no +kernels are found in the boot directory were proposed by Yclept Nemo +and Tom Gundersen respectively. + +Signed-off-by: Peter Jones +[javierm: remove outdated URL for BLS document] +Signed-off-by: Javier Martinez Canillas +[iwienand@redhat.com: skip machine ID check when updating entries] +Signed-off-by: Ian Wienand +[rharwood: use sort(1), commit message composits, drop man pages] +Signed-off-by: Robbie Harwood +--- + util/grub-mkconfig.in | 9 +- + util/grub-mkconfig_lib.in | 22 ++++- + util/grub.d/10_linux.in | 218 +++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 243 insertions(+), 6 deletions(-) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index 535c0f0249..f55339a3f6 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -50,6 +50,8 @@ grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@" + export TEXTDOMAIN=@PACKAGE@ + export TEXTDOMAINDIR="@localedir@" + ++export GRUB_GRUBENV_UPDATE="yes" ++ + . "${pkgdatadir}/grub-mkconfig_lib" + + # Usage: usage +@@ -59,6 +61,7 @@ usage () { + gettext "Generate a grub config file"; echo + echo + print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")" ++ print_option_help "--no-grubenv-update" "$(gettext "do not update variables in the grubenv file")" + print_option_help "-h, --help" "$(gettext "print this message and exit")" + print_option_help "-V, --version" "$(gettext "print the version information and exit")" + echo +@@ -94,6 +97,9 @@ do + --output=*) + grub_cfg=`echo "$option" | sed 's/--output=//'` + ;; ++ --no-grubenv-update) ++ GRUB_GRUBENV_UPDATE="no" ++ ;; + -*) + gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 + usage +@@ -253,7 +259,8 @@ export GRUB_DEFAULT \ + GRUB_OS_PROBER_SKIP_LIST \ + GRUB_DISABLE_SUBMENU \ + GRUB_DEFAULT_DTB \ +- SUSE_BTRFS_SNAPSHOT_BOOTING ++ SUSE_BTRFS_SNAPSHOT_BOOTING \ ++ GRUB_ENABLE_BLSCFG + + if test "x${grub_cfg}" != "x"; then + rm -f "${grub_cfg}.new" +diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in +index 5e96f6cc5d..301d8a8a1e 100644 +--- a/util/grub-mkconfig_lib.in ++++ b/util/grub-mkconfig_lib.in +@@ -30,6 +30,9 @@ fi + if test "x$grub_file" = x; then + grub_file="${bindir}/@grub_file@" + fi ++if test "x$grub_editenv" = x; then ++ grub_editenv="${bindir}/@grub_editenv@" ++fi + if test "x$grub_mkrelpath" = x; then + grub_mkrelpath="${bindir}/@grub_mkrelpath@" + fi +@@ -122,8 +125,19 @@ EOF + fi + } + ++prepare_grub_to_access_device_with_variable () ++{ ++ device_variable="$1" ++ shift ++ prepare_grub_to_access_device "$@" ++ unset "device_variable" ++} ++ + prepare_grub_to_access_device () + { ++ if [ -z "$device_variable" ]; then ++ device_variable="root" ++ fi + old_ifs="$IFS" + IFS=' + ' +@@ -158,18 +172,18 @@ prepare_grub_to_access_device () + # otherwise set root as per value in device.map. + fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`" + if [ "x$fs_hint" != x ]; then +- echo "set root='$fs_hint'" ++ echo "set ${device_variable}='$fs_hint'" + fi + if [ "x${GRUB_DISABLE_UUID}" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then + hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints= + if [ "x$hints" != x ]; then + echo "if [ x\$feature_platform_search_hint = xy ]; then" +- echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}" ++ echo " search --no-floppy --fs-uuid --set=${device_variable} ${hints} ${fs_uuid}" + echo "else" +- echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}" ++ echo " search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}" + echo "fi" + else +- echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" ++ echo "search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}" + fi + fi + IFS="$old_ifs" +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 7bb3a211a7..2851952659 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -82,6 +82,218 @@ case x"$GRUB_FS" in + ;; + esac + ++populate_header_warn() ++{ ++if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then ++ bls_parser="10_linux script" ++else ++ bls_parser="blscfg command" ++fi ++cat </dev/null)) || : ++ ++ echo "${files[@]}" ++} ++ ++update_bls_cmdline() ++{ ++ local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++ local -a files=($(get_sorted_bls)) ++ ++ for bls in "${files[@]}"; do ++ local options="${cmdline}" ++ if [ -z "${bls##*debug*}" ]; then ++ options="${options} ${GRUB_CMDLINE_LINUX_DEBUG}" ++ fi ++ options="$(echo "${options}" | sed -e 's/\//\\\//g')" ++ sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf" ++ done ++} ++ ++populate_menu() ++{ ++ local -a files=($(get_sorted_bls)) ++ ++ gettext_printf "Generating boot entries from BLS files...\n" >&2 ++ ++ for bls in "${files[@]}"; do ++ read_config "${blsdir}/${bls}.conf" ++ ++ menu="${menu}menuentry '${title}' ${grub_arg} --id=${bls} {\n" ++ menu="${menu}\t linux ${linux} ${options}\n" ++ if [ -n "${initrd}" ] ; then ++ menu="${menu}\t initrd ${boot_prefix}${initrd}\n" ++ fi ++ menu="${menu}}\n\n" ++ done ++ # The printf command seems to be more reliable across shells for special character (\n, \t) evaluation ++ printf "$menu" ++} ++ ++# Make BLS the default if GRUB_ENABLE_BLSCFG was not set and grubby is not installed. ++if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null; then ++ GRUB_ENABLE_BLSCFG="true" ++fi ++ ++if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then ++ if [ x$dirname = x/ ]; then ++ if [ -z "${prepare_root_cache}" ]; then ++ prepare_grub_to_access_device ${GRUB_DEVICE} ++ fi ++ else ++ if [ -z "${prepare_boot_cache}" ]; then ++ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} ++ fi ++ fi ++ ++ if [ -d /sys/firmware/efi ]; then ++ bootefi_device="`${grub_probe} --target=device /boot/efi/`" ++ prepare_grub_to_access_device_with_variable boot ${bootefi_device} ++ else ++ boot_device="`${grub_probe} --target=device /boot/`" ++ prepare_grub_to_access_device_with_variable boot ${boot_device} ++ fi ++ ++ arch="$(uname -m)" ++ if [ "x${arch}" = "xppc64le" ] && [ -d /sys/firmware/opal ]; then ++ ++ BLS_POPULATE_MENU="true" ++ petitboot_path="/sys/firmware/devicetree/base/ibm,firmware-versions/petitboot" ++ ++ if test -e ${petitboot_path}; then ++ read -r -d '' petitboot_version < ${petitboot_path} ++ petitboot_version="$(echo ${petitboot_version//v})" ++ ++ if test -n ${petitboot_version}; then ++ major_version="$(echo ${petitboot_version} | cut -d . -f1)" ++ minor_version="$(echo ${petitboot_version} | cut -d . -f2)" ++ ++ re='^[0-9]+$' ++ if [[ $major_version =~ $re ]] && [[ $minor_version =~ $re ]] && ++ ([[ ${major_version} -gt 1 ]] || ++ [[ ${major_version} -eq 1 && ++ ${minor_version} -ge 8 ]]); then ++ BLS_POPULATE_MENU="false" ++ fi ++ fi ++ fi ++ fi ++ ++ populate_header_warn ++ ++ cat << EOF ++# The kernelopts variable should be defined in the grubenv file. But to ensure that menu ++# entries populated from BootLoaderSpec files that use this variable work correctly even ++# without a grubenv file, define a fallback kernelopts variable if this has not been set. ++# ++# The kernelopts variable in the grubenv file can be modified using the grubby tool or by ++# executing the grub2-mkconfig tool. For the latter, the values of the GRUB_CMDLINE_LINUX ++# and GRUB_CMDLINE_LINUX_DEFAULT options from /etc/default/grub file are used to set both ++# the kernelopts variable in the grubenv file and the fallback kernelopts variable. ++if [ -z "\${kernelopts}" ]; then ++ set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++fi ++EOF ++ ++ update_bls_cmdline ++ ++ if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then ++ populate_menu ++ else ++ cat << EOF ++ ++insmod blscfg ++blscfg ++EOF ++ fi ++ ++ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then ++ blsdir="/boot/loader/entries" ++ [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})" ++ if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then ++ blsdir=$(make_system_path_relative_to_its_root "${blsdir}") ++ if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then ++ ${grub_editenv} - set blsdir="${blsdir}" ++ fi ++ fi ++ ++ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then ++ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ++ fi ++ ++ if [ -n "${GRUB_DEFAULT_DTB}" ]; then ++ ${grub_editenv} - set devicetree="${GRUB_DEFAULT_DTB}" ++ fi ++ ++ if [ -n "${GRUB_SAVEDEFAULT}" ]; then ++ ${grub_editenv} - set save_default="${GRUB_SAVEDEFAULT}" ++ fi ++ fi ++ ++ exit 0 ++fi ++ + mktitle () + { + local title_type +@@ -121,6 +333,7 @@ linux_entry () + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" + fi ++ + if [ x$type != xsimple ] ; then + title=$(mktitle "$type" "$version") + if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then +@@ -231,6 +444,7 @@ is_top_level=true + while [ "x$list" != "x" ] ; do + linux=`version_find_latest $list` + gettext_printf "Found linux image: %s\n" "$linux" >&2 ++ + basename=`basename $linux` + dirname=`dirname $linux` + rel_dirname=`make_system_path_relative_to_its_root $dirname` +@@ -269,7 +483,9 @@ while [ "x$list" != "x" ] ; do + for i in ${initrd}; do + initrd_display="${initrd_display} ${dirname}/${i}" + done +- gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2 ++ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then ++ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2 ++ fi + fi + + fdt= diff --git a/SOURCES/0058-export-btrfs_subvol-and-btrfs_subvolid.patch b/SOURCES/0058-export-btrfs_subvol-and-btrfs_subvolid.patch deleted file mode 100644 index d38a6b8..0000000 --- a/SOURCES/0058-export-btrfs_subvol-and-btrfs_subvolid.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Wed, 18 Dec 2013 09:57:04 +0000 -Subject: [PATCH] export btrfs_subvol and btrfs_subvolid - -We should export btrfs_subvol and btrfs_subvolid to have both visible -to subsidiary configuration files loaded using configfile. - -Signed-off-by: Michael Chang ---- - grub-core/fs/btrfs.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index f1fff7385b5..ad1b56b716d 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -2714,6 +2714,8 @@ GRUB_MOD_INIT (btrfs) - subvol_set_env); - grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env, - subvolid_set_env); -+ grub_env_export ("btrfs_subvol"); -+ grub_env_export ("btrfs_subvolid"); - } - - GRUB_MOD_FINI (btrfs) diff --git a/SOURCES/0059-Don-t-attempt-to-backtrace-on-grub_abort-for-grub-em.patch b/SOURCES/0059-Don-t-attempt-to-backtrace-on-grub_abort-for-grub-em.patch new file mode 100644 index 0000000..1ac900c --- /dev/null +++ b/SOURCES/0059-Don-t-attempt-to-backtrace-on-grub_abort-for-grub-em.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 6 Feb 2018 11:16:28 +0100 +Subject: [PATCH] Don't attempt to backtrace on grub_abort() for grub-emu + +The emu platform doesn't have a grub_backtrace() implementation, so this +causes a build error. Don't attempt to call this when building grub-emu. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/kern/misc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index a3e215155b..c60601b699 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -1201,7 +1201,7 @@ static void __attribute__ ((noreturn)) + grub_abort (void) + { + #ifndef GRUB_UTIL +-#if defined(__i386__) || defined(__x86_64__) ++#if (defined(__i386__) || defined(__x86_64__)) && !defined(GRUB_MACHINE_EMU) + grub_backtrace(); + #endif + #endif diff --git a/SOURCES/0059-grub2-btrfs-03-follow_default.patch b/SOURCES/0059-grub2-btrfs-03-follow_default.patch deleted file mode 100644 index 2b9a136..0000000 --- a/SOURCES/0059-grub2-btrfs-03-follow_default.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Thu, 21 Aug 2014 03:39:11 +0000 -Subject: [PATCH] grub2-btrfs-03-follow_default - ---- - grub-core/fs/btrfs.c | 107 ++++++++++++++++++++++++++++++++++++--------------- - 1 file changed, 76 insertions(+), 31 deletions(-) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index ad1b56b716d..113c1f746c9 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -1256,6 +1256,7 @@ grub_btrfs_mount (grub_device_t dev) - { - struct grub_btrfs_data *data; - grub_err_t err; -+ const char *relpath = grub_env_get ("btrfs_relative_path"); - - if (!dev->disk) - { -@@ -1286,11 +1287,14 @@ grub_btrfs_mount (grub_device_t dev) - data->devices_attached[0].dev = dev; - data->devices_attached[0].id = data->sblock.this_device.device_id; - -- err = btrfs_handle_subvol (data); -- if (err) -+ if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) - { -- grub_free (data); -- return NULL; -+ err = btrfs_handle_subvol (data); -+ if (err) -+ { -+ grub_free (data); -+ return NULL; -+ } - } - - return data; -@@ -1855,24 +1859,39 @@ find_path (struct grub_btrfs_data *data, - grub_size_t allocated = 0; - struct grub_btrfs_dir_item *direl = NULL; - struct grub_btrfs_key key_out; -+ int follow_default; - const char *ctoken; - grub_size_t ctokenlen; - char *path_alloc = NULL; - char *origpath = NULL; - unsigned symlinks_max = 32; -+ const char *relpath = grub_env_get ("btrfs_relative_path"); - -+ follow_default = 0; - origpath = grub_strdup (path); - if (!origpath) - return grub_errno; - -- if (data->fs_tree) -+ if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) - { -- *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -- *tree = data->fs_tree; -- /* This is a tree root, so everything starts at objectid 256 */ -- key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); -- key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -- key->offset = 0; -+ if (data->fs_tree) -+ { -+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -+ *tree = data->fs_tree; -+ /* This is a tree root, so everything starts at objectid 256 */ -+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); -+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -+ key->offset = 0; -+ } -+ else -+ { -+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -+ *tree = data->sblock.root_tree; -+ key->object_id = data->sblock.root_dir_objectid; -+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -+ key->offset = 0; -+ follow_default = 1; -+ } - } - else - { -@@ -1883,15 +1902,23 @@ find_path (struct grub_btrfs_data *data, - - while (1) - { -- while (path[0] == '/') -- path++; -- if (!path[0]) -- break; -- slash = grub_strchr (path, '/'); -- if (!slash) -- slash = path + grub_strlen (path); -- ctoken = path; -- ctokenlen = slash - path; -+ if (!follow_default) -+ { -+ while (path[0] == '/') -+ path++; -+ if (!path[0]) -+ break; -+ slash = grub_strchr (path, '/'); -+ if (!slash) -+ slash = path + grub_strlen (path); -+ ctoken = path; -+ ctokenlen = slash - path; -+ } -+ else -+ { -+ ctoken = "default"; -+ ctokenlen = sizeof ("default") - 1; -+ } - - if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) - { -@@ -1902,7 +1929,9 @@ find_path (struct grub_btrfs_data *data, - - if (ctokenlen == 1 && ctoken[0] == '.') - { -- path = slash; -+ if (!follow_default) -+ path = slash; -+ follow_default = 0; - continue; - } - if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.') -@@ -1933,8 +1962,9 @@ find_path (struct grub_btrfs_data *data, - *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; - key->object_id = key_out.offset; - -- path = slash; -- -+ if (!follow_default) -+ path = slash; -+ follow_default = 0; - continue; - } - -@@ -2003,7 +2033,9 @@ find_path (struct grub_btrfs_data *data, - return err; - } - -- path = slash; -+ if (!follow_default) -+ path = slash; -+ follow_default = 0; - if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK) - { - struct grub_btrfs_inode inode; -@@ -2053,14 +2085,26 @@ find_path (struct grub_btrfs_data *data, - path = path_alloc = tmp; - if (path[0] == '/') - { -- if (data->fs_tree) -+ if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) - { -- *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -- *tree = data->fs_tree; -- /* This is a tree root, so everything starts at objectid 256 */ -- key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); -- key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -- key->offset = 0; -+ if (data->fs_tree) -+ { -+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -+ *tree = data->fs_tree; -+ /* This is a tree root, so everything starts at objectid 256 */ -+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); -+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -+ key->offset = 0; -+ } -+ else -+ { -+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; -+ *tree = data->sblock.root_tree; -+ key->object_id = data->sblock.root_dir_objectid; -+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -+ key->offset = 0; -+ follow_default = 1; -+ } - } - else - { -@@ -2716,6 +2760,7 @@ GRUB_MOD_INIT (btrfs) - subvolid_set_env); - grub_env_export ("btrfs_subvol"); - grub_env_export ("btrfs_subvolid"); -+ grub_env_export ("btrfs_relative_path"); - } - - GRUB_MOD_FINI (btrfs) diff --git a/SOURCES/0060-Add-grub2-switch-to-blscfg.patch b/SOURCES/0060-Add-grub2-switch-to-blscfg.patch new file mode 100644 index 0000000..e316116 --- /dev/null +++ b/SOURCES/0060-Add-grub2-switch-to-blscfg.patch @@ -0,0 +1,395 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 15 Mar 2018 14:12:40 -0400 +Subject: [PATCH] Add grub2-switch-to-blscfg + +Signed-off-by: Peter Jones +Signed-off-by: Javier Martinez Canillas +[jhlavac: Use ${etcdefaultgrub} instead of /etc/default/grub] +Signed-off-by: Jan Hlavac +[rharwood: skip on ostree installations, migrate man to h2m] +Signed-off-by: Robbie Harwood +--- + Makefile.util.def | 7 + + docs/man/grub-switch-to-blscfg.h2m | 2 + + util/grub-set-password.in | 2 +- + util/grub-switch-to-blscfg.in | 317 +++++++++++++++++++++++++++++++++++++ + util/grub.d/10_linux.in | 2 +- + 5 files changed, 328 insertions(+), 2 deletions(-) + create mode 100644 docs/man/grub-switch-to-blscfg.h2m + create mode 100644 util/grub-switch-to-blscfg.in + +diff --git a/Makefile.util.def b/Makefile.util.def +index 18a9242776..88f55e35c4 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -1348,6 +1348,13 @@ program = { + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + }; + ++script = { ++ name = grub-switch-to-blscfg; ++ common = util/grub-switch-to-blscfg.in; ++ mansection = 8; ++ installdir = sbin; ++}; ++ + program = { + name = grub-glue-efi; + mansection = 1; +diff --git a/docs/man/grub-switch-to-blscfg.h2m b/docs/man/grub-switch-to-blscfg.h2m +new file mode 100644 +index 0000000000..fa341426a5 +--- /dev/null ++++ b/docs/man/grub-switch-to-blscfg.h2m +@@ -0,0 +1,2 @@ ++[NAME] ++grub-switch-to-blscfg \- switch to using BLS config files +diff --git a/util/grub-set-password.in b/util/grub-set-password.in +index 5ebf50576d..c0b5ebbfdc 100644 +--- a/util/grub-set-password.in ++++ b/util/grub-set-password.in +@@ -1,6 +1,6 @@ + #!/bin/sh -e + +-EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/') ++EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') + if [ -d /sys/firmware/efi/efivars/ ]; then + grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` + else +diff --git a/util/grub-switch-to-blscfg.in b/util/grub-switch-to-blscfg.in +new file mode 100644 +index 0000000000..a851424beb +--- /dev/null ++++ b/util/grub-switch-to-blscfg.in +@@ -0,0 +1,317 @@ ++#! /bin/sh ++# ++# Set a default boot entry for GRUB. ++# Copyright (C) 2004,2009 Free Software Foundation, Inc. ++# ++# GRUB is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# GRUB is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with GRUB. If not, see . ++ ++#set -eu ++ ++# Initialize some variables. ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++sbindir=@sbindir@ ++bindir=@bindir@ ++sysconfdir="@sysconfdir@" ++PACKAGE_NAME=@PACKAGE_NAME@ ++PACKAGE_VERSION=@PACKAGE_VERSION@ ++datarootdir="@datarootdir@" ++datadir="@datadir@" ++if [ ! -v pkgdatadir ]; then ++ pkgdatadir="${datadir}/@PACKAGE@" ++fi ++ ++self=`basename $0` ++ ++grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@" ++grub_editenv=${bindir}/@grub_editenv@ ++etcdefaultgrub=/etc/default/grub ++ ++eval "$("${grub_get_kernel_settings}")" || true ++ ++EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') ++if [ -d /sys/firmware/efi/efivars/ ]; then ++ startlink=/etc/grub2-efi.cfg ++ grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` ++else ++ startlink=/etc/grub2.cfg ++ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` ++fi ++ ++blsdir=`echo "/@bootdirname@/loader/entries" | sed 's,//*,/,g'` ++ ++backupsuffix=.bak ++ ++arch="$(uname -m)" ++ ++export TEXTDOMAIN=@PACKAGE@ ++export TEXTDOMAINDIR="@localedir@" ++ ++. "${pkgdatadir}/grub-mkconfig_lib" ++ ++# Usage: usage ++# Print the usage. ++usage () { ++ gettext_printf "Usage: %s\n" "$self" ++ gettext "Switch to BLS config files.\n"; echo ++ echo ++ print_option_help "-h, --help" "$(gettext "print this message and exit")" ++ print_option_help "-V, --version" "$(gettext "print the version information and exit")" ++ echo ++ print_option_help "--backup-suffix=$(gettext "SUFFIX")" "$backupsuffix" ++ print_option_help "--bls-directory=$(gettext "DIR")" "$blsdir" ++ print_option_help "--config-file=$(gettext "FILE")" "$startlink" ++ print_option_help "--grub-defaults=$(gettext "FILE")" "$etcdefaultgrub" ++ print_option_help "--grub-directory=$(gettext "DIR")" "$grubdir" ++ # echo ++ # gettext "Report bugs to ."; echo ++} ++ ++argument () { ++ opt=$1 ++ shift ++ ++ if test $# -eq 0; then ++ gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2 ++ exit 1 ++ fi ++ echo $1 ++} ++ ++# Check the arguments. ++while test $# -gt 0 ++do ++ option=$1 ++ shift ++ ++ case "$option" in ++ -h | --help) ++ usage ++ exit 0 ;; ++ -V | --version) ++ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" ++ exit 0 ;; ++ ++ --backup-suffix) ++ backupsuffix=`argument $option "$@"` ++ shift ++ ;; ++ --backup-suffix=*) ++ backupsuffix=`echo "$option" | sed 's/--backup-suffix=//'` ++ ;; ++ ++ --bls-directory) ++ blsdir=`argument $option "$@"` ++ shift ++ ;; ++ --bls-directory=*) ++ blsdir=`echo "$option" | sed 's/--bls-directory=//'` ++ ;; ++ ++ --config-file) ++ startlink=`argument $option "$@"` ++ shift ++ ;; ++ --config-file=*) ++ startlink=`echo "$option" | sed 's/--config-file=//'` ++ ;; ++ ++ --grub-defaults) ++ etcdefaultgrub=`argument $option "$@"` ++ shift ++ ;; ++ --grub-defaults=*) ++ etcdefaultgrub=`echo "$option" | sed 's/--grub-defaults=//'` ++ ;; ++ ++ --grub-directory) ++ grubdir=`argument $option "$@"` ++ shift ++ ;; ++ --grub-directory=*) ++ grubdir=`echo "$option" | sed 's/--grub-directory=//'` ++ ;; ++ ++ *) ++ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 ++ usage ++ exit 1 ++ ;; ++ esac ++done ++ ++find_grub_cfg() { ++ local candidate="" ++ while [ -e "${candidate}" -o $# -gt 0 ] ++ do ++ if [ ! -e "${candidate}" ] ; then ++ candidate="$1" ++ shift ++ fi ++ ++ if [ -L "${candidate}" ]; then ++ candidate="$(realpath "${candidate}")" ++ fi ++ ++ if [ -f "${candidate}" ]; then ++ export GRUB_CONFIG_FILE="${candidate}" ++ return 0 ++ fi ++ done ++ return 1 ++} ++ ++if ! find_grub_cfg ${startlink} ${grubdir}/grub.cfg ; then ++ gettext_printf "Couldn't find config file\n" 1>&2 ++ exit 1 ++fi ++ ++if [ ! -d "${blsdir}" ]; then ++ install -m 700 -d "${blsdir}" ++fi ++ ++if [ -f /etc/machine-id ]; then ++ MACHINE_ID=$(cat /etc/machine-id) ++else ++ MACHINE_ID=$(dmesg | sha256sum) ++fi ++ ++mkbls() { ++ local kernelver=$1 && shift ++ local datetime=$1 && shift ++ local kernelopts=$1 && shift ++ ++ local debugname="" ++ local debugid="" ++ local flavor="" ++ ++ if [ "$kernelver" == *\+* ] ; then ++ local flavor=-"${kernelver##*+}" ++ if [ "${flavor}" == "-debug" ]; then ++ local debugname=" with debugging" ++ local debugid="-debug" ++ fi ++ fi ++ ( ++ source /etc/os-release ++ ++ cat <"${bls_target}" ++ ++ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then ++ bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")" ++ cp -aT "${bls_target}" "${bls_debug}" ++ title="$(grep '^title[ \t]' "${bls_debug}" | sed -e 's/^title[ \t]*//')" ++ options="$(echo "${cmdline} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')" ++ sed -i -e "s/^title.*/title ${title}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${bls_debug}" ++ sed -i -e "s/^options.*/options ${options}/" "${bls_debug}" ++ fi ++ done ++ ++ if [ -f "/boot/vmlinuz-0-rescue-${MACHINE_ID}" ]; then ++ mkbls "0-rescue-${MACHINE_ID}" "0" "${bootprefix}" >"${blsdir}/${MACHINE_ID}-0-rescue.conf" ++ fi ++} ++ ++# The grub2 EFI binary is not copied to the ESP as a part of an ostree ++# transaction. Make sure a grub2 version with BLS support is installed ++# but only do this if the blsdir is not set, to make sure that the BLS ++# parsing module will search for the BLS snippets in the default path. ++if test -f /run/ostree-booted && test -d /sys/firmware/efi/efivars && \ ++ ! ${grub_editenv} - list | grep -q blsdir && \ ++ mountpoint -q /boot; then ++ grub_binary="$(find /usr/lib/ostree-boot/efi/EFI/${EFIDIR}/ -name grub*.efi)" ++ install -m 700 ${grub_binary} ${grubdir} || exit 1 ++ # Create a hidden file to indicate that grub2 now has BLS support. ++ touch /boot/grub2/.grub2-blscfg-supported ++fi ++ ++GENERATE=0 ++if grep '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" \ ++ | grep -vq '^GRUB_ENABLE_BLSCFG="*true"*\s*$' ; then ++ if ! sed -i"${backupsuffix}" \ ++ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=true,' \ ++ "${etcdefaultgrub}" ; then ++ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}" ++ exit 1 ++ fi ++ GENERATE=1 ++elif ! grep -q '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" ; then ++ if ! echo 'GRUB_ENABLE_BLSCFG=true' >> "${etcdefaultgrub}" ; then ++ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}" ++ exit 1 ++ fi ++ GENERATE=1 ++fi ++ ++if [ "${GENERATE}" -eq 1 ] ; then ++ copy_bls ++ ++ if [ $arch = "x86_64" ] && [ ! -d /sys/firmware/efi ]; then ++ mod_dir="i386-pc" ++ elif [ $arch = "ppc64" -o $arch = "ppc64le" ] && [ ! -d /sys/firmware/opal ]; then ++ mod_dir="powerpc-ieee1275" ++ fi ++ ++ if [ -n "${mod_dir}" ]; then ++ for mod in blscfg increment; do ++ install -m 700 ${prefix}/lib/grub/${mod_dir}/${mod}.mod ${grubdir}/$mod_dir/ || exit 1 ++ done ++ fi ++ ++ cp -af "${GRUB_CONFIG_FILE}" "${GRUB_CONFIG_FILE}${backupsuffix}" ++ if ! grub2-mkconfig -o "${GRUB_CONFIG_FILE}" ; then ++ install -m 700 "${GRUB_CONFIG_FILE}${backupsuffix}" "${GRUB_CONFIG_FILE}" ++ sed -i"${backupsuffix}" \ ++ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=false,' \ ++ "${etcdefaultgrub}" ++ gettext_printf "Updating %s failed\n" "${GRUB_CONFIG_FILE}" ++ exit 1 ++ fi ++fi ++ ++# Bye. ++exit 0 +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 2851952659..e490e1a43a 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -138,7 +138,7 @@ blsdir="/boot/loader/entries" + + get_sorted_bls() + { +- if ! [ -d "${blsdir}" ]; then ++ if ! [ -d "${blsdir}" ] || [ -f /run/ostree-booted ] || [ -d /ostree/repo ]; then + return + fi + diff --git a/SOURCES/0060-grub2-btrfs-04-grub2-install.patch b/SOURCES/0060-grub2-btrfs-04-grub2-install.patch deleted file mode 100644 index f91c31a..0000000 --- a/SOURCES/0060-grub2-btrfs-04-grub2-install.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Thu, 21 Aug 2014 03:39:11 +0000 -Subject: [PATCH] grub2-btrfs-04-grub2-install - ---- - grub-core/osdep/linux/getroot.c | 7 +++++++ - grub-core/osdep/unix/config.c | 17 +++++++++++++++-- - util/config.c | 10 ++++++++++ - util/grub-install.c | 15 +++++++++++++++ - util/grub-mkrelpath.c | 6 ++++++ - include/grub/emu/config.h | 1 + - 6 files changed, 54 insertions(+), 2 deletions(-) - -diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c -index 001b818fe58..caf9b1ccd3f 100644 ---- a/grub-core/osdep/linux/getroot.c -+++ b/grub-core/osdep/linux/getroot.c -@@ -376,6 +376,7 @@ get_btrfs_fs_prefix (const char *mount_path) - return NULL; - } - -+int use_relative_path_on_btrfs = 0; - - char ** - grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) -@@ -519,6 +520,12 @@ again: - { - ret = grub_find_root_devices_from_btrfs (dir); - fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path); -+ if (use_relative_path_on_btrfs) -+ { -+ if (fs_prefix) -+ free (fs_prefix); -+ fs_prefix = xstrdup ("/"); -+ } - } - else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0) - { -diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c -index 7d6325138ce..46a881530c0 100644 ---- a/grub-core/osdep/unix/config.c -+++ b/grub-core/osdep/unix/config.c -@@ -82,6 +82,19 @@ grub_util_load_config (struct grub_util_config *cfg) - if (v) - cfg->grub_distributor = xstrdup (v); - -+ v = getenv ("SUSE_BTRFS_SNAPSHOT_BOOTING"); -+ if (v) -+ { -+ if (grub_strncmp(v, "true", sizeof ("true") - 1) == 0) -+ { -+ cfg->is_suse_btrfs_snapshot_enabled = 1; -+ } -+ else -+ { -+ cfg->is_suse_btrfs_snapshot_enabled = 0; -+ } -+ } -+ - cfgfile = grub_util_get_config_filename (); - if (!grub_util_is_regular (cfgfile)) - return; -@@ -105,8 +118,8 @@ grub_util_load_config (struct grub_util_config *cfg) - *ptr++ = *iptr; - } - -- strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\" " -- "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\""); -+ strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\nSUSE_BTRFS_SNAPSHOT_BOOTING=%s\\n\" " -+ "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\" \"$SUSE_BTRFS_SNAPSHOT_BOOTING\""); - - argv[2] = script; - argv[3] = '\0'; -diff --git a/util/config.c b/util/config.c -index ebcdd8f5e22..f044a880a76 100644 ---- a/util/config.c -+++ b/util/config.c -@@ -42,6 +42,16 @@ grub_util_parse_config (FILE *f, struct grub_util_config *cfg, int simple) - cfg->is_cryptodisk_enabled = 1; - continue; - } -+ if (grub_strncmp (ptr, "SUSE_BTRFS_SNAPSHOT_BOOTING=", -+ sizeof ("SUSE_BTRFS_SNAPSHOT_BOOTING=") - 1) == 0) -+ { -+ ptr += sizeof ("SUSE_BTRFS_SNAPSHOT_BOOTING=") - 1; -+ if (*ptr == '"' || *ptr == '\'') -+ ptr++; -+ if (grub_strncmp(ptr, "true", sizeof ("true") - 1) == 0) -+ cfg->is_suse_btrfs_snapshot_enabled = 1; -+ continue; -+ } - if (grub_strncmp (ptr, "GRUB_DISTRIBUTOR=", - sizeof ("GRUB_DISTRIBUTOR=") - 1) == 0) - { -diff --git a/util/grub-install.c b/util/grub-install.c -index 0fbe7f78c6d..0f66f36d23a 100644 ---- a/util/grub-install.c -+++ b/util/grub-install.c -@@ -827,6 +827,8 @@ fill_core_services (const char *core_services) - free (sysv_plist); - } - -+extern int use_relative_path_on_btrfs; -+ - int - main (int argc, char *argv[]) - { -@@ -860,6 +862,9 @@ main (int argc, char *argv[]) - - grub_util_load_config (&config); - -+ if (config.is_suse_btrfs_snapshot_enabled) -+ use_relative_path_on_btrfs = 1; -+ - if (!bootloader_id && config.grub_distributor) - { - char *ptr; -@@ -1352,6 +1357,16 @@ main (int argc, char *argv[]) - fprintf (load_cfg_f, "set debug='%s'\n", - debug_image); - } -+ -+ if (config.is_suse_btrfs_snapshot_enabled -+ && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0) -+ { -+ if (!load_cfg_f) -+ load_cfg_f = grub_util_fopen (load_cfg, "wb"); -+ have_load_cfg = 1; -+ fprintf (load_cfg_f, "set btrfs_relative_path='y'\n"); -+ } -+ - char *prefix_drive = NULL; - char *install_drive = NULL; - -diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c -index 47a241a391b..5db7a9a7d97 100644 ---- a/util/grub-mkrelpath.c -+++ b/util/grub-mkrelpath.c -@@ -40,9 +40,12 @@ struct arguments - }; - - static struct argp_option options[] = { -+ {"relative", 'r', 0, 0, "use relative path on btrfs", 0}, - { 0, 0, 0, 0, 0, 0 } - }; - -+extern int use_relative_path_on_btrfs; -+ - static error_t - argp_parser (int key, char *arg, struct argp_state *state) - { -@@ -52,6 +55,9 @@ argp_parser (int key, char *arg, struct argp_state *state) - - switch (key) - { -+ case 'r': -+ use_relative_path_on_btrfs = 1; -+ break; - case ARGP_KEY_ARG: - if (state->arg_num == 0) - arguments->pathname = xstrdup (arg); -diff --git a/include/grub/emu/config.h b/include/grub/emu/config.h -index 875d5896ce1..c9a7e5f4ade 100644 ---- a/include/grub/emu/config.h -+++ b/include/grub/emu/config.h -@@ -37,6 +37,7 @@ struct grub_util_config - { - int is_cryptodisk_enabled; - char *grub_distributor; -+ int is_suse_btrfs_snapshot_enabled; - }; - - void diff --git a/SOURCES/0061-grub2-btrfs-05-grub2-mkconfig.patch b/SOURCES/0061-grub2-btrfs-05-grub2-mkconfig.patch deleted file mode 100644 index 8270505..0000000 --- a/SOURCES/0061-grub2-btrfs-05-grub2-mkconfig.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Thu, 21 Aug 2014 03:39:11 +0000 -Subject: [PATCH] grub2-btrfs-05-grub2-mkconfig - -Signed-off-by: Michael Chang ---- - util/grub-mkconfig.in | 3 ++- - util/grub-mkconfig_lib.in | 4 ++++ - util/grub.d/00_header.in | 25 ++++++++++++++++++++++++- - util/grub.d/10_linux.in | 4 ++++ - util/grub.d/20_linux_xen.in | 4 ++++ - 5 files changed, 38 insertions(+), 2 deletions(-) - -diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in -index 005f093809b..535c0f02499 100644 ---- a/util/grub-mkconfig.in -+++ b/util/grub-mkconfig.in -@@ -252,7 +252,8 @@ export GRUB_DEFAULT \ - GRUB_BADRAM \ - GRUB_OS_PROBER_SKIP_LIST \ - GRUB_DISABLE_SUBMENU \ -- GRUB_DEFAULT_DTB -+ GRUB_DEFAULT_DTB \ -+ SUSE_BTRFS_SNAPSHOT_BOOTING - - if test "x${grub_cfg}" != "x"; then - rm -f "${grub_cfg}.new" -diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in -index 42c2ea9ba50..fafeac95061 100644 ---- a/util/grub-mkconfig_lib.in -+++ b/util/grub-mkconfig_lib.in -@@ -52,7 +52,11 @@ grub_warn () - - make_system_path_relative_to_its_root () - { -+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] ; then -+ "${grub_mkrelpath}" -r "$1" -+ else - "${grub_mkrelpath}" "$1" -+ fi - } - - is_path_readable_by_grub () -diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in -index 858b526c925..de727e6ee6b 100644 ---- a/util/grub.d/00_header.in -+++ b/util/grub.d/00_header.in -@@ -27,6 +27,14 @@ export TEXTDOMAINDIR="@localedir@" - - . "$pkgdatadir/grub-mkconfig_lib" - -+if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] && -+ [ "x${GRUB_FS}" = "xbtrfs" ] ; then -+ cat </dev/null || true` -diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in -index ada20775a14..e9e73b815fb 100644 ---- a/util/grub.d/20_linux_xen.in -+++ b/util/grub.d/20_linux_xen.in -@@ -73,10 +73,14 @@ fi - - case x"$GRUB_FS" in - xbtrfs) -+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then -+ GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}" -+ else - rootsubvol="`make_system_path_relative_to_its_root /`" - rootsubvol="${rootsubvol#/}" - if [ "x${rootsubvol}" != x ]; then - GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" -+ fi - fi;; - xzfs) - rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true` diff --git a/SOURCES/0061-make-better-backtraces.patch b/SOURCES/0061-make-better-backtraces.patch new file mode 100644 index 0000000..7fdcaf7 --- /dev/null +++ b/SOURCES/0061-make-better-backtraces.patch @@ -0,0 +1,910 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 9 Jul 2019 17:05:03 +0200 +Subject: [PATCH] make better backtraces + +Signed-off-by: Peter Jones +--- + Makefile.util.def | 6 ++ + grub-core/Makefile.core.def | 16 ++-- + grub-core/{lib => commands}/backtrace.c | 2 +- + grub-core/gdb/cstub.c | 1 - + grub-core/kern/arm64/backtrace.c | 94 ++++++++++++++++++++++++ + grub-core/kern/backtrace.c | 97 +++++++++++++++++++++++++ + grub-core/kern/dl.c | 45 ++++++++++++ + grub-core/kern/i386/backtrace.c | 125 ++++++++++++++++++++++++++++++++ + grub-core/kern/i386/pc/init.c | 4 +- + grub-core/kern/ieee1275/init.c | 1 - + grub-core/kern/misc.c | 13 ++-- + grub-core/kern/mm.c | 6 +- + grub-core/lib/arm64/backtrace.c | 62 ---------------- + grub-core/lib/i386/backtrace.c | 78 -------------------- + include/grub/backtrace.h | 10 ++- + include/grub/dl.h | 2 + + include/grub/kernel.h | 3 + + grub-core/kern/arm/efi/startup.S | 2 + + grub-core/kern/arm/startup.S | 2 + + grub-core/kern/arm64/efi/startup.S | 2 + + grub-core/kern/i386/qemu/startup.S | 3 +- + grub-core/kern/ia64/efi/startup.S | 3 +- + grub-core/kern/sparc64/ieee1275/crt0.S | 3 +- + grub-core/Makefile.am | 1 + + 24 files changed, 414 insertions(+), 167 deletions(-) + rename grub-core/{lib => commands}/backtrace.c (98%) + create mode 100644 grub-core/kern/arm64/backtrace.c + create mode 100644 grub-core/kern/backtrace.c + create mode 100644 grub-core/kern/i386/backtrace.c + delete mode 100644 grub-core/lib/arm64/backtrace.c + delete mode 100644 grub-core/lib/i386/backtrace.c + +diff --git a/Makefile.util.def b/Makefile.util.def +index 88f55e35c4..bda9fd1211 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -51,6 +51,12 @@ library = { + common = grub-core/partmap/msdos.c; + common = grub-core/fs/proc.c; + common = grub-core/fs/archelp.c; ++ common = grub-core/kern/backtrace.c; ++ ++ x86 = grub-core/kern/i386/backtrace.c; ++ i386_xen = grub-core/kern/i386/backtrace.c; ++ x86_64_xen = grub-core/kern/i386/backtrace.c; ++ arm64 = grub-core/kern/arm64/backtrace.c; + }; + + library = { +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 058c88ac3a..52ec0fafcd 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -142,6 +142,12 @@ kernel = { + common = kern/rescue_reader.c; + common = kern/term.c; + common = kern/verifiers.c; ++ common = kern/backtrace.c; ++ ++ x86 = kern/i386/backtrace.c; ++ i386_xen = kern/i386/backtrace.c; ++ x86_64_xen = kern/i386/backtrace.c; ++ arm64 = kern/arm64/backtrace.c; + + noemu = kern/compiler-rt.c; + noemu = kern/mm.c; +@@ -188,9 +194,6 @@ kernel = { + + softdiv = lib/division.c; + +- x86 = lib/i386/backtrace.c; +- x86 = lib/backtrace.c; +- + i386 = kern/i386/dl.c; + i386_xen = kern/i386/dl.c; + i386_xen_pvh = kern/i386/dl.c; +@@ -2399,15 +2402,12 @@ module = { + + module = { + name = backtrace; +- x86 = lib/i386/backtrace.c; +- i386_xen_pvh = lib/i386/backtrace.c; +- i386_xen = lib/i386/backtrace.c; +- x86_64_xen = lib/i386/backtrace.c; +- common = lib/backtrace.c; ++ common = commands/backtrace.c; + enable = x86; + enable = i386_xen_pvh; + enable = i386_xen; + enable = x86_64_xen; ++ enable = arm64; + }; + + module = { +diff --git a/grub-core/lib/backtrace.c b/grub-core/commands/backtrace.c +similarity index 98% +rename from grub-core/lib/backtrace.c +rename to grub-core/commands/backtrace.c +index c0ad6ab8be..8b5ec3913b 100644 +--- a/grub-core/lib/backtrace.c ++++ b/grub-core/commands/backtrace.c +@@ -54,7 +54,7 @@ grub_cmd_backtrace (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) + { +- grub_backtrace (); ++ grub_backtrace (1); + return 0; + } + +diff --git a/grub-core/gdb/cstub.c b/grub-core/gdb/cstub.c +index b64acd70fe..99281472d3 100644 +--- a/grub-core/gdb/cstub.c ++++ b/grub-core/gdb/cstub.c +@@ -215,7 +215,6 @@ grub_gdb_trap (int trap_no) + grub_printf ("Unhandled exception 0x%x at ", trap_no); + grub_backtrace_print_address ((void *) grub_gdb_regs[PC]); + grub_printf ("\n"); +- grub_backtrace_pointer ((void *) grub_gdb_regs[EBP]); + grub_fatal ("Unhandled exception"); + } + +diff --git a/grub-core/kern/arm64/backtrace.c b/grub-core/kern/arm64/backtrace.c +new file mode 100644 +index 0000000000..019c6fdfef +--- /dev/null ++++ b/grub-core/kern/arm64/backtrace.c +@@ -0,0 +1,94 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_STACK_FRAME 102400 ++ ++struct fplr ++{ ++ void *lr; ++ struct fplr *fp; ++}; ++ ++void ++grub_backtrace_pointer (void *frame, unsigned int skip) ++{ ++ unsigned int x = 0; ++ struct fplr *fplr = (struct fplr *)frame; ++ ++ while (fplr) ++ { ++ const char *name = NULL; ++ char *addr = NULL; ++ ++ grub_dprintf("backtrace", "fp is %p next_fp is %p\n", ++ fplr, fplr->fp); ++ ++ if (x >= skip) ++ { ++ name = grub_get_symbol_by_addr (fplr->lr, 1); ++ if (name) ++ addr = grub_resolve_symbol (name); ++ grub_backtrace_print_address (fplr->lr); ++ ++ if (addr && addr != fplr->lr) ++ grub_printf (" %s() %p+%p \n", name ? name : "unknown", addr, ++ (void *)((grub_uint64_t)fplr->lr - (grub_uint64_t)addr)); ++ else ++ grub_printf(" %s() %p \n", name ? name : "unknown", addr); ++ ++ } ++ ++ x += 1; ++ ++ if (fplr->fp < fplr || ++ (grub_uint64_t)fplr->fp - (grub_uint64_t)fplr > MAX_STACK_FRAME || ++ fplr->fp == fplr) ++ { ++ break; ++ } ++ fplr = fplr->fp; ++ } ++} ++ ++asm ("\t.global \"_text\"\n" ++ "_text:\n" ++ "\t.quad .text\n" ++ "\t.global \"_data\"\n" ++ "_data:\n" ++ "\t.quad .data\n" ++ ); ++ ++extern grub_uint64_t _text; ++extern grub_uint64_t _data; ++ ++void ++grub_backtrace_arch (unsigned int skip) ++{ ++ grub_printf ("Backtrace (.text %p .data %p):\n", ++ (void *)_text, (void *)_data); ++ skip += 1; ++ grub_backtrace_pointer(__builtin_frame_address(0), skip); ++} +diff --git a/grub-core/kern/backtrace.c b/grub-core/kern/backtrace.c +new file mode 100644 +index 0000000000..4a82e865cc +--- /dev/null ++++ b/grub-core/kern/backtrace.c +@@ -0,0 +1,97 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static void ++grub_backtrace_print_address_default (void *addr) ++{ ++#ifndef GRUB_UTIL ++ grub_dl_t mod; ++ void *start_addr; ++ ++ FOR_DL_MODULES (mod) ++ { ++ grub_dl_segment_t segment; ++ for (segment = mod->segment; segment; segment = segment->next) ++ if (segment->addr <= addr && (grub_uint8_t *) segment->addr ++ + segment->size > (grub_uint8_t *) addr) ++ { ++ grub_printf ("%s.%x+%" PRIxGRUB_SIZE, mod->name, ++ segment->section, ++ (grub_size_t) ++ ((grub_uint8_t *)addr - (grub_uint8_t *)segment->addr)); ++ return; ++ } ++ } ++ ++ start_addr = grub_resolve_symbol ("_start"); ++ if (start_addr && start_addr < addr) ++ grub_printf ("kernel+%" PRIxGRUB_SIZE, ++ (grub_size_t) ++ ((grub_uint8_t *)addr - (grub_uint8_t *)start_addr)); ++ else ++#endif ++ grub_printf ("%p", addr); ++} ++ ++static void ++grub_backtrace_pointer_default (void *frame __attribute__((__unused__)), ++ unsigned int skip __attribute__((__unused__))) ++{ ++ return; ++} ++ ++void ++grub_backtrace_pointer (void *frame, unsigned int skip) ++ __attribute__((__weak__, ++ __alias__(("grub_backtrace_pointer_default")))); ++ ++void ++grub_backtrace_print_address (void *addr) ++ __attribute__((__weak__, ++ __alias__(("grub_backtrace_print_address_default")))); ++ ++static void ++grub_backtrace_arch_default(unsigned int skip) ++{ ++ grub_backtrace_pointer(__builtin_frame_address(0), skip + 1); ++} ++ ++void grub_backtrace_arch (unsigned int skip) ++ __attribute__((__weak__, __alias__(("grub_backtrace_arch_default")))); ++ ++void grub_backtrace (unsigned int skip) ++{ ++ grub_backtrace_arch(skip + 1); ++} ++ ++void grub_debug_backtrace (const char * const debug, ++ unsigned int skip) ++{ ++ if (grub_debug_enabled (debug)) ++ grub_backtrace (skip + 1); ++} +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 7afb9e6f72..88d2077709 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -124,6 +124,50 @@ grub_dl_resolve_symbol (const char *name) + return 0; + } + ++void * ++grub_resolve_symbol (const char *name) ++{ ++ grub_symbol_t sym; ++ ++ sym = grub_dl_resolve_symbol (name); ++ if (sym) ++ return sym->addr; ++ return NULL; ++} ++ ++const char * ++grub_get_symbol_by_addr(const void *addr, int isfunc) ++{ ++ unsigned int i; ++ grub_symbol_t before = NULL, after = NULL; ++ for (i = 0; i < GRUB_SYMTAB_SIZE; i++) ++ { ++ grub_symbol_t sym; ++ for (sym = grub_symtab[i]; sym; sym = sym->next) ++ { ++ //grub_printf ("addr 0x%08llx symbol %s\n", (unsigned long long)sym->addr, sym->name); ++ if (sym->addr > addr) ++ { ++ if (!after || sym->addr > after->addr) ++ after = sym; ++ } ++ ++ if (isfunc != sym->isfunc) ++ continue; ++ if (sym->addr > addr) ++ continue; ++ ++ if ((!before && sym->addr <= addr) || (before && before->addr <= sym->addr)) ++ before = sym; ++ } ++ } ++ ++ if (before && addr < after->addr) ++ return before->name; ++ ++ return NULL; ++} ++ + /* Register a symbol with the name NAME and the address ADDR. */ + grub_err_t + grub_dl_register_symbol (const char *name, void *addr, int isfunc, +@@ -336,6 +380,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) + const char *str; + Elf_Word size, entsize; + ++ grub_dprintf ("modules", "Resolving symbols for \"%s\"\n", mod->name); + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) +diff --git a/grub-core/kern/i386/backtrace.c b/grub-core/kern/i386/backtrace.c +new file mode 100644 +index 0000000000..2413f9a57d +--- /dev/null ++++ b/grub-core/kern/i386/backtrace.c +@@ -0,0 +1,125 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_STACK_FRAME 102400 ++ ++void ++grub_backtrace_pointer (void *frame, unsigned int skip) ++{ ++ void **ebp = (void **)frame; ++ unsigned long x = 0; ++ ++ while (ebp) ++ { ++ void **next_ebp = (void **)ebp[0]; ++ const char *name = NULL; ++ char *addr = NULL; ++ ++ grub_dprintf("backtrace", "ebp is %p next_ebp is %p\n", ebp, next_ebp); ++ ++ if (x >= skip) ++ { ++ name = grub_get_symbol_by_addr (ebp[1], 1); ++ if (name) ++ addr = grub_resolve_symbol (name); ++ grub_backtrace_print_address (ebp[1]); ++ ++ if (addr && addr != ebp[1]) ++ grub_printf (" %s() %p+%p \n", name ? name : "unknown", addr, ++ (char *)((char *)ebp[1] - addr)); ++ else ++ grub_printf(" %s() %p \n", name ? name : "unknown", addr); ++ ++#if 0 ++ grub_printf ("("); ++ for (i = 0, arg = ebp[2]; arg != next_ebp && i < 12; arg++, i++) ++ grub_printf ("%p,", arg); ++ grub_printf (")\n"); ++#endif ++ } ++ ++ x += 1; ++ ++ if (next_ebp < ebp || next_ebp - ebp > MAX_STACK_FRAME || next_ebp == ebp) ++ { ++ //grub_printf ("Invalid stack frame at %p (%p)\n", ebp, next_ebp); ++ break; ++ } ++ ebp = next_ebp; ++ } ++} ++ ++#if defined (__x86_64__) ++asm ("\t.global \"_text\"\n" ++ "_text:\n" ++ "\t.quad .text\n" ++ "\t.global \"_data\"\n" ++ "_data:\n" ++ "\t.quad .data\n" ++ ); ++#elif defined(__i386__) ++asm ("\t.global \"_text\"\n" ++ "_text:\n" ++ "\t.long .text\n" ++ "\t.global \"_data\"\n" ++ "_data:\n" ++ "\t.long .data\n" ++ ); ++#else ++#warning I dunno... ++#endif ++ ++extern unsigned long _text; ++extern unsigned long _data; ++ ++#ifdef GRUB_UTIL ++#define EXT_C(x) x ++#endif ++ ++void ++grub_backtrace_arch (unsigned int skip) ++{ ++ grub_printf ("Backtrace (.text %p .data %p):\n", ++ (void *)_text, (void *)_data); ++ skip += 1; ++#if defined (__x86_64__) ++ asm volatile ("movq %%rbp, %%rdi\n" ++ "movq 0, %%rsi\n" ++ "movl %0, %%esi\n" ++ "call " EXT_C("grub_backtrace_pointer") ++ : ++ : "r" (skip)); ++#elif defined(__i386__) ++ asm volatile ("addl $8, %%esp\n" ++ "pushl %0\n" ++ "pushl %%ebp\n" ++ "call " EXT_C("grub_backtrace_pointer") ++ : ++ : "r" (skip)); ++#else ++ grub_backtrace_pointer(__builtin_frame_address(0), skip); ++#endif ++} +diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c +index 27bc68b8a5..b51d0abfa6 100644 +--- a/grub-core/kern/i386/pc/init.c ++++ b/grub-core/kern/i386/pc/init.c +@@ -153,7 +153,7 @@ compact_mem_regions (void) + } + + grub_addr_t grub_modbase; +-extern grub_uint8_t _start[], _edata[]; ++extern grub_uint8_t _edata[]; + + /* Helper for grub_machine_init. */ + static int +@@ -217,7 +217,7 @@ grub_machine_init (void) + /* This has to happen before any BIOS calls. */ + grub_via_workaround_init (); + +- grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start); ++ grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - (grub_uint8_t *)_start); + + /* Initialize the console as early as possible. */ + grub_console_init (); +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 0cd2a62723..937c1bc44c 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -63,7 +63,6 @@ + #define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024) + #endif + +-extern char _start[]; + extern char _end[]; + + #ifdef __sparc__ +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index c60601b699..a432a6be54 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -1197,15 +1197,15 @@ grub_printf_fmt_check (const char *fmt, const char *fmt_expected) + + + /* Abort GRUB. This function does not return. */ +-static void __attribute__ ((noreturn)) ++static inline void __attribute__ ((noreturn)) + grub_abort (void) + { +-#ifndef GRUB_UTIL +-#if (defined(__i386__) || defined(__x86_64__)) && !defined(GRUB_MACHINE_EMU) +- grub_backtrace(); ++#if !defined(GRUB_MACHINE_EMU) && !defined(GRUB_UTIL) ++ grub_backtrace (1); ++#else ++ grub_printf ("\n"); + #endif +-#endif +- grub_printf ("\nAborted."); ++ grub_printf ("Aborted."); + + #ifndef GRUB_UTIL + if (grub_term_inputs) +@@ -1232,6 +1232,7 @@ grub_fatal (const char *fmt, ...) + { + va_list ap; + ++ grub_printf ("\n"); + va_start (ap, fmt); + grub_vprintf (_(fmt), ap); + va_end (ap); +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index c070afc621..d8c8377578 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -97,13 +97,13 @@ get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r) + break; + + if (! *r) +- grub_fatal ("out of range pointer %p", ptr); ++ grub_fatal ("out of range pointer %p\n", ptr); + + *p = (grub_mm_header_t) ptr - 1; + if ((*p)->magic == GRUB_MM_FREE_MAGIC) +- grub_fatal ("double free at %p", *p); ++ grub_fatal ("double free at %p\n", *p); + if ((*p)->magic != GRUB_MM_ALLOC_MAGIC) +- grub_fatal ("alloc magic is broken at %p: %lx", *p, ++ grub_fatal ("alloc magic is broken at %p: %lx\n", *p, + (unsigned long) (*p)->magic); + } + +diff --git a/grub-core/lib/arm64/backtrace.c b/grub-core/lib/arm64/backtrace.c +deleted file mode 100644 +index 1079b5380e..0000000000 +--- a/grub-core/lib/arm64/backtrace.c ++++ /dev/null +@@ -1,62 +0,0 @@ +-/* +- * GRUB -- GRand Unified Bootloader +- * Copyright (C) 2009 Free Software Foundation, Inc. +- * +- * GRUB is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * GRUB is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with GRUB. If not, see . +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define MAX_STACK_FRAME 102400 +- +-void +-grub_backtrace_pointer (int frame) +-{ +- while (1) +- { +- void *lp = __builtin_return_address (frame); +- if (!lp) +- break; +- +- lp = __builtin_extract_return_addr (lp); +- +- grub_printf ("%p: ", lp); +- grub_backtrace_print_address (lp); +- grub_printf (" ("); +- for (i = 0; i < 2; i++) +- grub_printf ("%p,", ((void **)ptr) [i + 2]); +- grub_printf ("%p)\n", ((void **)ptr) [i + 2]); +- nptr = *(void **)ptr; +- if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME +- || nptr == ptr) +- { +- grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr); +- break; +- } +- ptr = nptr; +- } +-} +- +-void +-grub_backtrace (void) +-{ +- grub_backtrace_pointer (1); +-} +- +diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c +deleted file mode 100644 +index c67273db3a..0000000000 +--- a/grub-core/lib/i386/backtrace.c ++++ /dev/null +@@ -1,78 +0,0 @@ +-/* +- * GRUB -- GRand Unified Bootloader +- * Copyright (C) 2009 Free Software Foundation, Inc. +- * +- * GRUB is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * GRUB is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with GRUB. If not, see . +- */ +-#include +-#ifdef GRUB_UTIL +-#define REALLY_GRUB_UTIL GRUB_UTIL +-#undef GRUB_UTIL +-#endif +- +-#include +-#include +- +-#ifdef REALLY_GRUB_UTIL +-#define GRUB_UTIL REALLY_GRUB_UTIL +-#undef REALLY_GRUB_UTIL +-#endif +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define MAX_STACK_FRAME 102400 +- +-void +-grub_backtrace_pointer (void *ebp) +-{ +- void *ptr, *nptr; +- unsigned i; +- +- ptr = ebp; +- while (1) +- { +- grub_printf ("%p: ", ptr); +- grub_backtrace_print_address (((void **) ptr)[1]); +- grub_printf (" ("); +- for (i = 0; i < 2; i++) +- grub_printf ("%p,", ((void **)ptr) [i + 2]); +- grub_printf ("%p)\n", ((void **)ptr) [i + 2]); +- nptr = *(void **)ptr; +- if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME +- || nptr == ptr) +- { +- grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr); +- break; +- } +- ptr = nptr; +- } +-} +- +-void +-grub_backtrace (void) +-{ +-#ifdef __x86_64__ +- asm volatile ("movq %%rbp, %%rdi\n" +- "callq *%%rax": :"a"(grub_backtrace_pointer)); +-#else +- asm volatile ("movl %%ebp, %%eax\n" +- "calll *%%ecx": :"c"(grub_backtrace_pointer)); +-#endif +-} +- +diff --git a/include/grub/backtrace.h b/include/grub/backtrace.h +index 395519762f..275cf85e2d 100644 +--- a/include/grub/backtrace.h ++++ b/include/grub/backtrace.h +@@ -19,8 +19,14 @@ + #ifndef GRUB_BACKTRACE_HEADER + #define GRUB_BACKTRACE_HEADER 1 + +-void grub_backtrace (void); +-void grub_backtrace_pointer (void *ptr); ++#include ++#include ++ ++void EXPORT_FUNC(grub_debug_backtrace) (const char * const debug, ++ unsigned int skip); ++void EXPORT_FUNC(grub_backtrace) (unsigned int skip); ++void grub_backtrace_arch (unsigned int skip); ++void grub_backtrace_pointer (void *ptr, unsigned int skip); + void grub_backtrace_print_address (void *addr); + + #endif +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 91933b85f2..2f76e6b043 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -259,6 +259,8 @@ grub_dl_is_persistent (grub_dl_t mod) + + #endif + ++void * EXPORT_FUNC(grub_resolve_symbol) (const char *name); ++const char * EXPORT_FUNC(grub_get_symbol_by_addr) (const void *addr, int isfunc); + grub_err_t grub_dl_register_symbol (const char *name, void *addr, + int isfunc, grub_dl_t mod); + +diff --git a/include/grub/kernel.h b/include/grub/kernel.h +index abbca5ea33..300a9766cd 100644 +--- a/include/grub/kernel.h ++++ b/include/grub/kernel.h +@@ -111,6 +111,9 @@ grub_addr_t grub_modules_get_end (void); + + #endif + ++void EXPORT_FUNC(start) (void); ++void EXPORT_FUNC(_start) (void); ++ + /* The start point of the C code. */ + void grub_main (void) __attribute__ ((noreturn)); + +diff --git a/grub-core/kern/arm/efi/startup.S b/grub-core/kern/arm/efi/startup.S +index 9f8265315a..f3bc41f9d0 100644 +--- a/grub-core/kern/arm/efi/startup.S ++++ b/grub-core/kern/arm/efi/startup.S +@@ -23,6 +23,8 @@ + .file "startup.S" + .text + .arm ++ .globl start, _start ++FUNCTION(start) + FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in r1/r0. +diff --git a/grub-core/kern/arm/startup.S b/grub-core/kern/arm/startup.S +index 3946fe8e18..5679a1d00a 100644 +--- a/grub-core/kern/arm/startup.S ++++ b/grub-core/kern/arm/startup.S +@@ -48,6 +48,8 @@ + + .text + .arm ++ .globl start, _start ++FUNCTION(start) + FUNCTION(_start) + b codestart + +diff --git a/grub-core/kern/arm64/efi/startup.S b/grub-core/kern/arm64/efi/startup.S +index 666a7ee3c9..41676bdb2b 100644 +--- a/grub-core/kern/arm64/efi/startup.S ++++ b/grub-core/kern/arm64/efi/startup.S +@@ -19,7 +19,9 @@ + #include + + .file "startup.S" ++ .globl start, _start + .text ++FUNCTION(start) + FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0. +diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S +index 0d89858d9b..939f182fc7 100644 +--- a/grub-core/kern/i386/qemu/startup.S ++++ b/grub-core/kern/i386/qemu/startup.S +@@ -24,7 +24,8 @@ + + .text + .code32 +- .globl _start ++ .globl start, _start ++start: + _start: + jmp codestart + +diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S +index d75c6d7cc7..8f2a593e52 100644 +--- a/grub-core/kern/ia64/efi/startup.S ++++ b/grub-core/kern/ia64/efi/startup.S +@@ -24,8 +24,9 @@ + .psr lsb + .lsb + +- .global _start ++ .global start, _start + .proc _start ++start: + _start: + alloc loc0=ar.pfs,2,4,0,0 + mov loc1=rp +diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S +index 03b916f053..701bf63abc 100644 +--- a/grub-core/kern/sparc64/ieee1275/crt0.S ++++ b/grub-core/kern/sparc64/ieee1275/crt0.S +@@ -22,7 +22,8 @@ + + .text + .align 4 +- .globl _start ++ .globl start, _start ++start: + _start: + ba codestart + mov %o4, %o0 +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index ee88e44e97..bfd29a3bf0 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -66,6 +66,7 @@ CLEANFILES += grub_script.yy.c grub_script.yy.h + + include $(srcdir)/Makefile.core.am + ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/backtrace.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h diff --git a/SOURCES/0062-grub2-btrfs-06-subvol-mount.patch b/SOURCES/0062-grub2-btrfs-06-subvol-mount.patch deleted file mode 100644 index 9a51175..0000000 --- a/SOURCES/0062-grub2-btrfs-06-subvol-mount.patch +++ /dev/null @@ -1,537 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Tue, 9 Jul 2019 13:56:16 +0200 -Subject: [PATCH] grub2-btrfs-06-subvol-mount - ---- - grub-core/fs/btrfs.c | 195 +++++++++++++++++++++++++++++++++++++++- - grub-core/osdep/linux/getroot.c | 148 +++++++++++++++++++++++++++++- - util/grub-install.c | 49 ++++++++++ - include/grub/emu/getroot.h | 5 ++ - 4 files changed, 392 insertions(+), 5 deletions(-) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 113c1f746c9..d323746ecfa 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -41,6 +41,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -266,6 +267,12 @@ static grub_err_t - grub_btrfs_read_logical (struct grub_btrfs_data *data, - grub_disk_addr_t addr, void *buf, grub_size_t size, - int recursion_depth); -+static grub_err_t -+get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key, -+ grub_uint64_t *tree, grub_uint8_t *type); -+ -+grub_uint64_t -+find_mtab_subvol_tree (const char *path, char **path_in_subvol); - - static grub_err_t - read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb) -@@ -1223,9 +1230,26 @@ lookup_root_by_name(struct grub_btrfs_data *data, const char *path) - grub_err_t err; - grub_uint64_t tree = 0; - grub_uint8_t type; -+ grub_uint64_t saved_tree; - struct grub_btrfs_key key; - -+ if (path[0] == '\0') -+ { -+ data->fs_tree = 0; -+ return GRUB_ERR_NONE; -+ } -+ -+ err = get_root (data, &key, &tree, &type); -+ if (err) -+ return err; -+ -+ saved_tree = data->fs_tree; -+ data->fs_tree = tree; -+ - err = find_path (data, path, &key, &tree, &type); -+ -+ data->fs_tree = saved_tree; -+ - if (err) - return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path); - -@@ -2199,11 +2223,20 @@ grub_btrfs_dir (grub_device_t device, const char *path, - int r = 0; - grub_uint64_t tree; - grub_uint8_t type; -+ char *new_path = NULL; - - if (!data) - return grub_errno; - -- err = find_path (data, path, &key_in, &tree, &type); -+ tree = find_mtab_subvol_tree (path, &new_path); -+ -+ if (tree) -+ data->fs_tree = tree; -+ -+ err = find_path (data, new_path ? new_path : path, &key_in, &tree, &type); -+ if (new_path) -+ grub_free (new_path); -+ - if (err) - { - grub_btrfs_unmount (data); -@@ -2305,11 +2338,21 @@ grub_btrfs_open (struct grub_file *file, const char *name) - struct grub_btrfs_inode inode; - grub_uint8_t type; - struct grub_btrfs_key key_in; -+ grub_uint64_t tree; -+ char *new_path = NULL; - - if (!data) - return grub_errno; - -- err = find_path (data, name, &key_in, &data->tree, &type); -+ tree = find_mtab_subvol_tree (name, &new_path); -+ -+ if (tree) -+ data->fs_tree = tree; -+ -+ err = find_path (data, new_path ? new_path : name, &key_in, &data->tree, &type); -+ if (new_path) -+ grub_free (new_path); -+ - if (err) - { - grub_btrfs_unmount (data); -@@ -2480,6 +2523,150 @@ grub_cmd_btrfs_info (grub_command_t cmd __attribute__ ((unused)), int argc, - return 0; - } - -+struct grub_btrfs_mtab -+{ -+ struct grub_btrfs_mtab *next; -+ struct grub_btrfs_mtab **prev; -+ char *path; -+ char *subvol; -+ grub_uint64_t tree; -+}; -+ -+typedef struct grub_btrfs_mtab* grub_btrfs_mtab_t; -+ -+static struct grub_btrfs_mtab *btrfs_mtab; -+ -+#define FOR_GRUB_MTAB(var) FOR_LIST_ELEMENTS (var, btrfs_mtab) -+#define FOR_GRUB_MTAB_SAFE(var, next) FOR_LIST_ELEMENTS_SAFE((var), (next), btrfs_mtab) -+ -+static void -+add_mountpoint (const char *path, const char *subvol, grub_uint64_t tree) -+{ -+ grub_btrfs_mtab_t m = grub_malloc (sizeof (*m)); -+ -+ m->path = grub_strdup (path); -+ m->subvol = grub_strdup (subvol); -+ m->tree = tree; -+ grub_list_push (GRUB_AS_LIST_P (&btrfs_mtab), GRUB_AS_LIST (m)); -+} -+ -+static grub_err_t -+grub_cmd_btrfs_mount_subvol (grub_command_t cmd __attribute__ ((unused)), int argc, -+ char **argv) -+{ -+ char *devname, *dirname, *subvol; -+ struct grub_btrfs_key key_in; -+ grub_uint8_t type; -+ grub_uint64_t tree; -+ grub_uint64_t saved_tree; -+ grub_err_t err; -+ struct grub_btrfs_data *data = NULL; -+ grub_device_t dev = NULL; -+ -+ if (argc < 3) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "required and "); -+ -+ devname = grub_file_get_device_name(argv[0]); -+ dev = grub_device_open (devname); -+ grub_free (devname); -+ -+ if (!dev) -+ { -+ err = grub_errno; -+ goto err_out; -+ } -+ -+ dirname = argv[1]; -+ subvol = argv[2]; -+ -+ data = grub_btrfs_mount (dev); -+ if (!data) -+ { -+ err = grub_errno; -+ goto err_out; -+ } -+ -+ err = find_path (data, dirname, &key_in, &tree, &type); -+ if (err) -+ goto err_out; -+ -+ if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) -+ { -+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); -+ goto err_out; -+ } -+ -+ err = get_root (data, &key_in, &tree, &type); -+ -+ if (err) -+ goto err_out; -+ -+ saved_tree = data->fs_tree; -+ data->fs_tree = tree; -+ err = find_path (data, subvol, &key_in, &tree, &type); -+ data->fs_tree = saved_tree; -+ -+ if (err) -+ goto err_out; -+ -+ if (key_in.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0) -+ { -+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", subvol); -+ goto err_out; -+ } -+ -+ grub_btrfs_unmount (data); -+ grub_device_close (dev); -+ add_mountpoint (dirname, subvol, tree); -+ -+ return GRUB_ERR_NONE; -+ -+err_out: -+ -+ if (data) -+ grub_btrfs_unmount (data); -+ -+ if (dev) -+ grub_device_close (dev); -+ -+ return err; -+} -+ -+grub_uint64_t -+find_mtab_subvol_tree (const char *path, char **path_in_subvol) -+{ -+ grub_btrfs_mtab_t m, cm; -+ grub_uint64_t tree; -+ -+ if (!path || !path_in_subvol) -+ return 0; -+ -+ *path_in_subvol = NULL; -+ tree = 0; -+ cm = NULL; -+ -+ FOR_GRUB_MTAB (m) -+ { -+ if (grub_strncmp (path, m->path, grub_strlen (m->path)) == 0) -+ { -+ if (!cm) -+ cm = m; -+ else -+ if (grub_strcmp (m->path, cm->path) > 0) -+ cm = m; -+ } -+ } -+ -+ if (cm) -+ { -+ const char *s = path + grub_strlen (cm->path); -+ *path_in_subvol = (s[0] == '\0') ? grub_strdup ("/") : grub_strdup (s); -+ tree = cm->tree; -+ } -+ -+ return tree; -+} -+ - static grub_err_t - get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree, - grub_uint64_t objectid, grub_uint64_t offset, -@@ -2686,6 +2873,7 @@ static struct grub_fs grub_btrfs_fs = { - }; - - static grub_command_t cmd_info; -+static grub_command_t cmd_mount_subvol; - static grub_extcmd_t cmd_list_subvols; - - static char * -@@ -2749,6 +2937,9 @@ GRUB_MOD_INIT (btrfs) - cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info, - "DEVICE", - "Print BtrFS info about DEVICE."); -+ cmd_mount_subvol = grub_register_command("btrfs-mount-subvol", grub_cmd_btrfs_mount_subvol, -+ "DEVICE DIRECTORY SUBVOL", -+ "Set btrfs DEVICE the DIRECTORY a mountpoint of SUBVOL."); - cmd_list_subvols = grub_register_extcmd("btrfs-list-subvols", - grub_cmd_btrfs_list_subvols, 0, - "[-p|-n] [-o var] DEVICE", -diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c -index caf9b1ccd3f..28790307e00 100644 ---- a/grub-core/osdep/linux/getroot.c -+++ b/grub-core/osdep/linux/getroot.c -@@ -107,6 +107,14 @@ struct btrfs_ioctl_search_key - grub_uint32_t unused[9]; - }; - -+struct btrfs_ioctl_search_header { -+ grub_uint64_t transid; -+ grub_uint64_t objectid; -+ grub_uint64_t offset; -+ grub_uint32_t type; -+ grub_uint32_t len; -+}; -+ - struct btrfs_ioctl_search_args { - struct btrfs_ioctl_search_key key; - grub_uint64_t buf[(4096 - sizeof(struct btrfs_ioctl_search_key)) -@@ -378,6 +386,109 @@ get_btrfs_fs_prefix (const char *mount_path) - - int use_relative_path_on_btrfs = 0; - -+static char * -+get_btrfs_subvol (const char *path) -+{ -+ struct btrfs_ioctl_ino_lookup_args args; -+ grub_uint64_t tree_id; -+ int fd = -1; -+ char *ret = NULL; -+ -+ fd = open (path, O_RDONLY); -+ -+ if (fd < 0) -+ return NULL; -+ -+ memset (&args, 0, sizeof(args)); -+ args.objectid = GRUB_BTRFS_TREE_ROOT_OBJECTID; -+ -+ if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0) -+ goto error; -+ -+ tree_id = args.treeid; -+ -+ while (tree_id != GRUB_BTRFS_ROOT_VOL_OBJECTID) -+ { -+ struct btrfs_ioctl_search_args sargs; -+ struct grub_btrfs_root_backref *br; -+ struct btrfs_ioctl_search_header *search_header; -+ char *old; -+ grub_uint16_t len; -+ grub_uint64_t inode_id; -+ -+ memset (&sargs, 0, sizeof(sargs)); -+ -+ sargs.key.tree_id = 1; -+ sargs.key.min_objectid = tree_id; -+ sargs.key.max_objectid = tree_id; -+ -+ sargs.key.min_offset = 0; -+ sargs.key.max_offset = ~0ULL; -+ sargs.key.min_transid = 0; -+ sargs.key.max_transid = ~0ULL; -+ sargs.key.min_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF; -+ sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF; -+ -+ sargs.key.nr_items = 1; -+ -+ if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0) -+ goto error; -+ -+ if (sargs.key.nr_items == 0) -+ goto error; -+ -+ search_header = (struct btrfs_ioctl_search_header *)sargs.buf; -+ br = (struct grub_btrfs_root_backref *) (search_header + 1); -+ -+ len = grub_le_to_cpu16 (br->n); -+ inode_id = grub_le_to_cpu64 (br->inode_id); -+ tree_id = search_header->offset; -+ -+ old = ret; -+ ret = malloc (len + 1); -+ memcpy (ret, br->name, len); -+ ret[len] = '\0'; -+ -+ if (inode_id != GRUB_BTRFS_TREE_ROOT_OBJECTID) -+ { -+ char *s; -+ -+ memset(&args, 0, sizeof(args)); -+ args.treeid = search_header->offset; -+ args.objectid = inode_id; -+ -+ if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0) -+ goto error; -+ -+ s = xasprintf ("%s%s", args.name, ret); -+ free (ret); -+ ret = s; -+ } -+ -+ if (old) -+ { -+ char *s = xasprintf ("%s/%s", ret, old); -+ free (ret); -+ free (old); -+ ret = s; -+ } -+ } -+ -+ close (fd); -+ return ret; -+ -+error: -+ -+ if (fd >= 0) -+ close (fd); -+ if (ret) -+ free (ret); -+ -+ return NULL; -+} -+ -+void (*grub_find_root_btrfs_mount_path_hook)(const char *mount_path); -+ - char ** - grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) - { -@@ -519,12 +630,15 @@ again: - else if (grub_strcmp (entries[i].fstype, "btrfs") == 0) - { - ret = grub_find_root_devices_from_btrfs (dir); -- fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path); - if (use_relative_path_on_btrfs) - { -- if (fs_prefix) -- free (fs_prefix); - fs_prefix = xstrdup ("/"); -+ if (grub_find_root_btrfs_mount_path_hook) -+ grub_find_root_btrfs_mount_path_hook (entries[i].enc_path); -+ } -+ else -+ { -+ fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path); - } - } - else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0) -@@ -1150,6 +1264,34 @@ grub_util_get_grub_dev_os (const char *os_dev) - return grub_dev; - } - -+ -+char * -+grub_util_get_btrfs_subvol (const char *path, char **mount_path) -+{ -+ char *mp = NULL; -+ -+ if (mount_path) -+ *mount_path = NULL; -+ -+ auto void -+ mount_path_hook (const char *m) -+ { -+ mp = strdup (m); -+ } -+ -+ grub_find_root_btrfs_mount_path_hook = mount_path_hook; -+ grub_free (grub_find_root_devices_from_mountinfo (path, NULL)); -+ grub_find_root_btrfs_mount_path_hook = NULL; -+ -+ if (!mp) -+ return NULL; -+ -+ if (mount_path) -+ *mount_path = mp; -+ -+ return get_btrfs_subvol (mp); -+} -+ - char * - grub_make_system_path_relative_to_its_root_os (const char *path) - { -diff --git a/util/grub-install.c b/util/grub-install.c -index 0f66f36d23a..84ed6e88ecb 100644 ---- a/util/grub-install.c -+++ b/util/grub-install.c -@@ -1569,6 +1569,55 @@ main (int argc, char *argv[]) - prefix_drive = xasprintf ("(%s)", grub_drives[0]); - } - -+#ifdef __linux__ -+ -+ if (config.is_suse_btrfs_snapshot_enabled -+ && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0) -+ { -+ char *subvol = NULL; -+ char *mount_path = NULL; -+ char **rootdir_devices = NULL; -+ char *rootdir_path = grub_util_path_concat (2, "/", rootdir); -+ -+ if (grub_util_is_directory (rootdir_path)) -+ rootdir_devices = grub_guess_root_devices (rootdir_path); -+ -+ free (rootdir_path); -+ -+ if (rootdir_devices && rootdir_devices[0]) -+ if (grub_strcmp (rootdir_devices[0], grub_devices[0]) == 0) -+ subvol = grub_util_get_btrfs_subvol (platdir, &mount_path); -+ -+ if (subvol && mount_path) -+ { -+ char *def_subvol; -+ -+ def_subvol = grub_util_get_btrfs_subvol ("/", NULL); -+ -+ if (def_subvol) -+ { -+ if (!load_cfg_f) -+ load_cfg_f = grub_util_fopen (load_cfg, "wb"); -+ have_load_cfg = 1; -+ -+ if (grub_strcmp (subvol, def_subvol) != 0) -+ fprintf (load_cfg_f, "btrfs-mount-subvol ($root) %s %s\n", mount_path, subvol); -+ free (def_subvol); -+ } -+ } -+ -+ for (curdev = rootdir_devices; *curdev; curdev++) -+ free (*curdev); -+ if (rootdir_devices) -+ free (rootdir_devices); -+ if (subvol) -+ free (subvol); -+ if (mount_path) -+ free (mount_path); -+ } -+ -+#endif -+ - char mkimage_target[200]; - const char *core_name = NULL; - -diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h -index 73fa2d34abb..9c642ae3fe3 100644 ---- a/include/grub/emu/getroot.h -+++ b/include/grub/emu/getroot.h -@@ -53,6 +53,11 @@ char ** - grub_find_root_devices_from_mountinfo (const char *dir, char **relroot); - #endif - -+#ifdef __linux__ -+char * -+grub_util_get_btrfs_subvol (const char *path, char **mount_path); -+#endif -+ - /* Devmapper functions provided by getroot_devmapper.c. */ - void - grub_util_pull_devmapper (const char *os_dev); diff --git a/SOURCES/0062-normal-don-t-draw-our-startup-message-if-debug-is-se.patch b/SOURCES/0062-normal-don-t-draw-our-startup-message-if-debug-is-se.patch new file mode 100644 index 0000000..a916299 --- /dev/null +++ b/SOURCES/0062-normal-don-t-draw-our-startup-message-if-debug-is-se.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 9 Nov 2017 15:58:52 -0500 +Subject: [PATCH] normal: don't draw our startup message if debug is set + +--- + grub-core/normal/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 55558cc0b9..af9792c963 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -430,6 +430,9 @@ grub_normal_reader_init (int nested) + const char *msg_esc = _("ESC at any time exits."); + char *msg_formatted; + ++ if (grub_env_get ("debug") != NULL) ++ return 0; ++ + msg_formatted = grub_xasprintf (_("Minimal BASH-like line editing is supported. For " + "the first word, TAB lists possible command completions. Anywhere " + "else TAB lists possible device or file completions. %s"), diff --git a/SOURCES/0063-Fallback-to-old-subvol-name-scheme-to-support-old-sn.patch b/SOURCES/0063-Fallback-to-old-subvol-name-scheme-to-support-old-sn.patch deleted file mode 100644 index b02ab53..0000000 --- a/SOURCES/0063-Fallback-to-old-subvol-name-scheme-to-support-old-sn.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrei Borzenkov -Date: Tue, 21 Jun 2016 16:44:17 +0000 -Subject: [PATCH] Fallback to old subvol name scheme to support old snapshot - config - -Ref: bsc#953538 ---- - grub-core/fs/btrfs.c | 32 +++++++++++++++++++++++++++++++- - 1 file changed, 31 insertions(+), 1 deletion(-) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index d323746ecfa..673ded03522 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -1260,11 +1260,41 @@ lookup_root_by_name(struct grub_btrfs_data *data, const char *path) - return GRUB_ERR_NONE; - } - -+static grub_err_t -+lookup_root_by_name_fallback(struct grub_btrfs_data *data, const char *path) -+{ -+ grub_err_t err; -+ grub_uint64_t tree = 0; -+ grub_uint8_t type; -+ struct grub_btrfs_key key; -+ -+ err = find_path (data, path, &key, &tree, &type); -+ if (err) -+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path); -+ -+ if (key.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0) -+ return grub_error(GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", path); -+ -+ data->fs_tree = tree; -+ return GRUB_ERR_NONE; -+} -+ - static grub_err_t - btrfs_handle_subvol(struct grub_btrfs_data *data __attribute__ ((unused))) - { - if (btrfs_default_subvol) -- return lookup_root_by_name(data, btrfs_default_subvol); -+ { -+ grub_err_t err; -+ err = lookup_root_by_name(data, btrfs_default_subvol); -+ -+ /* Fallback to old schemes */ -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ { -+ err = GRUB_ERR_NONE; -+ return lookup_root_by_name_fallback(data, btrfs_default_subvol); -+ } -+ return err; -+ } - - if (btrfs_default_subvolid) - return lookup_root_by_id(data, btrfs_default_subvolid); diff --git a/SOURCES/0063-Work-around-some-minor-include-path-weirdnesses.patch b/SOURCES/0063-Work-around-some-minor-include-path-weirdnesses.patch new file mode 100644 index 0000000..c7ae8d0 --- /dev/null +++ b/SOURCES/0063-Work-around-some-minor-include-path-weirdnesses.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 16 Mar 2018 13:28:57 -0400 +Subject: [PATCH] Work around some minor include path weirdnesses + +Signed-off-by: Peter Jones +--- + include/grub/arm/efi/console.h | 24 ++++++++++++++++++++++++ + include/grub/arm64/efi/console.h | 24 ++++++++++++++++++++++++ + include/grub/i386/efi/console.h | 24 ++++++++++++++++++++++++ + include/grub/x86_64/efi/console.h | 24 ++++++++++++++++++++++++ + 4 files changed, 96 insertions(+) + create mode 100644 include/grub/arm/efi/console.h + create mode 100644 include/grub/arm64/efi/console.h + create mode 100644 include/grub/i386/efi/console.h + create mode 100644 include/grub/x86_64/efi/console.h + +diff --git a/include/grub/arm/efi/console.h b/include/grub/arm/efi/console.h +new file mode 100644 +index 0000000000..1592f6f76b +--- /dev/null ++++ b/include/grub/arm/efi/console.h +@@ -0,0 +1,24 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_ARM_EFI_CONSOLE_H ++#define GRUB_ARM_EFI_CONSOLE_H ++ ++#include ++ ++#endif /* ! GRUB_ARM_EFI_CONSOLE_H */ +diff --git a/include/grub/arm64/efi/console.h b/include/grub/arm64/efi/console.h +new file mode 100644 +index 0000000000..9568933938 +--- /dev/null ++++ b/include/grub/arm64/efi/console.h +@@ -0,0 +1,24 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_ARM64_EFI_CONSOLE_H ++#define GRUB_ARM64_EFI_CONSOLE_H ++ ++#include ++ ++#endif /* ! GRUB_ARM64_EFI_CONSOLE_H */ +diff --git a/include/grub/i386/efi/console.h b/include/grub/i386/efi/console.h +new file mode 100644 +index 0000000000..9231375cb0 +--- /dev/null ++++ b/include/grub/i386/efi/console.h +@@ -0,0 +1,24 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_I386_EFI_CONSOLE_H ++#define GRUB_I386_EFI_CONSOLE_H ++ ++#include ++ ++#endif /* ! GRUB_I386_EFI_CONSOLE_H */ +diff --git a/include/grub/x86_64/efi/console.h b/include/grub/x86_64/efi/console.h +new file mode 100644 +index 0000000000..dba9d8678d +--- /dev/null ++++ b/include/grub/x86_64/efi/console.h +@@ -0,0 +1,24 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_X86_64_EFI_CONSOLE_H ++#define GRUB_X86_64_EFI_CONSOLE_H ++ ++#include ++ ++#endif /* ! GRUB_X86_64_EFI_CONSOLE_H */ diff --git a/SOURCES/0064-Grub-not-working-correctly-with-btrfs-snapshots-bsc-.patch b/SOURCES/0064-Grub-not-working-correctly-with-btrfs-snapshots-bsc-.patch deleted file mode 100644 index d4e20cd..0000000 --- a/SOURCES/0064-Grub-not-working-correctly-with-btrfs-snapshots-bsc-.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Thu, 11 May 2017 08:56:57 +0000 -Subject: [PATCH] Grub not working correctly with btrfs snapshots (bsc#1026511) - ---- - grub-core/fs/btrfs.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 238 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 673ded03522..2b21cbaa67e 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -2887,6 +2887,238 @@ out: - return 0; - } - -+static grub_err_t -+grub_btrfs_get_parent_subvol_path (struct grub_btrfs_data *data, -+ grub_uint64_t child_id, -+ const char *child_path, -+ grub_uint64_t *parent_id, -+ char **path_out) -+{ -+ grub_uint64_t fs_root = 0; -+ struct grub_btrfs_key key_in = { -+ .object_id = child_id, -+ .type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF, -+ .offset = 0, -+ }, key_out; -+ struct grub_btrfs_root_ref *ref; -+ char *buf; -+ struct grub_btrfs_leaf_descriptor desc; -+ grub_size_t elemsize; -+ grub_disk_addr_t elemaddr; -+ grub_err_t err; -+ char *parent_path; -+ -+ *parent_id = 0; -+ *path_out = 0; -+ -+ err = lower_bound(data, &key_in, &key_out, data->sblock.root_tree, -+ &elemaddr, &elemsize, &desc, 0); -+ if (err) -+ return err; -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF || elemaddr == 0) -+ next(data, &desc, &elemaddr, &elemsize, &key_out); -+ -+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF) -+ { -+ free_iterator(&desc); -+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("can't find root backrefs")); -+ } -+ -+ buf = grub_malloc(elemsize + 1); -+ if (!buf) -+ { -+ free_iterator(&desc); -+ return grub_errno; -+ } -+ -+ err = grub_btrfs_read_logical(data, elemaddr, buf, elemsize, 0); -+ if (err) -+ { -+ grub_free(buf); -+ free_iterator(&desc); -+ return err; -+ } -+ -+ buf[elemsize] = 0; -+ ref = (struct grub_btrfs_root_ref *)buf; -+ -+ err = get_fs_root(data, data->sblock.root_tree, grub_le_to_cpu64 (key_out.offset), -+ 0, &fs_root); -+ if (err) -+ { -+ grub_free(buf); -+ free_iterator(&desc); -+ return err; -+ } -+ -+ find_pathname(data, grub_le_to_cpu64 (ref->dirid), fs_root, ref->name, &parent_path); -+ -+ if (child_path) -+ { -+ *path_out = grub_xasprintf ("%s/%s", parent_path, child_path); -+ grub_free (parent_path); -+ } -+ else -+ *path_out = parent_path; -+ -+ *parent_id = grub_le_to_cpu64 (key_out.offset); -+ -+ grub_free(buf); -+ free_iterator(&desc); -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_btrfs_get_default_subvolume_id (struct grub_btrfs_data *data, grub_uint64_t *id) -+{ -+ grub_err_t err; -+ grub_disk_addr_t elemaddr; -+ grub_size_t elemsize; -+ struct grub_btrfs_key key, key_out; -+ struct grub_btrfs_dir_item *direl = NULL; -+ const char *ctoken = "default"; -+ grub_size_t ctokenlen = sizeof ("default") - 1; -+ -+ *id = 0; -+ key.object_id = data->sblock.root_dir_objectid; -+ key.type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; -+ key.offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen)); -+ err = lower_bound (data, &key, &key_out, data->sblock.root_tree, &elemaddr, &elemsize, -+ NULL, 0); -+ if (err) -+ return err; -+ -+ if (key_cmp (&key, &key_out) != 0) -+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); -+ -+ struct grub_btrfs_dir_item *cdirel; -+ direl = grub_malloc (elemsize + 1); -+ err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize, 0); -+ if (err) -+ { -+ grub_free (direl); -+ return err; -+ } -+ for (cdirel = direl; -+ (grub_uint8_t *) cdirel - (grub_uint8_t *) direl -+ < (grub_ssize_t) elemsize; -+ cdirel = (void *) ((grub_uint8_t *) (direl + 1) -+ + grub_le_to_cpu16 (cdirel->n) -+ + grub_le_to_cpu16 (cdirel->m))) -+ { -+ if (ctokenlen == grub_le_to_cpu16 (cdirel->n) -+ && grub_memcmp (cdirel->name, ctoken, ctokenlen) == 0) -+ break; -+ } -+ if ((grub_uint8_t *) cdirel - (grub_uint8_t *) direl -+ >= (grub_ssize_t) elemsize) -+ { -+ grub_free (direl); -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); -+ return err; -+ } -+ -+ if (cdirel->key.type != GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM) -+ { -+ grub_free (direl); -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); -+ return err; -+ } -+ -+ *id = grub_le_to_cpu64 (cdirel->key.object_id); -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_btrfs_get_default_subvol (struct grub_extcmd_context *ctxt, -+ int argc, char **argv) -+{ -+ char *devname; -+ grub_device_t dev; -+ struct grub_btrfs_data *data; -+ grub_err_t err; -+ grub_uint64_t id; -+ char *subvol = NULL; -+ grub_uint64_t subvolid = 0; -+ char *varname = NULL; -+ char *output = NULL; -+ int path_only = ctxt->state[1].set; -+ int num_only = ctxt->state[2].set; -+ -+ if (ctxt->state[0].set) -+ varname = ctxt->state[0].arg; -+ -+ if (argc < 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); -+ -+ devname = grub_file_get_device_name(argv[0]); -+ if (!devname) -+ return grub_errno; -+ -+ dev = grub_device_open (devname); -+ grub_free (devname); -+ if (!dev) -+ return grub_errno; -+ -+ data = grub_btrfs_mount(dev); -+ if (!data) -+ { -+ grub_device_close (dev); -+ grub_dprintf ("btrfs", "failed to open fs\n"); -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ -+ err = grub_btrfs_get_default_subvolume_id (data, &subvolid); -+ if (err) -+ { -+ grub_btrfs_unmount (data); -+ grub_device_close (dev); -+ return err; -+ } -+ -+ id = subvolid; -+ while (id != GRUB_BTRFS_ROOT_VOL_OBJECTID) -+ { -+ grub_uint64_t parent_id; -+ char *path_out; -+ -+ err = grub_btrfs_get_parent_subvol_path (data, grub_cpu_to_le64 (id), subvol, &parent_id, &path_out); -+ if (err) -+ { -+ grub_btrfs_unmount (data); -+ grub_device_close (dev); -+ return err; -+ } -+ -+ if (subvol) -+ grub_free (subvol); -+ subvol = path_out; -+ id = parent_id; -+ } -+ -+ if (num_only && path_only) -+ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T" /%s", subvolid, subvol); -+ else if (num_only) -+ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T, subvolid); -+ else -+ output = grub_xasprintf ("/%s", subvol); -+ -+ if (varname) -+ grub_env_set(varname, output); -+ else -+ grub_printf ("%s\n", output); -+ -+ grub_free (output); -+ grub_free (subvol); -+ -+ grub_btrfs_unmount (data); -+ grub_device_close (dev); -+ -+ return GRUB_ERR_NONE; -+} -+ - static struct grub_fs grub_btrfs_fs = { - .name = "btrfs", - .fs_dir = grub_btrfs_dir, -@@ -2905,6 +3137,7 @@ static struct grub_fs grub_btrfs_fs = { - static grub_command_t cmd_info; - static grub_command_t cmd_mount_subvol; - static grub_extcmd_t cmd_list_subvols; -+static grub_extcmd_t cmd_get_default_subvol; - - static char * - subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)), -@@ -2975,6 +3208,11 @@ GRUB_MOD_INIT (btrfs) - "[-p|-n] [-o var] DEVICE", - "Print list of BtrFS subvolumes on " - "DEVICE.", options); -+ cmd_get_default_subvol = grub_register_extcmd("btrfs-get-default-subvol", -+ grub_cmd_btrfs_get_default_subvol, 0, -+ "[-p|-n] [-o var] DEVICE", -+ "Print default BtrFS subvolume on " -+ "DEVICE.", options); - grub_register_variable_hook ("btrfs_subvol", subvol_get_env, - subvol_set_env); - grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env, diff --git a/SOURCES/0064-Make-it-possible-to-enabled-build-id-sha1.patch b/SOURCES/0064-Make-it-possible-to-enabled-build-id-sha1.patch new file mode 100644 index 0000000..99d8055 --- /dev/null +++ b/SOURCES/0064-Make-it-possible-to-enabled-build-id-sha1.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 25 Jun 2015 15:41:06 -0400 +Subject: [PATCH] Make it possible to enabled --build-id=sha1 + +Signed-off-by: Peter Jones +--- + configure.ac | 8 ++++++++ + acinclude.m4 | 19 +++++++++++++++++++ + 2 files changed, 27 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 0d0e6782a1..302300711f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1442,7 +1442,15 @@ grub_PROG_TARGET_CC + if test "x$TARGET_APPLE_LINKER" != x1 ; then + grub_PROG_OBJCOPY_ABSOLUTE + fi ++ ++AC_ARG_ENABLE([build-id], ++ [AS_HELP_STRING([--enable-build-id], ++ [ask the linker to supply build-id notes (default=no)])]) ++if test x$enable_build_id = xyes; then ++grub_PROG_LD_BUILD_ID_SHA1 ++else + grub_PROG_LD_BUILD_ID_NONE ++fi + if test "x$target_cpu" = xi386; then + if test "$platform" != emu && test "x$TARGET_APPLE_LINKER" != x1 ; then + if test ! -z "$TARGET_IMG_LDSCRIPT"; then +diff --git a/acinclude.m4 b/acinclude.m4 +index 6e14bb553c..21238fcfd0 100644 +--- a/acinclude.m4 ++++ b/acinclude.m4 +@@ -136,6 +136,25 @@ if test "x$grub_cv_prog_ld_build_id_none" = xyes; then + fi + ]) + ++dnl Supply --build-id=sha1 to ld if building modules. ++dnl This suppresses warnings from ld on some systems ++AC_DEFUN([grub_PROG_LD_BUILD_ID_SHA1], ++[AC_MSG_CHECKING([whether linker accepts --build-id=sha1]) ++AC_CACHE_VAL(grub_cv_prog_ld_build_id_sha1, ++[save_LDFLAGS="$LDFLAGS" ++LDFLAGS="$LDFLAGS -Wl,--build-id=sha1" ++AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], ++ [grub_cv_prog_ld_build_id_sha1=yes], ++ [grub_cv_prog_ld_build_id_sha1=no]) ++LDFLAGS="$save_LDFLAGS" ++]) ++AC_MSG_RESULT([$grub_cv_prog_ld_build_id_sha1]) ++ ++if test "x$grub_cv_prog_ld_build_id_sha1" = xyes; then ++ TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,--build-id=sha1" ++fi ++]) ++ + dnl Check nm + AC_DEFUN([grub_PROG_NM_WORKS], + [AC_MSG_CHECKING([whether nm works]) diff --git a/SOURCES/0065-Add-grub_efi_allocate_pool-and-grub_efi_free_pool-wr.patch b/SOURCES/0065-Add-grub_efi_allocate_pool-and-grub_efi_free_pool-wr.patch deleted file mode 100644 index bde7096..0000000 --- a/SOURCES/0065-Add-grub_efi_allocate_pool-and-grub_efi_free_pool-wr.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 1 Jun 2017 09:59:56 -0400 -Subject: [PATCH] Add grub_efi_allocate_pool() and grub_efi_free_pool() - wrappers. - -Signed-off-by: Peter Jones ---- - include/grub/efi/efi.h | 36 ++++++++++++++++++++++++++++++++---- - 1 file changed, 32 insertions(+), 4 deletions(-) - -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 585fa6662b6..03f9a9d0118 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -24,6 +24,10 @@ - #include - #include - -+/* Variables. */ -+extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); -+extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); -+ - /* Functions. */ - void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol, - void *registration); -@@ -60,6 +64,33 @@ EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, - grub_efi_uintn_t *descriptor_size, - grub_efi_uint32_t *descriptor_version); - void grub_efi_memory_fini (void); -+ -+static inline grub_efi_status_t -+__attribute__((__unused__)) -+grub_efi_allocate_pool (grub_efi_memory_type_t pool_type, -+ grub_efi_uintn_t buffer_size, -+ void **buffer) -+{ -+ grub_efi_boot_services_t *b; -+ grub_efi_status_t status; -+ -+ b = grub_efi_system_table->boot_services; -+ status = efi_call_3 (b->allocate_pool, pool_type, buffer_size, buffer); -+ return status; -+} -+ -+static inline grub_efi_status_t -+__attribute__((__unused__)) -+grub_efi_free_pool (void *buffer) -+{ -+ grub_efi_boot_services_t *b; -+ grub_efi_status_t status; -+ -+ b = grub_efi_system_table->boot_services; -+ status = efi_call_1 (b->free_pool, buffer); -+ return status; -+} -+ - grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (grub_efi_handle_t image_handle); - void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp); - char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); -@@ -115,10 +146,7 @@ void grub_efi_init (void); - void grub_efi_fini (void); - void grub_efi_set_prefix (void); - --/* Variables. */ --extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); --extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); -- -+/* More variables. */ - extern int EXPORT_VAR(grub_efi_is_finished); - - struct grub_net_card; diff --git a/SOURCES/0065-Add-grub_qdprintf-grub_dprintf-without-the-file-line.patch b/SOURCES/0065-Add-grub_qdprintf-grub_dprintf-without-the-file-line.patch new file mode 100644 index 0000000..7658e9b --- /dev/null +++ b/SOURCES/0065-Add-grub_qdprintf-grub_dprintf-without-the-file-line.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 28 Jun 2015 13:09:58 -0400 +Subject: [PATCH] Add grub_qdprintf() - grub_dprintf() without the file+line + number. + +This just makes copy+paste of our debug loading info easier. + +Signed-off-by: Peter Jones +--- + grub-core/kern/misc.c | 18 ++++++++++++++++++ + include/grub/misc.h | 2 ++ + 2 files changed, 20 insertions(+) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index a432a6be54..9a2fae6398 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -191,6 +191,24 @@ grub_real_dprintf (const char *file, const int line, const char *condition, + } + } + ++void ++grub_qdprintf (const char *condition, const char *fmt, ...) ++{ ++ va_list args; ++ const char *debug = grub_env_get ("debug"); ++ ++ if (! debug) ++ return; ++ ++ if (grub_strword (debug, "all") || grub_strword (debug, condition)) ++ { ++ va_start (args, fmt); ++ grub_vprintf (fmt, args); ++ va_end (args); ++ grub_refresh (); ++ } ++} ++ + #define PREALLOC_SIZE 255 + + int +diff --git a/include/grub/misc.h b/include/grub/misc.h +index fd18e6320b..3adc4036e3 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -345,6 +345,8 @@ void EXPORT_FUNC(grub_real_dprintf) (const char *file, + const int line, + const char *condition, + const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 4, 5))); ++void EXPORT_FUNC(grub_qdprintf) (const char *condition, ++ const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 2, 3))); + int EXPORT_FUNC(grub_vprintf) (const char *fmt, va_list args); + int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...) + __attribute__ ((format (GNU_PRINTF, 3, 4))); diff --git a/SOURCES/0066-Make-a-gdb-dprintf-that-tells-us-load-addresses.patch b/SOURCES/0066-Make-a-gdb-dprintf-that-tells-us-load-addresses.patch new file mode 100644 index 0000000..ccf34a5 --- /dev/null +++ b/SOURCES/0066-Make-a-gdb-dprintf-that-tells-us-load-addresses.patch @@ -0,0 +1,178 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 25 Jun 2015 15:11:36 -0400 +Subject: [PATCH] Make a "gdb" dprintf that tells us load addresses. + +This makes a grub_dprintf() call during platform init and during module +loading that tells us the virtual addresses of the .text and .data +sections of grub-core/kernel.exec and any modules it loads. + +Specifically, it displays them in the gdb "add-symbol-file" syntax, with +the presumption that there's a variable $grubdir that reflects the path +to any such binaries. + +Signed-off-by: Peter Jones +--- + grub-core/kern/dl.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ + grub-core/kern/efi/efi.c | 4 ++-- + grub-core/kern/efi/init.c | 26 +++++++++++++++++++++++- + include/grub/efi/efi.h | 2 +- + 4 files changed, 78 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 88d2077709..9557254035 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -501,6 +501,23 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name) + return s; + return NULL; + } ++static long ++grub_dl_find_section_index (Elf_Ehdr *e, const char *name) ++{ ++ Elf_Shdr *s; ++ const char *str; ++ unsigned i; ++ ++ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); ++ str = (char *) e + s->sh_offset; ++ ++ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); ++ i < e->e_shnum; ++ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) ++ if (grub_strcmp (str + s->sh_name, name) == 0) ++ return (long)i; ++ return -1; ++} + + /* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. +@@ -653,6 +670,37 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) + + return GRUB_ERR_NONE; + } ++static void ++grub_dl_print_gdb_info (grub_dl_t mod, Elf_Ehdr *e) ++{ ++ void *text, *data = NULL; ++ long idx; ++ ++ idx = grub_dl_find_section_index (e, ".text"); ++ if (idx < 0) ++ return; ++ ++ text = grub_dl_get_section_addr (mod, idx); ++ if (!text) ++ return; ++ ++ idx = grub_dl_find_section_index (e, ".data"); ++ if (idx >= 0) ++ data = grub_dl_get_section_addr (mod, idx); ++ ++ if (data) ++ grub_qdprintf ("gdb", "add-symbol-file \\\n" ++ "/usr/lib/debug/usr/lib/grub/%s-%s/%s.debug " ++ "\\\n %p -s .data %p\n", ++ GRUB_TARGET_CPU, GRUB_PLATFORM, ++ mod->name, text, data); ++ else ++ grub_qdprintf ("gdb", "add-symbol-file \\\n" ++ "/usr/lib/debug/usr/lib/grub/%s-%s/%s.debug " ++ "\\\n%p\n", ++ GRUB_TARGET_CPU, GRUB_PLATFORM, ++ mod->name, text); ++} + + /* Load a module from core memory. */ + grub_dl_t +@@ -712,6 +760,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + grub_dprintf ("modules", "module name: %s\n", mod->name); + grub_dprintf ("modules", "init function: %p\n", mod->init); + ++ grub_dl_print_gdb_info (mod, e); ++ + if (grub_dl_add (mod)) + { + grub_dl_unload (mod); +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index ae9885edb8..d6a2fb5778 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -296,7 +296,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, + /* Search the mods section from the PE32/PE32+ image. This code uses + a PE32 header, but should work with PE32+ as well. */ + grub_addr_t +-grub_efi_modules_addr (void) ++grub_efi_section_addr (const char *section_name) + { + grub_efi_loaded_image_t *image; + struct grub_pe32_header *header; +@@ -321,7 +321,7 @@ grub_efi_modules_addr (void) + i < coff_header->num_sections; + i++, section++) + { +- if (grub_strcmp (section->name, "mods") == 0) ++ if (grub_strcmp (section->name, section_name) == 0) + break; + } + +diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c +index 6d39bd3ad2..2d12e6188f 100644 +--- a/grub-core/kern/efi/init.c ++++ b/grub-core/kern/efi/init.c +@@ -115,10 +115,33 @@ grub_efi_env_init (void) + grub_free (envblk_s.buf); + } + ++static void ++grub_efi_print_gdb_info (void) ++{ ++ grub_addr_t text; ++ grub_addr_t data; ++ ++ text = grub_efi_section_addr (".text"); ++ if (!text) ++ return; ++ ++ data = grub_efi_section_addr (".data"); ++ if (data) ++ grub_qdprintf ("gdb", ++ "add-symbol-file /usr/lib/debug/usr/lib/grub/%s-%s/" ++ "kernel.exec %p -s .data %p\n", ++ GRUB_TARGET_CPU, GRUB_PLATFORM, (void *)text, (void *)data); ++ else ++ grub_qdprintf ("gdb", ++ "add-symbol-file /usr/lib/debug/usr/lib/grub/%s-%s/" ++ "kernel.exec %p\n", ++ GRUB_TARGET_CPU, GRUB_PLATFORM, (void *)text); ++} ++ + void + grub_efi_init (void) + { +- grub_modbase = grub_efi_modules_addr (); ++ grub_modbase = grub_efi_section_addr ("mods"); + /* First of all, initialize the console so that GRUB can display + messages. */ + grub_console_init (); +@@ -142,6 +165,7 @@ grub_efi_init (void) + 0, 0, 0, NULL); + + grub_efi_env_init (); ++ grub_efi_print_gdb_info (); + grub_efidisk_init (); + } + +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 03f9a9d011..2e0691454b 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -138,7 +138,7 @@ grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); + grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args); + #endif + +-grub_addr_t grub_efi_modules_addr (void); ++grub_addr_t grub_efi_section_addr (const char *section); + + void grub_efi_mm_init (void); + void grub_efi_mm_fini (void); diff --git a/SOURCES/0066-Use-grub_efi_.-memory-helpers-where-reasonable.patch b/SOURCES/0066-Use-grub_efi_.-memory-helpers-where-reasonable.patch deleted file mode 100644 index 4fa92c0..0000000 --- a/SOURCES/0066-Use-grub_efi_.-memory-helpers-where-reasonable.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 1 Jun 2017 10:06:38 -0400 -Subject: [PATCH] Use grub_efi_...() memory helpers where reasonable. - -This uses grub_efi_allocate_pool(), grub_efi_free_pool(), and -grub_efi_free_pages() instead of open-coded efi_call_N() calls, so we -get more reasonable type checking. - -Signed-off-by: Peter Jones ---- - grub-core/loader/efi/chainloader.c | 24 +++++++++--------------- - 1 file changed, 9 insertions(+), 15 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 3ff305b1d32..ba3d2930197 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -65,7 +65,7 @@ grub_chainloader_unload (void) - - b = grub_efi_system_table->boot_services; - efi_call_1 (b->unload_image, image_handle); -- efi_call_2 (b->free_pages, address, pages); -+ grub_efi_free_pages (address, pages); - - grub_free (file_path); - grub_free (cmdline); -@@ -108,7 +108,7 @@ grub_chainloader_boot (void) - } - - if (exit_data) -- efi_call_1 (b->free_pool, exit_data); -+ grub_efi_free_pool (exit_data); - - grub_loader_unset (); - -@@ -523,10 +523,9 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp) - static grub_efi_boolean_t - handle_image (void *data, grub_efi_uint32_t datasize) - { -- grub_efi_boot_services_t *b; - grub_efi_loaded_image_t *li, li_bak; - grub_efi_status_t efi_status; -- char *buffer = NULL; -+ void *buffer = NULL; - char *buffer_aligned = NULL; - grub_efi_uint32_t i; - struct grub_pe32_section_table *section; -@@ -537,8 +536,6 @@ handle_image (void *data, grub_efi_uint32_t datasize) - int found_entry_point = 0; - int rc; - -- b = grub_efi_system_table->boot_services; -- - rc = read_header (data, datasize, &context); - if (rc < 0) - { -@@ -578,8 +575,8 @@ handle_image (void *data, grub_efi_uint32_t datasize) - grub_dprintf ("chain", "image size is %08"PRIxGRUB_UINT64_T", datasize is %08x\n", - context.image_size, datasize); - -- efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, -- buffer_size, &buffer); -+ efi_status = grub_efi_allocate_pool (GRUB_EFI_LOADER_DATA, buffer_size, -+ &buffer); - - if (efi_status != GRUB_EFI_SUCCESS) - { -@@ -811,14 +808,14 @@ handle_image (void *data, grub_efi_uint32_t datasize) - - grub_dprintf ("chain", "entry_point returned %ld\n", efi_status); - grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); -- efi_status = efi_call_1 (b->free_pool, buffer); -+ efi_status = grub_efi_free_pool (buffer); - - return 1; - - error_exit: - grub_dprintf ("chain", "error_exit: grub_errno: %d\n", grub_errno); - if (buffer) -- efi_call_1 (b->free_pool, buffer); -+ grub_efi_free_pool (buffer); - - return 0; - } -@@ -826,10 +823,7 @@ error_exit: - static grub_err_t - grub_secureboot_chainloader_unload (void) - { -- grub_efi_boot_services_t *b; -- -- b = grub_efi_system_table->boot_services; -- efi_call_2 (b->free_pages, address, pages); -+ grub_efi_free_pages (address, pages); - grub_free (file_path); - grub_free (cmdline); - cmdline = 0; -@@ -1096,7 +1090,7 @@ fail: - grub_free (file_path); - - if (address) -- efi_call_2 (b->free_pages, address, pages); -+ grub_efi_free_pages (address, pages); - - if (cmdline) - grub_free (cmdline); diff --git a/SOURCES/0067-Add-PRIxGRUB_EFI_STATUS-and-use-it.patch b/SOURCES/0067-Add-PRIxGRUB_EFI_STATUS-and-use-it.patch deleted file mode 100644 index 1a96b43..0000000 --- a/SOURCES/0067-Add-PRIxGRUB_EFI_STATUS-and-use-it.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 1 Jun 2017 10:07:50 -0400 -Subject: [PATCH] Add PRIxGRUB_EFI_STATUS and use it. - -This avoids syntax checkers getting confused about if it's llx or lx. - -Signed-off-by: Peter Jones ---- - grub-core/loader/efi/chainloader.c | 3 ++- - include/grub/efi/api.h | 9 +++++++++ - 2 files changed, 11 insertions(+), 1 deletion(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index ba3d2930197..47f5aa14817 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -806,7 +806,8 @@ handle_image (void *data, grub_efi_uint32_t datasize) - efi_status = efi_call_2 (entry_point, grub_efi_image_handle, - grub_efi_system_table); - -- grub_dprintf ("chain", "entry_point returned %ld\n", efi_status); -+ grub_dprintf ("chain", "entry_point returned 0x%"PRIxGRUB_EFI_STATUS"\n", -+ efi_status); - grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); - efi_status = grub_efi_free_pool (buffer); - -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 117469450d3..99628801478 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -546,7 +546,16 @@ typedef grub_uint64_t grub_efi_uint64_t; - typedef grub_uint8_t grub_efi_char8_t; - typedef grub_uint16_t grub_efi_char16_t; - -+ - typedef grub_efi_uintn_t grub_efi_status_t; -+/* Make grub_efi_status_t reasonably printable. */ -+#if GRUB_CPU_SIZEOF_VOID_P == 8 -+#define PRIxGRUB_EFI_STATUS "lx" -+#define PRIdGRUB_EFI_STATUS "ld" -+#else -+#define PRIxGRUB_EFI_STATUS "llx" -+#define PRIdGRUB_EFI_STATUS "lld" -+#endif - - #define GRUB_EFI_ERROR_CODE(value) \ - ((((grub_efi_status_t) 1) << (sizeof (grub_efi_status_t) * 8 - 1)) | (value)) diff --git a/SOURCES/0067-Fixup-for-newer-compiler.patch b/SOURCES/0067-Fixup-for-newer-compiler.patch new file mode 100644 index 0000000..ed23271 --- /dev/null +++ b/SOURCES/0067-Fixup-for-newer-compiler.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 10 May 2018 13:40:19 -0400 +Subject: [PATCH] Fixup for newer compiler + +--- + grub-core/fs/btrfs.c | 2 +- + include/grub/gpt_partition.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 2b21cbaa67..4cc86e9b79 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -218,7 +218,7 @@ struct grub_btrfs_inode + grub_uint64_t size; + grub_uint8_t dummy2[0x70]; + struct grub_btrfs_time mtime; +-} GRUB_PACKED; ++} GRUB_PACKED __attribute__ ((aligned(8))); + + struct grub_btrfs_extent_data + { +diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h +index 7a93f43291..8212697bf6 100644 +--- a/include/grub/gpt_partition.h ++++ b/include/grub/gpt_partition.h +@@ -76,7 +76,7 @@ struct grub_gpt_partentry + grub_uint64_t end; + grub_uint64_t attrib; + char name[72]; +-} GRUB_PACKED; ++} GRUB_PACKED __attribute__ ((aligned(8))); + + grub_err_t + grub_gpt_partition_map_iterate (grub_disk_t disk, diff --git a/SOURCES/0068-Don-t-attempt-to-export-the-start-and-_start-symbols.patch b/SOURCES/0068-Don-t-attempt-to-export-the-start-and-_start-symbols.patch new file mode 100644 index 0000000..9b78c00 --- /dev/null +++ b/SOURCES/0068-Don-t-attempt-to-export-the-start-and-_start-symbols.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Sat, 12 May 2018 11:29:07 +0200 +Subject: [PATCH] Don't attempt to export the start and _start symbols for + grub-emu + +Commit 318ee04aadc ("make better backtraces") reworked the backtrace logic +but the changes lead to the following build error on the grub-emu platform: + +grub_emu_lite-symlist.o:(.data+0xf08): undefined reference to `start' +collect2: error: ld returned 1 exit status +make[3]: *** [Makefile:25959: grub-emu-lite] Error 1 +make[3]: *** Waiting for unfinished jobs.... +cat kernel_syms.input | grep -v '^#' | sed -n \ + -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/defined kernel '""'\1/;p;}' \ + -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined kernel '""'\1/;p;}' \ + | sort -u >kernel_syms.lst + +The problem is that start and _start symbols are exported unconditionally, +but these aren't defined for grub-emu since is an emultaed platform so it +doesn't have a startup logic. Don't attempt to export those for grub-emu. + +Signed-off-by: Javier Martinez Canillas +--- + include/grub/kernel.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/grub/kernel.h b/include/grub/kernel.h +index 300a9766cd..55849777ea 100644 +--- a/include/grub/kernel.h ++++ b/include/grub/kernel.h +@@ -111,8 +111,10 @@ grub_addr_t grub_modules_get_end (void); + + #endif + ++#if !defined(GRUB_MACHINE_EMU) + void EXPORT_FUNC(start) (void); + void EXPORT_FUNC(_start) (void); ++#endif + + /* The start point of the C code. */ + void grub_main (void) __attribute__ ((noreturn)); diff --git a/SOURCES/0068-don-t-use-int-for-efi-status.patch b/SOURCES/0068-don-t-use-int-for-efi-status.patch deleted file mode 100644 index 44d3555..0000000 --- a/SOURCES/0068-don-t-use-int-for-efi-status.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 26 Jun 2017 12:44:59 -0400 -Subject: [PATCH] don't use int for efi status - ---- - grub-core/kern/efi/efi.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index 05d8237a9b2..ae9885edb84 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -167,7 +167,7 @@ grub_reboot (void) - void - grub_exit (int retval) - { -- int rc = GRUB_EFI_LOAD_ERROR; -+ grub_efi_status_t rc = GRUB_EFI_LOAD_ERROR; - - if (retval == 0) - rc = GRUB_EFI_SUCCESS; diff --git a/SOURCES/0069-Fixup-for-newer-compiler.patch b/SOURCES/0069-Fixup-for-newer-compiler.patch new file mode 100644 index 0000000..167dca1 --- /dev/null +++ b/SOURCES/0069-Fixup-for-newer-compiler.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 10 May 2018 13:40:19 -0400 +Subject: [PATCH] Fixup for newer compiler + +--- + conf/Makefile.common | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 191b1a70c6..5f0ef96985 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -38,7 +38,7 @@ CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) + CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 + CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) +-STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx ++STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -R .note.gnu.property -R .gnu.build.attributes + + CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d diff --git a/SOURCES/0069-make-GRUB_MOD_INIT-declare-its-function-prototypes.patch b/SOURCES/0069-make-GRUB_MOD_INIT-declare-its-function-prototypes.patch deleted file mode 100644 index 1014900..0000000 --- a/SOURCES/0069-make-GRUB_MOD_INIT-declare-its-function-prototypes.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 26 Jun 2017 12:46:23 -0400 -Subject: [PATCH] make GRUB_MOD_INIT() declare its function prototypes. - ---- - include/grub/dl.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/include/grub/dl.h b/include/grub/dl.h -index b3753c9ca26..91933b85f2c 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -54,6 +54,7 @@ grub_mod_fini (void) - - #define GRUB_MOD_INIT(name) \ - static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \ -+extern void grub_##name##_init (void); \ - void \ - grub_##name##_init (void) { grub_mod_init (0); } \ - static void \ -@@ -61,6 +62,7 @@ grub_mod_init (grub_dl_t mod __attribute__ ((unused))) - - #define GRUB_MOD_FINI(name) \ - static void grub_mod_fini (void) __attribute__ ((used)); \ -+extern void grub_##name##_fini (void); \ - void \ - grub_##name##_fini (void) { grub_mod_fini (); } \ - static void \ diff --git a/SOURCES/0070-Add-support-for-non-Ethernet-network-cards.patch b/SOURCES/0070-Add-support-for-non-Ethernet-network-cards.patch new file mode 100644 index 0000000..fb44628 --- /dev/null +++ b/SOURCES/0070-Add-support-for-non-Ethernet-network-cards.patch @@ -0,0 +1,766 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrzej Kacprowski +Date: Wed, 10 Jul 2019 15:22:29 +0200 +Subject: [PATCH] Add support for non-Ethernet network cards + +This patch replaces fixed 6-byte link layer address with +up to 32-byte variable sized address. +This allows supporting Infiniband and Omni-Path fabric +which use 20-byte address, but other network card types +can also take advantage of this change. +The network card driver is responsible for replacing L2 +header provided by grub2 if needed. +This approach is compatible with UEFI network stack which +also allows up to 32-byte variable size link address. + +The BOOTP/DHCP packet format is limited to 16 byte client +hardware address, if link address is more that 16-bytes +then chaddr field in BOOTP it will be set to 0 as per rfc4390. + +Resolves: rhbz#1370642 + +Signed-off-by: Andrzej Kacprowski +[msalter: Fix max string calculation in grub_net_hwaddr_to_str] +Signed-off-by: Mark Salter +--- + grub-core/net/arp.c | 155 ++++++++++++++++++++++----------- + grub-core/net/bootp.c | 15 ++-- + grub-core/net/drivers/efi/efinet.c | 8 +- + grub-core/net/drivers/emu/emunet.c | 1 + + grub-core/net/drivers/i386/pc/pxe.c | 13 +-- + grub-core/net/drivers/ieee1275/ofnet.c | 2 + + grub-core/net/drivers/uboot/ubootnet.c | 1 + + grub-core/net/ethernet.c | 88 +++++++++---------- + grub-core/net/icmp6.c | 15 ++-- + grub-core/net/ip.c | 4 +- + grub-core/net/net.c | 50 ++++++----- + include/grub/net.h | 19 ++-- + 12 files changed, 219 insertions(+), 152 deletions(-) + +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index 54306e3b16..67b409a8ac 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -31,22 +31,12 @@ enum + ARP_REPLY = 2 + }; + +-enum +- { +- /* IANA ARP constant to define hardware type as ethernet. */ +- GRUB_NET_ARPHRD_ETHERNET = 1 +- }; +- +-struct arppkt { ++struct arphdr { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; +- grub_uint8_t sender_mac[6]; +- grub_uint32_t sender_ip; +- grub_uint8_t recv_mac[6]; +- grub_uint32_t recv_ip; + } GRUB_PACKED; + + static int have_pending; +@@ -57,12 +47,16 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) + { + struct grub_net_buff nb; +- struct arppkt *arp_packet; ++ struct arphdr *arp_header; + grub_net_link_level_address_t target_mac_addr; + grub_err_t err; + int i; + grub_uint8_t *nbd; + grub_uint8_t arp_data[128]; ++ grub_uint8_t hln; ++ grub_uint8_t pln; ++ grub_uint8_t arp_packet_len; ++ grub_uint8_t *tmp_ptr; + + if (proto_addr->type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + return grub_error (GRUB_ERR_BUG, "unsupported address family"); +@@ -73,23 +67,39 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + grub_netbuff_clear (&nb); + grub_netbuff_reserve (&nb, 128); + +- err = grub_netbuff_push (&nb, sizeof (*arp_packet)); ++ hln = inf->card->default_address.len; ++ pln = sizeof (proto_addr->ipv4); ++ arp_packet_len = sizeof (*arp_header) + 2 * (hln + pln); ++ ++ err = grub_netbuff_push (&nb, arp_packet_len); + if (err) + return err; + +- arp_packet = (struct arppkt *) nb.data; +- arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); +- arp_packet->hln = 6; +- arp_packet->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); +- arp_packet->pln = 4; +- arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); +- /* Sender hardware address. */ +- grub_memcpy (arp_packet->sender_mac, &inf->hwaddress.mac, 6); +- arp_packet->sender_ip = inf->address.ipv4; +- grub_memset (arp_packet->recv_mac, 0, 6); +- arp_packet->recv_ip = proto_addr->ipv4; +- /* Target protocol address */ +- grub_memset (&target_mac_addr.mac, 0xff, 6); ++ arp_header = (struct arphdr *) nb.data; ++ arp_header->hrd = grub_cpu_to_be16 (inf->card->default_address.type); ++ arp_header->hln = hln; ++ arp_header->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); ++ arp_header->pln = pln; ++ arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); ++ tmp_ptr = nb.data + sizeof (*arp_header); ++ ++ /* The source hardware address. */ ++ grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln); ++ tmp_ptr += hln; ++ ++ /* The source protocol address. */ ++ grub_memcpy (tmp_ptr, &inf->address.ipv4, pln); ++ tmp_ptr += pln; ++ ++ /* The target hardware address. */ ++ grub_memset (tmp_ptr, 0, hln); ++ tmp_ptr += hln; ++ ++ /* The target protocol address */ ++ grub_memcpy (tmp_ptr, &proto_addr->ipv4, pln); ++ tmp_ptr += pln; ++ ++ grub_memset (&target_mac_addr.mac, 0xff, hln); + + nbd = nb.data; + send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP); +@@ -114,28 +124,53 @@ grub_err_t + grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card, + grub_uint16_t *vlantag) + { +- struct arppkt *arp_packet = (struct arppkt *) nb->data; ++ struct arphdr *arp_header = (struct arphdr *) nb->data; + grub_net_network_level_address_t sender_addr, target_addr; + grub_net_link_level_address_t sender_mac_addr; + struct grub_net_network_level_interface *inf; ++ grub_uint16_t hw_type; ++ grub_uint8_t hln; ++ grub_uint8_t pln; ++ grub_uint8_t arp_packet_len; ++ grub_uint8_t *tmp_ptr; + +- if (arp_packet->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) +- || arp_packet->pln != 4 || arp_packet->hln != 6 +- || nb->tail - nb->data < (int) sizeof (*arp_packet)) ++ hw_type = card->default_address.type; ++ hln = card->default_address.len; ++ pln = sizeof(sender_addr.ipv4); ++ arp_packet_len = sizeof (*arp_header) + 2 * (pln + hln); ++ ++ if (arp_header->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) ++ || arp_header->hrd != grub_cpu_to_be16 (hw_type) ++ || arp_header->hln != hln || arp_header->pln != pln ++ || nb->tail - nb->data < (int) arp_packet_len) { + return GRUB_ERR_NONE; ++ } + ++ tmp_ptr = nb->data + sizeof (*arp_header); ++ ++ /* The source hardware address. */ ++ sender_mac_addr.type = hw_type; ++ sender_mac_addr.len = hln; ++ grub_memcpy (sender_mac_addr.mac, tmp_ptr, hln); ++ tmp_ptr += hln; ++ ++ /* The source protocol address. */ + sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; ++ grub_memcpy(&sender_addr.ipv4, tmp_ptr, pln); ++ tmp_ptr += pln; ++ ++ grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); ++ ++ /* The target hardware address. */ ++ tmp_ptr += hln; ++ ++ /* The target protocol address. */ + target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; +- sender_addr.ipv4 = arp_packet->sender_ip; +- target_addr.ipv4 = arp_packet->recv_ip; +- if (arp_packet->sender_ip == pending_req) ++ grub_memcpy(&target_addr.ipv4, tmp_ptr, pln); ++ ++ if (sender_addr.ipv4 == pending_req) + have_pending = 1; + +- sender_mac_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (sender_mac_addr.mac, arp_packet->sender_mac, +- sizeof (sender_mac_addr.mac)); +- grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); +- + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + /* Verify vlantag id */ +@@ -148,11 +183,11 @@ grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card, + + /* Am I the protocol address target? */ + if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 +- && arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) ++ && arp_header->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) + { + grub_net_link_level_address_t target; + struct grub_net_buff nb_reply; +- struct arppkt *arp_reply; ++ struct arphdr *arp_reply; + grub_uint8_t arp_data[128]; + grub_err_t err; + +@@ -161,25 +196,39 @@ grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card, + grub_netbuff_clear (&nb_reply); + grub_netbuff_reserve (&nb_reply, 128); + +- err = grub_netbuff_push (&nb_reply, sizeof (*arp_packet)); ++ err = grub_netbuff_push (&nb_reply, arp_packet_len); + if (err) + return err; + +- arp_reply = (struct arppkt *) nb_reply.data; ++ arp_reply = (struct arphdr *) nb_reply.data; + +- arp_reply->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); ++ arp_reply->hrd = grub_cpu_to_be16 (hw_type); + arp_reply->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); +- arp_reply->pln = 4; +- arp_reply->hln = 6; ++ arp_reply->pln = pln; ++ arp_reply->hln = hln; + arp_reply->op = grub_cpu_to_be16_compile_time (ARP_REPLY); +- arp_reply->sender_ip = arp_packet->recv_ip; +- arp_reply->recv_ip = arp_packet->sender_ip; +- arp_reply->hln = 6; +- +- target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (target.mac, arp_packet->sender_mac, 6); +- grub_memcpy (arp_reply->sender_mac, inf->hwaddress.mac, 6); +- grub_memcpy (arp_reply->recv_mac, arp_packet->sender_mac, 6); ++ ++ tmp_ptr = nb_reply.data + sizeof (*arp_reply); ++ ++ /* The source hardware address. */ ++ grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln); ++ tmp_ptr += hln; ++ ++ /* The source protocol address. */ ++ grub_memcpy (tmp_ptr, &target_addr.ipv4, pln); ++ tmp_ptr += pln; ++ ++ /* The target hardware address. */ ++ grub_memcpy (tmp_ptr, sender_mac_addr.mac, hln); ++ tmp_ptr += hln; ++ ++ /* The target protocol address */ ++ grub_memcpy (tmp_ptr, &sender_addr.ipv4, pln); ++ tmp_ptr += pln; ++ ++ target.type = hw_type; ++ target.len = hln; ++ grub_memcpy (target.mac, sender_mac_addr.mac, hln); + + /* Change operation to REPLY and send packet */ + send_ethernet_packet (inf, &nb_reply, target, GRUB_NET_ETHERTYPE_ARP); +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index e28fb6a09f..08b6b2b5d6 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -233,7 +233,6 @@ grub_net_configure_by_dhcp_ack (const char *name, + int is_def, char **device, char **path) + { + grub_net_network_level_address_t addr; +- grub_net_link_level_address_t hwaddr; + struct grub_net_network_level_interface *inter; + int mask = -1; + char server_ip[sizeof ("xxx.xxx.xxx.xxx")]; +@@ -250,12 +249,8 @@ grub_net_configure_by_dhcp_ack (const char *name, + if (path) + *path = 0; + +- grub_memcpy (hwaddr.mac, bp->mac_addr, +- bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len +- : sizeof (hwaddr.mac)); +- hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- +- inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); ++ grub_dprintf("dhcp", "configuring dhcp for %s\n", name); ++ inter = grub_net_add_addr (name, card, &addr, &card->default_address, flags); + if (!inter) + return 0; + +@@ -567,7 +562,9 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) + grub_memset (pack, 0, sizeof (*pack)); + pack->opcode = 1; + pack->hw_type = 1; +- pack->hw_len = 6; ++ pack->hw_len = iface->hwaddress.len > 16 ? 0 ++ : iface->hwaddress.len; ++ + err = grub_get_datetime (&date); + if (err || !grub_datetime2unixtime (&date, &t)) + { +@@ -580,7 +577,7 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) + else + pack->ident = iface->xid; + +- grub_memcpy (&pack->mac_addr, &iface->hwaddress.mac, 6); ++ grub_memcpy (&pack->mac_addr, &iface->hwaddress.mac, pack->hw_len); + + grub_netbuff_push (nb, sizeof (*udph)); + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 173fb63153..a673bea807 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -279,6 +279,9 @@ grub_efinet_findcards (void) + /* This should not happen... Why? */ + continue; + ++ if (net->mode->hwaddr_size > GRUB_NET_MAX_LINK_ADDRESS_SIZE) ++ continue; ++ + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED + && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) + continue; +@@ -315,10 +318,11 @@ grub_efinet_findcards (void) + card->name = grub_xasprintf ("efinet%d", i++); + card->driver = &efidriver; + card->flags = 0; +- card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ card->default_address.type = net->mode->if_type; ++ card->default_address.len = net->mode->hwaddr_size; + grub_memcpy (card->default_address.mac, + net->mode->current_address, +- sizeof (card->default_address.mac)); ++ net->mode->hwaddr_size); + card->efi_net = net; + card->efi_handle = *handle; + +diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c +index b194920861..5b6c5e16a6 100644 +--- a/grub-core/net/drivers/emu/emunet.c ++++ b/grub-core/net/drivers/emu/emunet.c +@@ -46,6 +46,7 @@ static struct grub_net_card emucard = + .mtu = 1500, + .default_address = { + .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, ++ . len = 6, + {.mac = {0, 1, 2, 3, 4, 5}} + }, + .flags = 0 +diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c +index 3f4152d036..9f8fb4b6d2 100644 +--- a/grub-core/net/drivers/i386/pc/pxe.c ++++ b/grub-core/net/drivers/i386/pc/pxe.c +@@ -386,20 +386,21 @@ GRUB_MOD_INIT(pxe) + grub_memset (ui, 0, sizeof (*ui)); + grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry); + ++ grub_pxe_card.default_address.len = 6; + grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr, +- sizeof (grub_pxe_card.default_address.mac)); +- for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) ++ grub_pxe_card.default_address.len); ++ for (i = 0; i < grub_pxe_card.default_address.len; i++) + if (grub_pxe_card.default_address.mac[i] != 0) + break; +- if (i != sizeof (grub_pxe_card.default_address.mac)) ++ if (i != grub_pxe_card.default_address.len) + { +- for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) ++ for (i = 0; i < grub_pxe_card.default_address.len; i++) + if (grub_pxe_card.default_address.mac[i] != 0xff) + break; + } +- if (i == sizeof (grub_pxe_card.default_address.mac)) ++ if (i == grub_pxe_card.default_address.len) + grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr, +- sizeof (grub_pxe_card.default_address.mac)); ++ grub_pxe_card.default_address.len); + grub_pxe_card.mtu = ui->mtu; + + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c +index 3860b6f78d..bcb3f9ea02 100644 +--- a/grub-core/net/drivers/ieee1275/ofnet.c ++++ b/grub-core/net/drivers/ieee1275/ofnet.c +@@ -160,6 +160,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath, + grub_uint16_t vlantag = 0; + + hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ hw_addr.len = 6; + + args = bootpath + grub_strlen (devpath) + 1; + do +@@ -503,6 +504,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias) + grub_memcpy (&lla.mac, pprop, 6); + + lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ lla.len = 6; + card->default_address = lla; + + card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; +diff --git a/grub-core/net/drivers/uboot/ubootnet.c b/grub-core/net/drivers/uboot/ubootnet.c +index 056052e40d..22ebcbf211 100644 +--- a/grub-core/net/drivers/uboot/ubootnet.c ++++ b/grub-core/net/drivers/uboot/ubootnet.c +@@ -131,6 +131,7 @@ GRUB_MOD_INIT (ubootnet) + + grub_memcpy (&(card->default_address.mac), &devinfo->di_net.hwaddr, 6); + card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ card->default_address.len = 6; + + card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; + card->txbuf = grub_zalloc (card->txbufsize); +diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c +index 4d7ceed6f9..9aae83a5eb 100644 +--- a/grub-core/net/ethernet.c ++++ b/grub-core/net/ethernet.c +@@ -29,13 +29,6 @@ + + #define LLCADDRMASK 0x7f + +-struct etherhdr +-{ +- grub_uint8_t dst[6]; +- grub_uint8_t src[6]; +- grub_uint16_t type; +-} GRUB_PACKED; +- + struct llchdr + { + grub_uint8_t dsap; +@@ -55,13 +48,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + grub_net_link_level_address_t target_addr, + grub_net_ethertype_t ethertype) + { +- struct etherhdr *eth; ++ grub_uint8_t *eth; + grub_err_t err; +- grub_uint8_t etherhdr_size; +- grub_uint16_t vlantag_id = VLANTAG_IDENTIFIER; ++ grub_uint32_t vlantag = 0; ++ grub_uint8_t hw_addr_len = inf->card->default_address.len; ++ grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2; + +- etherhdr_size = sizeof (*eth); +- COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE); ++ /* Source and destination link addresses + ethertype + vlan tag */ ++ COMPILE_TIME_ASSERT ((GRUB_NET_MAX_LINK_ADDRESS_SIZE * 2 + 2 + 4) < ++ GRUB_NET_MAX_LINK_HEADER_SIZE); + + /* Increase ethernet header in case of vlantag */ + if (inf->vlantag != 0) +@@ -70,11 +65,22 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + err = grub_netbuff_push (nb, etherhdr_size); + if (err) + return err; +- eth = (struct etherhdr *) nb->data; +- grub_memcpy (eth->dst, target_addr.mac, 6); +- grub_memcpy (eth->src, inf->hwaddress.mac, 6); ++ eth = nb->data; ++ grub_memcpy (eth, target_addr.mac, hw_addr_len); ++ eth += hw_addr_len; ++ grub_memcpy (eth, inf->hwaddress.mac, hw_addr_len); ++ eth += hw_addr_len; ++ ++ /* Check if a vlan-tag is present. */ ++ if (vlantag != 0) ++ { ++ *((grub_uint32_t *)eth) = grub_cpu_to_be32 (vlantag); ++ eth += sizeof (vlantag); ++ } ++ ++ /* Write ethertype */ ++ *((grub_uint16_t*) eth) = grub_cpu_to_be16 (ethertype); + +- eth->type = grub_cpu_to_be16 (ethertype); + if (!inf->card->opened) + { + err = GRUB_ERR_NONE; +@@ -85,18 +91,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + inf->card->opened = 1; + } + +- /* Check and add a vlan-tag if needed. */ +- if (inf->vlantag != 0) +- { +- /* Move eth type to the right */ +- grub_memcpy ((char *) nb->data + etherhdr_size - 2, +- (char *) nb->data + etherhdr_size - 6, 2); +- +- /* Add the tag in the middle */ +- grub_memcpy ((char *) nb->data + etherhdr_size - 6, &vlantag_id, 2); +- grub_memcpy ((char *) nb->data + etherhdr_size - 4, (char *) &(inf->vlantag), 2); +- } +- + return inf->card->driver->send (inf->card, nb); + } + +@@ -104,31 +98,40 @@ grub_err_t + grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + struct grub_net_card *card) + { +- struct etherhdr *eth; ++ grub_uint8_t *eth; + struct llchdr *llch; + struct snaphdr *snaph; + grub_net_ethertype_t type; + grub_net_link_level_address_t hwaddress; + grub_net_link_level_address_t src_hwaddress; + grub_err_t err; +- grub_uint8_t etherhdr_size = sizeof (*eth); ++ grub_uint8_t hw_addr_len = card->default_address.len; ++ grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2; + grub_uint16_t vlantag = 0; + ++ eth = nb->data; + +- /* Check if a vlan-tag is present. If so, the ethernet header is 4 bytes */ +- /* longer than the original one. The vlantag id is extracted and the header */ +- /* is reseted to the original size. */ +- if (grub_get_unaligned16 (nb->data + etherhdr_size - 2) == VLANTAG_IDENTIFIER) ++ hwaddress.type = card->default_address.type; ++ hwaddress.len = hw_addr_len; ++ grub_memcpy (hwaddress.mac, eth, hw_addr_len); ++ eth += hw_addr_len; ++ ++ src_hwaddress.type = card->default_address.type; ++ src_hwaddress.len = hw_addr_len; ++ grub_memcpy (src_hwaddress.mac, eth, hw_addr_len); ++ eth += hw_addr_len; ++ ++ type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); ++ if (type == VLANTAG_IDENTIFIER) + { +- vlantag = grub_get_unaligned16 (nb->data + etherhdr_size); ++ /* Skip vlan tag */ ++ eth += 2; ++ vlantag = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); + etherhdr_size += 4; +- /* Move eth type to the original position */ +- grub_memcpy((char *) nb->data + etherhdr_size - 6, +- (char *) nb->data + etherhdr_size - 2, 2); ++ eth += 2; ++ type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); + } + +- eth = (struct etherhdr *) nb->data; +- type = grub_be_to_cpu16 (eth->type); + err = grub_netbuff_pull (nb, etherhdr_size); + if (err) + return err; +@@ -148,11 +151,6 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + } + } + +- hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); +- src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac)); +- + switch (type) + { + /* ARP packet. */ +diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c +index 2cbd95dce2..56a3ec5c8e 100644 +--- a/grub-core/net/icmp6.c ++++ b/grub-core/net/icmp6.c +@@ -231,8 +231,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; +- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); ++ ll_address.type = card->default_address.type; ++ ll_address.len = card->default_address.len; ++ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } +@@ -335,8 +336,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; +- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); ++ ll_address.type = card->default_address.type; ++ ll_address.len = card->default_address.len; ++ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } +@@ -384,8 +386,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; +- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); ++ ll_address.type = card->default_address.type; ++ ll_address.len = card->default_address.len; ++ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + if (ohdr->type == OPTION_PREFIX && ohdr->len == 4) +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index ea5edf8f1f..a5896f6dc2 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -276,8 +276,8 @@ handle_dgram (struct grub_net_buff *nb, + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV + && inf->hwaddress.type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET +- && grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr, +- sizeof (inf->hwaddress.mac)) == 0) ++ && (grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr, ++ bootp->hw_len) == 0 || bootp->hw_len == 0)) + { + grub_net_process_dhcp (nb, inf); + grub_netbuff_free (nb); +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 22f2689aae..a46f82362e 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -133,8 +133,9 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + << 48) + && proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1)))) + { +- hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memset (hw_addr->mac, -1, 6); ++ hw_addr->type = inf->card->default_address.type; ++ hw_addr->len = inf->card->default_address.len; ++ grub_memset (hw_addr->mac, -1, hw_addr->len); + return GRUB_ERR_NONE; + } + +@@ -142,6 +143,7 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + && ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff)) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ hw_addr->len = inf->card->default_address.len; + hw_addr->mac[0] = 0x33; + hw_addr->mac[1] = 0x33; + hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff); +@@ -762,23 +764,23 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) + void + grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) + { +- str[0] = 0; +- switch (addr->type) ++ char *ptr; ++ unsigned i; ++ int maxstr; ++ ++ if (addr->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE) + { +- case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: +- { +- char *ptr; +- unsigned i; +- for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++) +- { +- grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str), +- "%02x:", addr->mac[i] & 0xff); +- ptr += (sizeof ("XX:") - 1); +- } +- return; +- } ++ str[0] = 0; ++ grub_printf (_("Unsupported hw address type %d len %d\n"), ++ addr->type, addr->len); ++ return; ++ } ++ maxstr = addr->len * grub_strlen ("XX:"); ++ for (ptr = str, i = 0; i < addr->len; i++) ++ { ++ ptr += grub_snprintf (ptr, maxstr - (ptr - str), ++ "%02x:", addr->mac[i] & 0xff); + } +- grub_printf (_("Unsupported hw address type %d\n"), addr->type); + } + + int +@@ -789,13 +791,17 @@ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + return -1; + if (a->type > b->type) + return +1; +- switch (a->type) ++ if (a->len < b->len) ++ return -1; ++ if (a->len > b->len) ++ return +1; ++ if (a->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE) + { +- case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: +- return grub_memcmp (a->mac, b->mac, sizeof (a->mac)); ++ grub_printf (_("Unsupported hw address type %d len %d\n"), ++ a->type, a->len); ++ return + 1; + } +- grub_printf (_("Unsupported hw address type %d\n"), a->type); +- return 1; ++ return grub_memcmp (a->mac, b->mac, a->len); + } + + int +diff --git a/include/grub/net.h b/include/grub/net.h +index 8a05ec4fe7..af0404db7e 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -29,7 +29,8 @@ + + enum + { +- GRUB_NET_MAX_LINK_HEADER_SIZE = 64, ++ GRUB_NET_MAX_LINK_HEADER_SIZE = 96, ++ GRUB_NET_MAX_LINK_ADDRESS_SIZE = 32, + GRUB_NET_UDP_HEADER_SIZE = 8, + GRUB_NET_TCP_HEADER_SIZE = 20, + GRUB_NET_OUR_IPV4_HEADER_SIZE = 20, +@@ -42,15 +43,17 @@ enum + + typedef enum grub_link_level_protocol_id + { +- GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET ++ /* IANA ARP constant to define hardware type. */ ++ GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET = 1, + } grub_link_level_protocol_id_t; + + typedef struct grub_net_link_level_address + { + grub_link_level_protocol_id_t type; ++ grub_uint8_t len; + union + { +- grub_uint8_t mac[6]; ++ grub_uint8_t mac[GRUB_NET_MAX_LINK_ADDRESS_SIZE]; + }; + } grub_net_link_level_address_t; + +@@ -566,11 +569,13 @@ grub_net_addr_cmp (const grub_net_network_level_address_t *a, + #define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX") + + /* +- Currently suppoerted adresses: +- ethernet: XX:XX:XX:XX:XX:XX ++ Up to 32 byte hardware address supported, see GRUB_NET_MAX_LINK_ADDRESS_SIZE + */ +- +-#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) ++#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof (\ ++ "XX:XX:XX:XX:XX:XX:XX:XX:"\ ++ "XX:XX:XX:XX:XX:XX:XX:XX:"\ ++ "XX:XX:XX:XX:XX:XX:XX:XX:"\ ++ "XX:XX:XX:XX:XX:XX:XX:XX")) + + void + grub_net_addr_to_str (const grub_net_network_level_address_t *target, diff --git a/SOURCES/0070-Don-t-guess-boot-efi-as-HFS-on-ppc-machines-in-grub-.patch b/SOURCES/0070-Don-t-guess-boot-efi-as-HFS-on-ppc-machines-in-grub-.patch deleted file mode 100644 index 890aa34..0000000 --- a/SOURCES/0070-Don-t-guess-boot-efi-as-HFS-on-ppc-machines-in-grub-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 20 Apr 2017 13:29:06 -0400 -Subject: [PATCH] Don't guess /boot/efi/ as HFS+ on ppc machines in - grub-install - -This should never be trying this, and since we've consolidated the -grubenv to always be on /boot/efi/EFI/fedora/, this code causes it to -always make the wrong decision. - -Resolves: rhbz#1484474 - -Signed-off-by: Peter Jones ---- - util/grub-install.c | 12 +----------- - 1 file changed, 1 insertion(+), 11 deletions(-) - -diff --git a/util/grub-install.c b/util/grub-install.c -index 84ed6e88ecb..a2bec7446cb 100644 ---- a/util/grub-install.c -+++ b/util/grub-install.c -@@ -1190,18 +1190,8 @@ main (int argc, char *argv[]) - char *d; - - is_guess = 1; -- d = grub_util_path_concat (2, bootdir, "macppc"); -- if (!grub_util_is_directory (d)) -- { -- free (d); -- d = grub_util_path_concat (2, bootdir, "efi"); -- } - /* Find the Mac HFS(+) System Partition. */ -- if (!grub_util_is_directory (d)) -- { -- free (d); -- d = grub_util_path_concat (2, bootdir, "EFI"); -- } -+ d = grub_util_path_concat (2, bootdir, "macppc"); - if (!grub_util_is_directory (d)) - { - free (d); diff --git a/SOURCES/0071-20_linux_xen-load-xen-or-multiboot-2-modules-as-need.patch b/SOURCES/0071-20_linux_xen-load-xen-or-multiboot-2-modules-as-need.patch deleted file mode 100644 index 3fd779f..0000000 --- a/SOURCES/0071-20_linux_xen-load-xen-or-multiboot-2-modules-as-need.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 9 Jul 2019 14:31:19 +0200 -Subject: [PATCH] 20_linux_xen: load xen or multiboot{,2} modules as needed. - -Signed-off-by: Peter Jones ---- - util/grub.d/20_linux_xen.in | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in -index e9e73b815fb..c23b064be6c 100644 ---- a/util/grub.d/20_linux_xen.in -+++ b/util/grub.d/20_linux_xen.in -@@ -153,6 +153,7 @@ linux_entry_xsm () - else - xen_rm_opts="no-real-mode edd=off" - fi -+ insmod ${xen_module} - ${xen_loader} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts} - echo '$(echo "$lmessage" | grub_quote)' - ${module_loader} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args} -@@ -166,6 +167,7 @@ EOF - done - sed "s/^/$submenu_indentation/" << EOF - echo '$(echo "$message" | grub_quote)' -+ insmod ${xen_module} - ${module_loader} --nounzip $(echo $initrd_path) - EOF - fi -@@ -253,13 +255,16 @@ while [ "x${xen_list}" != "x" ] ; do - echo " submenu '$(gettext_printf "Xen hypervisor, version %s" "${xen_version}" | grub_quote)' \$menuentry_id_option 'xen-hypervisor-$xen_version-$boot_device_id' {" - fi - if ($grub_file --is-arm64-efi $current_xen); then -+ xen_module="xen_boot" - xen_loader="xen_hypervisor" - module_loader="xen_module" - else - if ($grub_file --is-x86-multiboot2 $current_xen); then -+ xen_module="multiboot2" - xen_loader="multiboot2" - module_loader="module2" - else -+ xen_module="multiboot" - xen_loader="multiboot" - module_loader="module" - fi diff --git a/SOURCES/0071-net-read-bracketed-ipv6-addrs-and-port-numbers.patch b/SOURCES/0071-net-read-bracketed-ipv6-addrs-and-port-numbers.patch new file mode 100644 index 0000000..307e33c --- /dev/null +++ b/SOURCES/0071-net-read-bracketed-ipv6-addrs-and-port-numbers.patch @@ -0,0 +1,270 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aaron Miller +Date: Fri, 29 Jul 2016 17:41:38 +0800 +Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers + +Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses +to be recognized with brackets around them, which is required to specify a port +number + +Signed-off-by: Aaron Miller +[pjones: various bug fixes] +Signed-off-by: Peter Jones +--- + grub-core/net/http.c | 25 ++++++++++++--- + grub-core/net/net.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++--- + grub-core/net/tftp.c | 8 +++-- + include/grub/net.h | 1 + + 4 files changed, 109 insertions(+), 12 deletions(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index b616cf40b1..12a2632ea5 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -289,7 +289,9 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), + nb2 = grub_netbuff_alloc (data->chunk_rem); + if (!nb2) + return grub_errno; +- grub_netbuff_put (nb2, data->chunk_rem); ++ err = grub_netbuff_put (nb2, data->chunk_rem); ++ if (err) ++ return grub_errno; + grub_memcpy (nb2->data, nb->data, data->chunk_rem); + if (file->device->net->packs.count >= 20) + { +@@ -312,12 +314,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + int i; + struct grub_net_buff *nb; + grub_err_t err; ++ char* server = file->device->net->server; ++ int port = file->device->net->port; + + nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE + + sizeof ("GET ") - 1 + + grub_strlen (data->filename) + + sizeof (" HTTP/1.1\r\nHost: ") - 1 +- + grub_strlen (file->device->net->server) ++ + grub_strlen (server) + sizeof (":XXXXXXXXXX") + + sizeof ("\r\nUser-Agent: " PACKAGE_STRING + "\r\n") - 1 + + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX" +@@ -356,7 +360,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + sizeof (" HTTP/1.1\r\nHost: ") - 1); + + ptr = nb->tail; +- err = grub_netbuff_put (nb, grub_strlen (file->device->net->server)); ++ err = grub_netbuff_put (nb, grub_strlen (server)); + if (err) + { + grub_netbuff_free (nb); +@@ -365,6 +369,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + grub_memcpy (ptr, file->device->net->server, + grub_strlen (file->device->net->server)); + ++ if (port) ++ { ++ ptr = nb->tail; ++ grub_snprintf ((char *) ptr, ++ sizeof (":XXXXXXXXXX"), ++ ":%d", ++ port); ++ } ++ + ptr = nb->tail; + err = grub_netbuff_put (nb, + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") +@@ -390,8 +403,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + grub_netbuff_put (nb, 2); + grub_memcpy (ptr, "\r\n", 2); + +- data->sock = grub_net_tcp_open (file->device->net->server, +- HTTP_PORT, http_receive, ++ grub_dprintf ("http", "opening path %s on host %s TCP port %d\n", ++ data->filename, server, port ? port : HTTP_PORT); ++ data->sock = grub_net_tcp_open (server, ++ port ? port : HTTP_PORT, http_receive, + http_err, NULL, + file); + if (!data->sock) +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index a46f82362e..0ce5e675ed 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -444,6 +444,13 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) + grub_uint16_t newip[8]; + const char *ptr = val; + int word, quaddot = -1; ++ int bracketed = 0; ++ ++ if (ptr[0] == '[') ++ { ++ bracketed = 1; ++ ptr++; ++ } + + if (ptr[0] == ':' && ptr[1] != ':') + return 0; +@@ -482,6 +489,8 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) + grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); + } + grub_memcpy (ip, newip, 16); ++ if (bracketed && *ptr == ']') ++ ptr++; + if (rest) + *rest = ptr; + return 1; +@@ -1343,8 +1352,10 @@ grub_net_open_real (const char *name) + { + grub_net_app_level_t proto; + const char *protname, *server; ++ char *host; + grub_size_t protnamelen; + int try; ++ int port = 0; + + if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) + { +@@ -1382,6 +1393,72 @@ grub_net_open_real (const char *name) + return NULL; + } + ++ char* port_start; ++ /* ipv6 or port specified? */ ++ if ((port_start = grub_strchr (server, ':'))) ++ { ++ char* ipv6_begin; ++ if((ipv6_begin = grub_strchr (server, '['))) ++ { ++ char* ipv6_end = grub_strchr (server, ']'); ++ if(!ipv6_end) ++ { ++ grub_error (GRUB_ERR_NET_BAD_ADDRESS, ++ N_("mismatched [ in address")); ++ return NULL; ++ } ++ /* port number after bracketed ipv6 addr */ ++ if(ipv6_end[1] == ':') ++ { ++ port = grub_strtoul (ipv6_end + 2, NULL, 10); ++ if(port > 65535) ++ { ++ grub_error (GRUB_ERR_NET_BAD_ADDRESS, ++ N_("bad port number")); ++ return NULL; ++ } ++ } ++ host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1); ++ } ++ else ++ { ++ if (grub_strchr (port_start + 1, ':')) ++ { ++ int iplen = grub_strlen (server); ++ /* bracket bare ipv6 addrs */ ++ host = grub_malloc (iplen + 3); ++ if(!host) ++ { ++ return NULL; ++ } ++ host[0] = '['; ++ grub_memcpy (host + 1, server, iplen); ++ host[iplen + 1] = ']'; ++ host[iplen + 2] = '\0'; ++ } ++ else ++ { ++ /* hostname:port or ipv4:port */ ++ port = grub_strtol (port_start + 1, NULL, 10); ++ if(port > 65535) ++ { ++ grub_error (GRUB_ERR_NET_BAD_ADDRESS, ++ N_("bad port number")); ++ return NULL; ++ } ++ host = grub_strndup (server, port_start - server); ++ } ++ } ++ } ++ else ++ { ++ host = grub_strdup (server); ++ } ++ if (!host) ++ { ++ return NULL; ++ } ++ + for (try = 0; try < 2; try++) + { + FOR_NET_APP_LEVEL (proto) +@@ -1391,14 +1468,13 @@ grub_net_open_real (const char *name) + { + grub_net_t ret = grub_zalloc (sizeof (*ret)); + if (!ret) +- return NULL; +- ret->protocol = proto; +- ret->server = grub_strdup (server); +- if (!ret->server) + { +- grub_free (ret); ++ grub_free (host); + return NULL; + } ++ ret->protocol = proto; ++ ret->port = port; ++ ret->server = host; + ret->fs = &grub_net_fs; + return ret; + } +@@ -1473,6 +1549,7 @@ grub_net_open_real (const char *name) + grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), + name); + ++ grub_free (host); + return NULL; + } + +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 4ab2f5c735..d54b13f09f 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -295,6 +295,7 @@ tftp_open (struct grub_file *file, const char *filename) + grub_err_t err; + grub_uint8_t *nbd; + grub_net_network_level_address_t addr; ++ int port = file->device->net->port; + + data = grub_zalloc (sizeof (*data)); + if (!data) +@@ -362,14 +363,17 @@ tftp_open (struct grub_file *file, const char *filename) + err = grub_net_resolve_address (file->device->net->server, &addr); + if (err) + { +- grub_dprintf("tftp", "Address resolution failed: %d\n", err); ++ grub_dprintf ("tftp", "Address resolution failed: %d\n", err); ++ grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n", ++ (unsigned long long)data->file_size, ++ (unsigned long long)data->block_size); + grub_free (data); + return err; + } + + grub_dprintf("tftp", "opening connection\n"); + data->sock = grub_net_udp_open (addr, +- TFTP_SERVER_PORT, tftp_receive, ++ port ? port : TFTP_SERVER_PORT, tftp_receive, + file); + if (!data->sock) + { +diff --git a/include/grub/net.h b/include/grub/net.h +index af0404db7e..d55d505a03 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -273,6 +273,7 @@ typedef struct grub_net + { + char *server; + char *name; ++ int port; + grub_net_app_level_t protocol; + grub_net_packets_t packs; + grub_off_t offset; diff --git a/SOURCES/0072-Make-pmtimer-tsc-calibration-not-take-51-seconds-to-.patch b/SOURCES/0072-Make-pmtimer-tsc-calibration-not-take-51-seconds-to-.patch deleted file mode 100644 index acfb116..0000000 --- a/SOURCES/0072-Make-pmtimer-tsc-calibration-not-take-51-seconds-to-.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 7 Nov 2017 17:12:17 -0500 -Subject: [PATCH] Make pmtimer tsc calibration not take 51 seconds to fail. - -On my laptop running at 2.4GHz, if I run a VM where tsc calibration -using pmtimer will fail presuming a broken pmtimer, it takes ~51 seconds -to do so (as measured with the stopwatch on my phone), with a tsc delta -of 0x1cd1c85300, or around 125 billion cycles. - -If instead of trying to wait for 5-200ms to show up on the pmtimer, we try -to wait for 5-200us, it decides it's broken in ~0x2626aa0 TSCs, aka ~2.4 -million cycles, or more or less instantly. - -Additionally, this reading the pmtimer was returning 0xffffffff anyway, -and that's obviously an invalid return. I've added a check for that and -0 so we don't bother waiting for the test if what we're seeing is dead -pins with no response at all. - -If "debug" is includes "pmtimer", you will see one of the following -three outcomes. If pmtimer gives all 0 or all 1 bits, you will see: - -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 1 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 2 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 3 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 4 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 5 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 6 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 7 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 8 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 9 -kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 10 -kern/i386/tsc_pmtimer.c:78: timer is broken; giving up. - -This outcome was tested using qemu+kvm with UEFI (OVMF) firmware and -these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX - -If pmtimer gives any other bit patterns but is not actually marching -forward fast enough to use for clock calibration, you will see: - -kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations) -kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0 - -This outcome was tested using grub compiled with GRUB_PMTIMER_IGNORE_BAD_READS -defined (so as not to trip the bad read test) using qemu+kvm with UEFI -(OVMF) firmware, and these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX - -If pmtimer actually works, you'll see something like: - -kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations) -kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0 - -This outcome was tested using qemu+kvm with UEFI (OVMF) firmware, and -these options: -machine pc-i440fx-2.4 -cpu Broadwell-noTSX - -I've also tested this outcome on a real Intel Xeon E3-1275v3 on an Intel -Server Board S1200V3RPS using the SDV.RP.B8 "Release" build here: -https://firmware.intel.com/sites/default/files/UEFIDevKit_S1200RP_vB8.zip - -Signed-off-by: Peter Jones ---- - grub-core/kern/i386/tsc_pmtimer.c | 109 +++++++++++++++++++++++++++++++------- - 1 file changed, 89 insertions(+), 20 deletions(-) - -diff --git a/grub-core/kern/i386/tsc_pmtimer.c b/grub-core/kern/i386/tsc_pmtimer.c -index c9c36169978..ca15c3aacd7 100644 ---- a/grub-core/kern/i386/tsc_pmtimer.c -+++ b/grub-core/kern/i386/tsc_pmtimer.c -@@ -28,40 +28,101 @@ - #include - #include - -+/* -+ * Define GRUB_PMTIMER_IGNORE_BAD_READS if you're trying to test a timer that's -+ * present but doesn't keep time well. -+ */ -+// #define GRUB_PMTIMER_IGNORE_BAD_READS -+ - grub_uint64_t - grub_pmtimer_wait_count_tsc (grub_port_t pmtimer, - grub_uint16_t num_pm_ticks) - { - grub_uint32_t start; -- grub_uint32_t last; -- grub_uint32_t cur, end; -+ grub_uint64_t cur, end; - grub_uint64_t start_tsc; - grub_uint64_t end_tsc; -- int num_iter = 0; -+ unsigned int num_iter = 0; -+#ifndef GRUB_PMTIMER_IGNORE_BAD_READS -+ int bad_reads = 0; -+#endif - -- start = grub_inl (pmtimer) & 0xffffff; -- last = start; -+ /* -+ * Some timers are 24-bit and some are 32-bit, but it doesn't make much -+ * difference to us. Caring which one we have isn't really worth it since -+ * the low-order digits will give us enough data to calibrate TSC. So just -+ * mask the top-order byte off. -+ */ -+ cur = start = grub_inl (pmtimer) & 0xffffffUL; - end = start + num_pm_ticks; - start_tsc = grub_get_tsc (); - while (1) - { -- cur = grub_inl (pmtimer) & 0xffffff; -- if (cur < last) -- cur |= 0x1000000; -- num_iter++; -+ cur &= 0xffffffffff000000ULL; -+ cur |= grub_inl (pmtimer) & 0xffffffUL; -+ -+ end_tsc = grub_get_tsc(); -+ -+#ifndef GRUB_PMTIMER_IGNORE_BAD_READS -+ /* -+ * If we get 10 reads in a row that are obviously dead pins, there's no -+ * reason to do this thousands of times. -+ */ -+ if (cur == 0xffffffUL || cur == 0) -+ { -+ bad_reads++; -+ grub_dprintf ("pmtimer", -+ "pmtimer: 0x%"PRIxGRUB_UINT64_T" bad_reads: %d\n", -+ cur, bad_reads); -+ grub_dprintf ("pmtimer", "timer is broken; giving up.\n"); -+ -+ if (bad_reads == 10) -+ return 0; -+ } -+#endif -+ -+ if (cur < start) -+ cur += 0x1000000; -+ - if (cur >= end) - { -- end_tsc = grub_get_tsc (); -+ grub_dprintf ("pmtimer", "pmtimer delta is 0x%"PRIxGRUB_UINT64_T"\n", -+ cur - start); -+ grub_dprintf ("pmtimer", "tsc delta is 0x%"PRIxGRUB_UINT64_T"\n", -+ end_tsc - start_tsc); - return end_tsc - start_tsc; - } -- /* Check for broken PM timer. -- 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz) -- if after this time we still don't have 1 ms on pmtimer, then -- pmtimer is broken. -+ -+ /* -+ * Check for broken PM timer. 1ms at 10GHz should be 1E+7 TSCs; at -+ * 250MHz it should be 2.5E6. So if after 4E+7 TSCs on a 10GHz machine, -+ * we should have seen pmtimer show 4ms of change (i.e. cur =~ -+ * start+14320); on a 250MHz machine that should be 16ms (start+57280). -+ * If after this a time we still don't have 1ms on pmtimer, then pmtimer -+ * is broken. -+ * -+ * Likewise, if our code is perfectly efficient and introduces no delays -+ * whatsoever, on a 10GHz system we should see a TSC delta of 3580 in -+ * ~3580 iterations. On a 250MHz machine that should be ~900 iterations. -+ * -+ * With those factors in mind, there are two limits here. There's a hard -+ * limit here at 8x our desired pm timer delta, picked as an arbitrarily -+ * large value that's still not a lot of time to humans, because if we -+ * get that far this is either an implausibly fast machine or the pmtimer -+ * is not running. And there's another limit on 4x our 10GHz tsc delta -+ * without seeing cur converge on our target value. - */ -- if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) { -- return 0; -- } -+ if ((++num_iter > (grub_uint32_t)num_pm_ticks << 3UL) || -+ end_tsc - start_tsc > 40000000) -+ { -+ grub_dprintf ("pmtimer", -+ "pmtimer delta is 0x%"PRIxGRUB_UINT64_T" (%u iterations)\n", -+ cur - start, num_iter); -+ grub_dprintf ("pmtimer", -+ "tsc delta is implausible: 0x%"PRIxGRUB_UINT64_T"\n", -+ end_tsc - start_tsc); -+ return 0; -+ } - } - } - -@@ -74,12 +135,20 @@ grub_tsc_calibrate_from_pmtimer (void) - - fadt = grub_acpi_find_fadt (); - if (!fadt) -- return 0; -+ { -+ grub_dprintf ("pmtimer", "No FADT found; not using pmtimer.\n"); -+ return 0; -+ } - pmtimer = fadt->pmtimer; - if (!pmtimer) -- return 0; -+ { -+ grub_dprintf ("pmtimer", "FADT does not specify pmtimer; skipping.\n"); -+ return 0; -+ } - -- /* It's 3.579545 MHz clock. Wait 1 ms. */ -+ /* -+ * It's 3.579545 MHz clock. Wait 1 ms. -+ */ - tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580); - if (tsc_diff == 0) - return 0; diff --git a/SOURCES/0072-bootp-New-net_bootp6-command.patch b/SOURCES/0072-bootp-New-net_bootp6-command.patch new file mode 100644 index 0000000..bef3acd --- /dev/null +++ b/SOURCES/0072-bootp-New-net_bootp6-command.patch @@ -0,0 +1,1368 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 10 Jul 2019 15:42:36 +0200 +Subject: [PATCH] bootp: New net_bootp6 command + +Implement new net_bootp6 command for IPv6 network auto configuration via the +DHCPv6 protocol (RFC3315). + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +[pjones: Put back our code to add a local route] +Signed-off-by: Peter Jones +--- + grub-core/net/bootp.c | 1059 ++++++++++++++++++++++++++++++------ + grub-core/net/drivers/efi/efinet.c | 20 +- + grub-core/net/ip.c | 39 ++ + include/grub/efi/api.h | 2 +- + include/grub/net.h | 91 ++-- + 5 files changed, 1002 insertions(+), 209 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 08b6b2b5d6..fe93b80f1c 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -24,6 +24,98 @@ + #include + #include + #include ++#include ++#include ++ ++static int ++dissect_url (const char *url, char **proto, char **host, char **path) ++{ ++ const char *p, *ps; ++ grub_size_t l; ++ ++ *proto = *host = *path = NULL; ++ ps = p = url; ++ ++ while ((p = grub_strchr (p, ':'))) ++ { ++ if (grub_strlen (p) < sizeof ("://") - 1) ++ break; ++ if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0) ++ { ++ l = p - ps; ++ *proto = grub_malloc (l + 1); ++ if (!*proto) ++ { ++ grub_print_error (); ++ return 0; ++ } ++ ++ grub_memcpy (*proto, ps, l); ++ (*proto)[l] = '\0'; ++ p += sizeof ("://") - 1; ++ break; ++ } ++ ++p; ++ } ++ ++ if (!*proto) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url); ++ return 0; ++ } ++ ++ ps = p; ++ p = grub_strchr (p, '/'); ++ ++ if (!p) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ ++ l = p - ps; ++ ++ if (l > 2 && ps[0] == '[' && ps[l - 1] == ']') ++ { ++ *host = grub_malloc (l - 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps + 1, l - 2); ++ (*host)[l - 2] = 0; ++ } ++ else ++ { ++ *host = grub_malloc (l + 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps, l); ++ (*host)[l] = 0; ++ } ++ ++ *path = grub_strdup (p); ++ if (!*path) ++ { ++ grub_print_error (); ++ grub_free (*host); ++ grub_free (*proto); ++ *host = NULL; ++ *proto = NULL; ++ return 0; ++ } ++ return 1; ++} + + struct grub_dhcp_discover_options + { +@@ -604,6 +696,584 @@ out: + return err; + } + ++/* The default netbuff size for sending DHCPv6 packets which should be ++ large enough to hold the information */ ++#define GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE 512 ++ ++struct grub_dhcp6_options ++{ ++ grub_uint8_t *client_duid; ++ grub_uint16_t client_duid_len; ++ grub_uint8_t *server_duid; ++ grub_uint16_t server_duid_len; ++ grub_uint32_t iaid; ++ grub_uint32_t t1; ++ grub_uint32_t t2; ++ grub_net_network_level_address_t *ia_addr; ++ grub_uint32_t preferred_lifetime; ++ grub_uint32_t valid_lifetime; ++ grub_net_network_level_address_t *dns_server_addrs; ++ grub_uint16_t num_dns_server; ++ char *boot_file_proto; ++ char *boot_file_server_ip; ++ char *boot_file_path; ++}; ++ ++typedef struct grub_dhcp6_options *grub_dhcp6_options_t; ++ ++struct grub_dhcp6_session ++{ ++ struct grub_dhcp6_session *next; ++ struct grub_dhcp6_session **prev; ++ grub_uint32_t iaid; ++ grub_uint32_t transaction_id:24; ++ grub_uint64_t start_time; ++ struct grub_net_dhcp6_option_duid_ll duid; ++ struct grub_net_network_level_interface *iface; ++ ++ /* The associated dhcpv6 options */ ++ grub_dhcp6_options_t adv; ++ grub_dhcp6_options_t reply; ++}; ++ ++typedef struct grub_dhcp6_session *grub_dhcp6_session_t; ++ ++typedef void (*dhcp6_option_hook_fn) (const struct grub_net_dhcp6_option *opt, void *data); ++ ++static void ++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, ++ dhcp6_option_hook_fn hook, void *hook_data); ++ ++static void ++parse_dhcp6_iaaddr (const struct grub_net_dhcp6_option *opt, void *data) ++{ ++ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t )data; ++ ++ grub_uint16_t code = grub_be_to_cpu16 (opt->code); ++ grub_uint16_t len = grub_be_to_cpu16 (opt->len); ++ ++ if (code == GRUB_NET_DHCP6_OPTION_IAADDR) ++ { ++ const struct grub_net_dhcp6_option_iaaddr *iaaddr; ++ iaaddr = (const struct grub_net_dhcp6_option_iaaddr *)opt->data; ++ ++ if (len < sizeof (*iaaddr)) ++ { ++ grub_dprintf ("bootp", "DHCPv6: code %u with insufficient length %u\n", code, len); ++ return; ++ } ++ if (!dhcp6->ia_addr) ++ { ++ dhcp6->ia_addr = grub_malloc (sizeof(*dhcp6->ia_addr)); ++ dhcp6->ia_addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ dhcp6->ia_addr->ipv6[0] = grub_get_unaligned64 (iaaddr->addr); ++ dhcp6->ia_addr->ipv6[1] = grub_get_unaligned64 (iaaddr->addr + 8); ++ dhcp6->preferred_lifetime = grub_be_to_cpu32 (iaaddr->preferred_lifetime); ++ dhcp6->valid_lifetime = grub_be_to_cpu32 (iaaddr->valid_lifetime); ++ } ++ } ++} ++ ++static void ++parse_dhcp6_option (const struct grub_net_dhcp6_option *opt, void *data) ++{ ++ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t)data; ++ grub_uint16_t code = grub_be_to_cpu16 (opt->code); ++ grub_uint16_t len = grub_be_to_cpu16 (opt->len); ++ ++ switch (code) ++ { ++ case GRUB_NET_DHCP6_OPTION_CLIENTID: ++ ++ if (dhcp6->client_duid || !len) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 CLIENTID with length %u\n", len); ++ break; ++ } ++ dhcp6->client_duid = grub_malloc (len); ++ grub_memcpy (dhcp6->client_duid, opt->data, len); ++ dhcp6->client_duid_len = len; ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_SERVERID: ++ ++ if (dhcp6->server_duid || !len) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 SERVERID with length %u\n", len); ++ break; ++ } ++ dhcp6->server_duid = grub_malloc (len); ++ grub_memcpy (dhcp6->server_duid, opt->data, len); ++ dhcp6->server_duid_len = len; ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_IA_NA: ++ { ++ const struct grub_net_dhcp6_option_iana *ia_na; ++ grub_uint16_t data_len; ++ ++ if (dhcp6->iaid || len < sizeof (*ia_na)) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 IA_NA with length %u\n", len); ++ break; ++ } ++ ia_na = (const struct grub_net_dhcp6_option_iana *)opt->data; ++ dhcp6->iaid = grub_be_to_cpu32 (ia_na->iaid); ++ dhcp6->t1 = grub_be_to_cpu32 (ia_na->t1); ++ dhcp6->t2 = grub_be_to_cpu32 (ia_na->t2); ++ ++ data_len = len - sizeof (*ia_na); ++ if (data_len) ++ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)ia_na->data, data_len, parse_dhcp6_iaaddr, dhcp6); ++ } ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_DNS_SERVERS: ++ { ++ const grub_uint8_t *po; ++ grub_uint16_t ln; ++ grub_net_network_level_address_t *la; ++ ++ if (!len || len & 0xf) ++ { ++ grub_dprintf ("bootp", "Skip invalid length DHCPv6 DNS_SERVERS \n"); ++ break; ++ } ++ dhcp6->num_dns_server = ln = len >> 4; ++ dhcp6->dns_server_addrs = la = grub_zalloc (ln * sizeof (*la)); ++ ++ for (po = opt->data; ln > 0; po += 0x10, la++, ln--) ++ { ++ la->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ la->ipv6[0] = grub_get_unaligned64 (po); ++ la->ipv6[1] = grub_get_unaligned64 (po + 8); ++ la->option = DNS_OPTION_PREFER_IPV6; ++ } ++ } ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_BOOTFILE_URL: ++ dissect_url ((const char *)opt->data, ++ &dhcp6->boot_file_proto, ++ &dhcp6->boot_file_server_ip, ++ &dhcp6->boot_file_path); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void ++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, dhcp6_option_hook_fn hook, void *hook_data) ++{ ++ while (size) ++ { ++ grub_uint16_t code, len; ++ ++ if (size < sizeof (*opt)) ++ { ++ grub_dprintf ("bootp", "DHCPv6: Options stopped with remaining size %" PRIxGRUB_SIZE "\n", size); ++ break; ++ } ++ size -= sizeof (*opt); ++ len = grub_be_to_cpu16 (opt->len); ++ code = grub_be_to_cpu16 (opt->code); ++ if (size < len) ++ { ++ grub_dprintf ("bootp", "DHCPv6: Options stopped at out of bound length %u for option %u\n", len, code); ++ break; ++ } ++ if (!len) ++ { ++ grub_dprintf ("bootp", "DHCPv6: Options stopped at zero length option %u\n", code); ++ break; ++ } ++ else ++ { ++ if (hook) ++ hook (opt, hook_data); ++ size -= len; ++ opt = (const struct grub_net_dhcp6_option *)((grub_uint8_t *)opt + len + sizeof (*opt)); ++ } ++ } ++} ++ ++static grub_dhcp6_options_t ++grub_dhcp6_options_get (const struct grub_net_dhcp6_packet *v6h, ++ grub_size_t size) ++{ ++ grub_dhcp6_options_t options; ++ ++ if (size < sizeof (*v6h)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small")); ++ return NULL; ++ } ++ ++ options = grub_zalloc (sizeof(*options)); ++ if (!options) ++ return NULL; ++ ++ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)v6h->dhcp_options, ++ size - sizeof (*v6h), parse_dhcp6_option, options); ++ ++ return options; ++} ++ ++static void ++grub_dhcp6_options_free (grub_dhcp6_options_t options) ++{ ++ if (options->client_duid) ++ grub_free (options->client_duid); ++ if (options->server_duid) ++ grub_free (options->server_duid); ++ if (options->ia_addr) ++ grub_free (options->ia_addr); ++ if (options->dns_server_addrs) ++ grub_free (options->dns_server_addrs); ++ if (options->boot_file_proto) ++ grub_free (options->boot_file_proto); ++ if (options->boot_file_server_ip) ++ grub_free (options->boot_file_server_ip); ++ if (options->boot_file_path) ++ grub_free (options->boot_file_path); ++ ++ grub_free (options); ++} ++ ++static grub_dhcp6_session_t grub_dhcp6_sessions; ++#define FOR_DHCP6_SESSIONS_SAFE(var, next) FOR_LIST_ELEMENTS_SAFE (var, next, grub_dhcp6_sessions) ++#define FOR_DHCP6_SESSIONS(var) FOR_LIST_ELEMENTS (var, grub_dhcp6_sessions) ++ ++static void ++grub_net_configure_by_dhcp6_info (const char *name, ++ struct grub_net_card *card, ++ grub_dhcp6_options_t dhcp6, ++ int is_def, ++ int flags, ++ struct grub_net_network_level_interface **ret_inf) ++{ ++ grub_net_network_level_netaddress_t netaddr; ++ struct grub_net_network_level_interface *inf; ++ ++ if (dhcp6->ia_addr) ++ { ++ inf = grub_net_add_addr (name, card, dhcp6->ia_addr, &card->default_address, flags); ++ ++ netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ netaddr.ipv6.base[0] = dhcp6->ia_addr->ipv6[0]; ++ netaddr.ipv6.base[1] = 0; ++ netaddr.ipv6.masksize = 64; ++ grub_net_add_route (name, netaddr, inf); ++ ++ if (ret_inf) ++ *ret_inf = inf; ++ } ++ ++ if (dhcp6->dns_server_addrs) ++ { ++ grub_uint16_t i; ++ ++ for (i = 0; i < dhcp6->num_dns_server; ++i) ++ grub_net_add_dns_server (dhcp6->dns_server_addrs + i); ++ } ++ ++ if (dhcp6->boot_file_path) ++ grub_env_set_net_property (name, "boot_file", dhcp6->boot_file_path, ++ grub_strlen (dhcp6->boot_file_path)); ++ ++ if (is_def && dhcp6->boot_file_server_ip) ++ { ++ grub_net_default_server = grub_strdup (dhcp6->boot_file_server_ip); ++ grub_env_set ("net_default_interface", name); ++ grub_env_export ("net_default_interface"); ++ } ++} ++ ++static void ++grub_dhcp6_session_add (struct grub_net_network_level_interface *iface, ++ grub_uint32_t iaid) ++{ ++ grub_dhcp6_session_t se; ++ struct grub_datetime date; ++ grub_err_t err; ++ grub_int32_t t = 0; ++ ++ se = grub_malloc (sizeof (*se)); ++ ++ err = grub_get_datetime (&date); ++ if (err || !grub_datetime2unixtime (&date, &t)) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ t = 0; ++ } ++ ++ se->iface = iface; ++ se->iaid = iaid; ++ se->transaction_id = t; ++ se->start_time = grub_get_time_ms (); ++ se->duid.type = grub_cpu_to_be16_compile_time (3) ; ++ se->duid.hw_type = grub_cpu_to_be16_compile_time (1); ++ grub_memcpy (&se->duid.hwaddr, &iface->hwaddress.mac, sizeof (se->duid.hwaddr)); ++ se->adv = NULL; ++ se->reply = NULL; ++ grub_list_push (GRUB_AS_LIST_P (&grub_dhcp6_sessions), GRUB_AS_LIST (se)); ++} ++ ++static void ++grub_dhcp6_session_remove (grub_dhcp6_session_t se) ++{ ++ grub_list_remove (GRUB_AS_LIST (se)); ++ if (se->adv) ++ grub_dhcp6_options_free (se->adv); ++ if (se->reply) ++ grub_dhcp6_options_free (se->reply); ++ grub_free (se); ++} ++ ++static void ++grub_dhcp6_session_remove_all (void) ++{ ++ grub_dhcp6_session_t se, next; ++ ++ FOR_DHCP6_SESSIONS_SAFE (se, next) ++ { ++ grub_dhcp6_session_remove (se); ++ } ++ grub_dhcp6_sessions = NULL; ++} ++ ++static grub_err_t ++grub_dhcp6_session_configure_network (grub_dhcp6_session_t se) ++{ ++ char *name; ++ ++ name = grub_xasprintf ("%s:dhcp6", se->iface->card->name); ++ if (!name) ++ return grub_errno; ++ ++ grub_net_configure_by_dhcp6_info (name, se->iface->card, se->reply, 1, 0, 0); ++ grub_free (name); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_dhcp6_session_send_request (grub_dhcp6_session_t se) ++{ ++ struct grub_net_buff *nb; ++ struct grub_net_dhcp6_option *opt; ++ struct grub_net_dhcp6_packet *v6h; ++ struct grub_net_dhcp6_option_iana *ia_na; ++ struct grub_net_dhcp6_option_iaaddr *iaaddr; ++ struct udphdr *udph; ++ grub_net_network_level_address_t multicast; ++ grub_net_link_level_address_t ll_multicast; ++ grub_uint64_t elapsed; ++ struct grub_net_network_level_interface *inf = se->iface; ++ grub_dhcp6_options_t dhcp6 = se->adv; ++ grub_err_t err = GRUB_ERR_NONE; ++ ++ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48); ++ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL); ++ ++ err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); ++ if (err) ++ return err; ++ ++ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ ++ if (!nb) ++ return grub_errno; ++ ++ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ err = grub_netbuff_push (nb, dhcp6->client_duid_len + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID); ++ opt->len = grub_cpu_to_be16 (dhcp6->client_duid_len); ++ grub_memcpy (opt->data, dhcp6->client_duid , dhcp6->client_duid_len); ++ ++ err = grub_netbuff_push (nb, dhcp6->server_duid_len + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_SERVERID); ++ opt->len = grub_cpu_to_be16 (dhcp6->server_duid_len); ++ grub_memcpy (opt->data, dhcp6->server_duid , dhcp6->server_duid_len); ++ ++ err = grub_netbuff_push (nb, sizeof (*ia_na) + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ if (dhcp6->ia_addr) ++ { ++ err = grub_netbuff_push (nb, sizeof(*iaaddr) + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ } ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); ++ opt->len = grub_cpu_to_be16 (sizeof (*ia_na)); ++ if (dhcp6->ia_addr) ++ opt->len += grub_cpu_to_be16 (sizeof(*iaaddr) + sizeof (*opt)); ++ ++ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data; ++ ia_na->iaid = grub_cpu_to_be32 (dhcp6->iaid); ++ ++ ia_na->t1 = grub_cpu_to_be32 (dhcp6->t1); ++ ia_na->t2 = grub_cpu_to_be32 (dhcp6->t2); ++ ++ if (dhcp6->ia_addr) ++ { ++ opt = (struct grub_net_dhcp6_option *)ia_na->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR); ++ opt->len = grub_cpu_to_be16 (sizeof (*iaaddr)); ++ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)opt->data; ++ grub_set_unaligned64 (iaaddr->addr, dhcp6->ia_addr->ipv6[0]); ++ grub_set_unaligned64 (iaaddr->addr + 8, dhcp6->ia_addr->ipv6[1]); ++ ++ iaaddr->preferred_lifetime = grub_cpu_to_be32 (dhcp6->preferred_lifetime); ++ iaaddr->valid_lifetime = grub_cpu_to_be32 (dhcp6->valid_lifetime); ++ } ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + 2 * sizeof (grub_uint16_t)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option*) nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ORO); ++ opt->len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_uint16_t)); ++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL)); ++ grub_set_unaligned16 (opt->data + 2, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS)); ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ opt = (struct grub_net_dhcp6_option*) nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME); ++ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t)); ++ ++ /* the time is expressed in hundredths of a second */ ++ elapsed = grub_divmod64 (grub_get_time_ms () - se->start_time, 10, 0); ++ ++ if (elapsed > 0xffff) ++ elapsed = 0xffff; ++ ++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16 ((grub_uint16_t)elapsed)); ++ ++ err = grub_netbuff_push (nb, sizeof (*v6h)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ v6h = (struct grub_net_dhcp6_packet *) nb->data; ++ v6h->message_type = GRUB_NET_DHCP6_REQUEST; ++ v6h->transaction_id = se->transaction_id; ++ ++ err = grub_netbuff_push (nb, sizeof (*udph)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ udph = (struct udphdr *) nb->data; ++ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT); ++ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT); ++ udph->chksum = 0; ++ udph->len = grub_cpu_to_be16 (nb->tail - nb->data); ++ ++ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, ++ &inf->address, ++ &multicast); ++ err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, ++ GRUB_NET_IP_UDP); ++ ++ grub_netbuff_free (nb); ++ ++ return err; ++} ++ ++struct grub_net_network_level_interface * ++grub_net_configure_by_dhcpv6_reply (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags, ++ const struct grub_net_dhcp6_packet *v6h, ++ grub_size_t size, ++ int is_def, ++ char **device, char **path) ++{ ++ struct grub_net_network_level_interface *inf; ++ grub_dhcp6_options_t dhcp6; ++ int mask = -1; ++ ++ dhcp6 = grub_dhcp6_options_get (v6h, size); ++ if (!dhcp6) ++ { ++ grub_print_error (); ++ return NULL; ++ } ++ ++ grub_net_configure_by_dhcp6_info (name, card, dhcp6, is_def, flags, &inf); ++ ++ if (device && dhcp6->boot_file_proto && dhcp6->boot_file_server_ip) ++ { ++ *device = grub_xasprintf ("%s,%s", dhcp6->boot_file_proto, dhcp6->boot_file_server_ip); ++ grub_print_error (); ++ } ++ if (path && dhcp6->boot_file_path) ++ { ++ *path = grub_strdup (dhcp6->boot_file_path); ++ grub_print_error (); ++ if (*path) ++ { ++ char *slash; ++ slash = grub_strrchr (*path, '/'); ++ if (slash) ++ *slash = 0; ++ else ++ **path = 0; ++ } ++ } ++ ++ grub_dhcp6_options_free (dhcp6); ++ ++ if (inf) ++ grub_net_add_ipv6_local (inf, mask); ++ ++ return inf; ++} ++ + /* + * This is called directly from net/ip.c:handle_dgram(), because those + * BOOTP/DHCP packets are a bit special due to their improper +@@ -672,6 +1342,77 @@ grub_net_process_dhcp (struct grub_net_buff *nb, + } + } + ++grub_err_t ++grub_net_process_dhcp6 (struct grub_net_buff *nb, ++ struct grub_net_card *card __attribute__ ((unused))) ++{ ++ const struct grub_net_dhcp6_packet *v6h; ++ grub_dhcp6_session_t se; ++ grub_size_t size; ++ grub_dhcp6_options_t options; ++ ++ v6h = (const struct grub_net_dhcp6_packet *) nb->data; ++ size = nb->tail - nb->data; ++ ++ options = grub_dhcp6_options_get (v6h, size); ++ if (!options) ++ return grub_errno; ++ ++ if (!options->client_duid || !options->server_duid || !options->ia_addr) ++ { ++ grub_dhcp6_options_free (options); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Bad DHCPv6 Packet"); ++ } ++ ++ FOR_DHCP6_SESSIONS (se) ++ { ++ if (se->transaction_id == v6h->transaction_id && ++ grub_memcmp (options->client_duid, &se->duid, sizeof (se->duid)) == 0 && ++ se->iaid == options->iaid) ++ break; ++ } ++ ++ if (!se) ++ { ++ grub_dprintf ("bootp", "DHCPv6 session not found\n"); ++ grub_dhcp6_options_free (options); ++ return GRUB_ERR_NONE; ++ } ++ ++ if (v6h->message_type == GRUB_NET_DHCP6_ADVERTISE) ++ { ++ if (se->adv) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 Advertised .. \n"); ++ grub_dhcp6_options_free (options); ++ return GRUB_ERR_NONE; ++ } ++ ++ se->adv = options; ++ return grub_dhcp6_session_send_request (se); ++ } ++ else if (v6h->message_type == GRUB_NET_DHCP6_REPLY) ++ { ++ if (!se->adv) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 Reply .. \n"); ++ grub_dhcp6_options_free (options); ++ return GRUB_ERR_NONE; ++ } ++ ++ se->reply = options; ++ grub_dhcp6_session_configure_network (se); ++ grub_dhcp6_session_remove (se); ++ return GRUB_ERR_NONE; ++ } ++ else ++ { ++ grub_dhcp6_options_free (options); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ + static grub_err_t + grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +@@ -897,180 +1638,174 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + return err; + } + +-static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp; +- +-struct grub_net_network_level_interface * +-grub_net_configure_by_dhcpv6_ack (const char *name, +- struct grub_net_card *card, +- grub_net_interface_flags_t flags +- __attribute__((__unused__)), +- const grub_net_link_level_address_t *hwaddr, +- const struct grub_net_dhcpv6_packet *packet, +- int is_def, char **device, char **path) ++static grub_err_t ++grub_cmd_bootp6 (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, char **args) + { +- struct grub_net_network_level_interface *inter = NULL; +- struct grub_net_network_level_address addr; +- int mask = -1; ++ struct grub_net_card *card; ++ grub_uint32_t iaid = 0; ++ int interval; ++ grub_err_t err; ++ grub_dhcp6_session_t se; + +- if (!device || !path) +- return NULL; ++ err = GRUB_ERR_NONE; + +- *device = 0; +- *path = 0; ++ FOR_NET_CARDS (card) ++ { ++ struct grub_net_network_level_interface *iface; + +- grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n", +- hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2], +- hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]); ++ if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) ++ continue; + +- if (is_def) +- grub_net_default_server = 0; ++ iface = grub_net_ipv6_get_link_local (card, &card->default_address); ++ if (!iface) ++ { ++ grub_dhcp6_session_remove_all (); ++ return grub_errno; ++ } + +- if (is_def && !grub_net_default_server && packet) ++ grub_dhcp6_session_add (iface, iaid++); ++ } ++ ++ for (interval = 200; interval < 10000; interval *= 2) + { +- const grub_uint8_t *options = packet->dhcp_options; +- unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet); +- unsigned int i; +- +- for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); ) +- { +- grub_uint16_t num, len; +- grub_net_dhcpv6_option_t *opt = +- (grub_net_dhcpv6_option_t *)(options + i); +- +- num = grub_be_to_cpu16(opt->option_num); +- len = grub_be_to_cpu16(opt->option_len); +- +- grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len); +- +- if (len == 0) +- break; +- +- if (len + i > 1024) +- break; +- +- if (num == GRUB_NET_DHCP6_BOOTFILE_URL) +- { +- char *scheme, *userinfo, *host, *file; +- char *tmp; +- int hostlen; +- int port; +- int rc = extract_url_info ((const char *)opt->option_data, +- (grub_size_t)len, +- &scheme, &userinfo, &host, &port, +- &file); +- if (rc < 0) +- continue; +- +- /* right now this only handles tftp. */ +- if (grub_strcmp("tftp", scheme)) +- { +- grub_free (scheme); +- grub_free (userinfo); +- grub_free (host); +- grub_free (file); +- continue; +- } +- grub_free (userinfo); +- +- hostlen = grub_strlen (host); +- if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']') +- { +- tmp = host+1; +- host[hostlen-1] = '\0'; +- } +- else +- tmp = host; +- +- *device = grub_xasprintf ("%s,%s", scheme, tmp); +- grub_free (scheme); +- grub_free (host); +- +- if (file && *file) +- { +- tmp = grub_strrchr (file, '/'); +- if (tmp) +- *(tmp+1) = '\0'; +- else +- file[0] = '\0'; +- } +- else if (!file) +- file = grub_strdup (""); +- +- if (file[0] == '/') +- { +- *path = grub_strdup (file+1); +- grub_free (file); +- } +- else +- *path = file; +- } +- else if (num == GRUB_NET_DHCP6_IA_NA) +- { +- const grub_net_dhcpv6_option_t *ia_na_opt; +- const grub_net_dhcpv6_opt_ia_na_t *ia_na = +- (const grub_net_dhcpv6_opt_ia_na_t *)opt; +- unsigned int left = len - OFFSET_OF (options, ia_na); +- unsigned int j; +- +- if ((grub_uint8_t *)ia_na + left > +- (grub_uint8_t *)options + option_max) +- left -= ((grub_uint8_t *)ia_na + left) +- - ((grub_uint8_t *)options + option_max); +- +- if (len < OFFSET_OF (option_data, opt) +- + sizeof (grub_net_dhcpv6_option_t)) +- { +- grub_dprintf ("net", +- "found dhcpv6 ia_na option with no address\n"); +- continue; +- } +- +- for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); ) +- { +- ia_na_opt = (const grub_net_dhcpv6_option_t *) +- (ia_na->options + j); +- grub_uint16_t ia_na_opt_num, ia_na_opt_len; +- +- ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num); +- ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len); +- if (ia_na_opt_len == 0) +- break; +- if (j + ia_na_opt_len > left) +- break; +- if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS) +- { +- const grub_net_dhcpv6_opt_ia_address_t *ia_addr; +- +- ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *) +- ia_na_opt; +- addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; +- grub_memcpy(addr.ipv6, ia_addr->ipv6_address, +- sizeof (ia_addr->ipv6_address)); +- inter = grub_net_add_addr (name, card, &addr, hwaddr, 0); +- } +- +- j += ia_na_opt_len; +- left -= ia_na_opt_len; +- } +- } +- +- i += len + 4; +- } +- +- grub_print_error (); ++ int done = 1; ++ ++ FOR_DHCP6_SESSIONS (se) ++ { ++ struct grub_net_buff *nb; ++ struct grub_net_dhcp6_option *opt; ++ struct grub_net_dhcp6_packet *v6h; ++ struct grub_net_dhcp6_option_duid_ll *duid; ++ struct grub_net_dhcp6_option_iana *ia_na; ++ grub_net_network_level_address_t multicast; ++ grub_net_link_level_address_t ll_multicast; ++ struct udphdr *udph; ++ ++ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48); ++ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL); ++ ++ err = grub_net_link_layer_resolve (se->iface, ++ &multicast, &ll_multicast); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ return err; ++ } ++ ++ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ ++ if (!nb) ++ { ++ grub_dhcp6_session_remove_all (); ++ return grub_errno; ++ } ++ ++ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME); ++ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t)); ++ grub_set_unaligned16 (opt->data, 0); ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*duid)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID); ++ opt->len = grub_cpu_to_be16 (sizeof (*duid)); ++ ++ duid = (struct grub_net_dhcp6_option_duid_ll *) opt->data; ++ grub_memcpy (duid, &se->duid, sizeof (*duid)); ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*ia_na)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); ++ opt->len = grub_cpu_to_be16 (sizeof (*ia_na)); ++ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data; ++ ia_na->iaid = grub_cpu_to_be32 (se->iaid); ++ ia_na->t1 = 0; ++ ia_na->t2 = 0; ++ ++ err = grub_netbuff_push (nb, sizeof (*v6h)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ v6h = (struct grub_net_dhcp6_packet *)nb->data; ++ v6h->message_type = GRUB_NET_DHCP6_SOLICIT; ++ v6h->transaction_id = se->transaction_id; ++ ++ grub_netbuff_push (nb, sizeof (*udph)); ++ ++ udph = (struct udphdr *) nb->data; ++ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT); ++ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT); ++ udph->chksum = 0; ++ udph->len = grub_cpu_to_be16 (nb->tail - nb->data); ++ ++ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, ++ &se->iface->address, &multicast); ++ ++ err = grub_net_send_ip_packet (se->iface, &multicast, ++ &ll_multicast, nb, GRUB_NET_IP_UDP); ++ done = 0; ++ grub_netbuff_free (nb); ++ ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ return err; ++ } ++ } ++ if (!done) ++ grub_net_poll_cards (interval, 0); + } + +- if (is_def) ++ FOR_DHCP6_SESSIONS (se) + { +- grub_env_set ("net_default_interface", name); +- grub_env_export ("net_default_interface"); ++ grub_error_push (); ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ N_("couldn't autoconfigure %s"), ++ se->iface->card->name); + } + +- if (inter) +- grub_net_add_ipv6_local (inter, mask); +- return inter; ++ grub_dhcp6_session_remove_all (); ++ ++ return err; + } + ++static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp, cmd_bootp6; + + void + grub_bootp_init (void) +@@ -1084,11 +1819,15 @@ grub_bootp_init (void) + cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, + N_("VAR INTERFACE NUMBER DESCRIPTION"), + N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); ++ cmd_bootp6 = grub_register_command ("net_bootp6", grub_cmd_bootp6, ++ N_("[CARD]"), ++ N_("perform a DHCPv6 autoconfiguration")); + } + + void + grub_bootp_fini (void) + { ++ grub_unregister_command (cmd_bootp6); + grub_unregister_command (cmd_getdhcp); + grub_unregister_command (cmd_bootp); + grub_unregister_command (cmd_dhcp); +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index a673bea807..8e25680db0 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -393,9 +393,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + pxe_mode = pxe->mode; + if (pxe_mode->using_ipv6) + { +- grub_net_link_level_address_t hwaddr; +- struct grub_net_network_level_interface *intf; +- + grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); + grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", + pxe_mode->dhcp_ack_received ? "yes" : "no", +@@ -403,15 +400,14 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (!pxe_mode->dhcp_ack_received) + continue; + +- hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (hwaddr.mac, +- card->efi_net->mode->current_address, +- sizeof (hwaddr.mac)); +- +- intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr, +- (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6, +- 1, device, path); +- if (intf && device && path) ++ grub_net_configure_by_dhcpv6_reply (card->name, card, 0, ++ (struct grub_net_dhcp6_packet *) ++ &pxe_mode->dhcp_ack, ++ sizeof (pxe_mode->dhcp_ack), ++ 1, device, path); ++ if (grub_errno) ++ grub_print_error (); ++ if (device && path) + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } + else +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index a5896f6dc2..ce6bdc75c6 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -239,6 +239,45 @@ handle_dgram (struct grub_net_buff *nb, + { + struct udphdr *udph; + udph = (struct udphdr *) nb->data; ++ ++ if (proto == GRUB_NET_IP_UDP && udph->dst == grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT)) ++ { ++ if (udph->chksum) ++ { ++ grub_uint16_t chk, expected; ++ chk = udph->chksum; ++ udph->chksum = 0; ++ expected = grub_net_ip_transport_checksum (nb, ++ GRUB_NET_IP_UDP, ++ source, ++ dest); ++ if (expected != chk) ++ { ++ grub_dprintf ("net", "Invalid UDP checksum. " ++ "Expected %x, got %x\n", ++ grub_be_to_cpu16 (expected), ++ grub_be_to_cpu16 (chk)); ++ grub_netbuff_free (nb); ++ return GRUB_ERR_NONE; ++ } ++ udph->chksum = chk; ++ } ++ ++ err = grub_netbuff_pull (nb, sizeof (*udph)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ err = grub_net_process_dhcp6 (nb, card); ++ if (err) ++ grub_print_error (); ++ ++ grub_netbuff_free (nb); ++ return GRUB_ERR_NONE; ++ } ++ + if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) + { + const struct grub_net_bootp_packet *bootp; +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 9962880147..7614b58dca 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -1532,7 +1532,7 @@ typedef struct grub_efi_pxe_ip_filter + { + grub_efi_uint8_t filters; + grub_efi_uint8_t ip_count; +- grub_efi_uint8_t reserved; ++ grub_efi_uint16_t reserved; + grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; + } grub_efi_pxe_ip_filter_t; + +diff --git a/include/grub/net.h b/include/grub/net.h +index d55d505a03..543251f727 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -451,50 +451,65 @@ struct grub_net_bootp_packet + grub_uint8_t vendor[0]; + } GRUB_PACKED; + +-enum +- { +- GRUB_NET_DHCP6_IA_NA = 3, +- GRUB_NET_DHCP6_IA_ADDRESS = 5, +- GRUB_NET_DHCP6_BOOTFILE_URL = 59, +- }; +- +-struct grub_net_dhcpv6_option ++struct grub_net_dhcp6_packet + { +- grub_uint16_t option_num; +- grub_uint16_t option_len; +- grub_uint8_t option_data[]; ++ grub_uint32_t message_type:8; ++ grub_uint32_t transaction_id:24; ++ grub_uint8_t dhcp_options[0]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t; + +-struct grub_net_dhcpv6_opt_ia_na +-{ +- grub_uint16_t option_num; +- grub_uint16_t option_len; ++struct grub_net_dhcp6_option { ++ grub_uint16_t code; ++ grub_uint16_t len; ++ grub_uint8_t data[0]; ++} GRUB_PACKED; ++ ++struct grub_net_dhcp6_option_iana { + grub_uint32_t iaid; + grub_uint32_t t1; + grub_uint32_t t2; +- grub_uint8_t options[]; ++ grub_uint8_t data[0]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t; + +-struct grub_net_dhcpv6_opt_ia_address +-{ +- grub_uint16_t option_num; +- grub_uint16_t option_len; +- grub_uint64_t ipv6_address[2]; ++struct grub_net_dhcp6_option_iaaddr { ++ grub_uint8_t addr[16]; + grub_uint32_t preferred_lifetime; + grub_uint32_t valid_lifetime; +- grub_uint8_t options[]; ++ grub_uint8_t data[0]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t; + +-struct grub_net_dhcpv6_packet ++struct grub_net_dhcp6_option_duid_ll + { +- grub_uint32_t message_type:8; +- grub_uint32_t transaction_id:24; +- grub_uint8_t dhcp_options[1024]; ++ grub_uint16_t type; ++ grub_uint16_t hw_type; ++ grub_uint8_t hwaddr[6]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t; ++ ++enum ++ { ++ GRUB_NET_DHCP6_SOLICIT = 1, ++ GRUB_NET_DHCP6_ADVERTISE = 2, ++ GRUB_NET_DHCP6_REQUEST = 3, ++ GRUB_NET_DHCP6_REPLY = 7 ++ }; ++ ++enum ++ { ++ DHCP6_CLIENT_PORT = 546, ++ DHCP6_SERVER_PORT = 547 ++ }; ++ ++enum ++ { ++ GRUB_NET_DHCP6_OPTION_CLIENTID = 1, ++ GRUB_NET_DHCP6_OPTION_SERVERID = 2, ++ GRUB_NET_DHCP6_OPTION_IA_NA = 3, ++ GRUB_NET_DHCP6_OPTION_IAADDR = 5, ++ GRUB_NET_DHCP6_OPTION_ORO = 6, ++ GRUB_NET_DHCP6_OPTION_ELAPSED_TIME = 8, ++ GRUB_NET_DHCP6_OPTION_DNS_SERVERS = 23, ++ GRUB_NET_DHCP6_OPTION_BOOTFILE_URL = 59 ++ }; + + #define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 + #define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 +@@ -532,12 +547,12 @@ grub_net_configure_by_dhcp_ack (const char *name, + int is_def, char **device, char **path); + + struct grub_net_network_level_interface * +-grub_net_configure_by_dhcpv6_ack (const char *name, +- struct grub_net_card *card, +- grub_net_interface_flags_t flags, +- const grub_net_link_level_address_t *hwaddr, +- const struct grub_net_dhcpv6_packet *packet, +- int is_def, char **device, char **path); ++grub_net_configure_by_dhcpv6_reply (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags, ++ const struct grub_net_dhcp6_packet *v6, ++ grub_size_t size, ++ int is_def, char **device, char **path); + + int + grub_ipv6_get_masksize(grub_uint16_t *mask); +@@ -554,6 +569,10 @@ void + grub_net_process_dhcp (struct grub_net_buff *nb, + struct grub_net_network_level_interface *iface); + ++grub_err_t ++grub_net_process_dhcp6 (struct grub_net_buff *nb, ++ struct grub_net_card *card); ++ + int + grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + const grub_net_link_level_address_t *b); diff --git a/SOURCES/0073-align-struct-efi_variable-better.patch b/SOURCES/0073-align-struct-efi_variable-better.patch deleted file mode 100644 index ec26def..0000000 --- a/SOURCES/0073-align-struct-efi_variable-better.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 27 Feb 2018 13:55:35 -0500 -Subject: [PATCH] align struct efi_variable better... - ---- - include/grub/efiemu/runtime.h | 2 +- - include/grub/types.h | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/include/grub/efiemu/runtime.h b/include/grub/efiemu/runtime.h -index 36d2dedf47e..9d93ba88bac 100644 ---- a/include/grub/efiemu/runtime.h -+++ b/include/grub/efiemu/runtime.h -@@ -33,5 +33,5 @@ struct efi_variable - grub_uint32_t namelen; - grub_uint32_t size; - grub_efi_uint32_t attributes; --} GRUB_PACKED; -+} GRUB_PACKED GRUB_ALIGNED(8); - #endif /* ! GRUB_EFI_EMU_RUNTIME_HEADER */ -diff --git a/include/grub/types.h b/include/grub/types.h -index 0a3ff159136..ba446d99040 100644 ---- a/include/grub/types.h -+++ b/include/grub/types.h -@@ -29,6 +29,7 @@ - #else - #define GRUB_PACKED __attribute__ ((packed)) - #endif -+#define GRUB_ALIGNED(x) __attribute__((aligned (x))) - - #ifdef GRUB_BUILD - # define GRUB_CPU_SIZEOF_VOID_P BUILD_SIZEOF_VOID_P diff --git a/SOURCES/0073-efinet-UEFI-IPv6-PXE-support.patch b/SOURCES/0073-efinet-UEFI-IPv6-PXE-support.patch new file mode 100644 index 0000000..988c178 --- /dev/null +++ b/SOURCES/0073-efinet-UEFI-IPv6-PXE-support.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 15 Apr 2015 14:48:30 +0800 +Subject: [PATCH] efinet: UEFI IPv6 PXE support + +When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is +cached in firmware buffer which can be obtained by PXE Base Code protocol. The +network interface can be setup through the parameters in that obtained packet. + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +--- + grub-core/net/drivers/efi/efinet.c | 2 ++ + include/grub/efi/api.h | 71 +++++++++++++++++++++++--------------- + 2 files changed, 46 insertions(+), 27 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 8e25680db0..014e5bf980 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -409,6 +409,8 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + grub_print_error (); + if (device && path) + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); ++ if (grub_errno) ++ grub_print_error (); + } + else + { +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 7614b58dca..91ab528e4d 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -1524,31 +1524,6 @@ typedef union + grub_efi_pxe_dhcpv6_packet_t dhcpv6; + } grub_efi_pxe_packet_t; + +-#define GRUB_EFI_PXE_MAX_IPCNT 8 +-#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8 +-#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8 +- +-typedef struct grub_efi_pxe_ip_filter +-{ +- grub_efi_uint8_t filters; +- grub_efi_uint8_t ip_count; +- grub_efi_uint16_t reserved; +- grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; +-} grub_efi_pxe_ip_filter_t; +- +-typedef struct grub_efi_pxe_arp_entry +-{ +- grub_efi_ip_address_t ip_addr; +- grub_efi_mac_address_t mac_addr; +-} grub_efi_pxe_arp_entry_t; +- +-typedef struct grub_efi_pxe_route_entry +-{ +- grub_efi_ip_address_t ip_addr; +- grub_efi_ip_address_t subnet_mask; +- grub_efi_ip_address_t gateway_addr; +-} grub_efi_pxe_route_entry_t; +- + typedef struct grub_efi_pxe_icmp_error + { + grub_efi_uint8_t type; +@@ -1574,6 +1549,48 @@ typedef struct grub_efi_pxe_tftp_error + grub_efi_char8_t error_string[127]; + } grub_efi_pxe_tftp_error_t; + ++typedef struct { ++ grub_uint8_t addr[4]; ++} grub_efi_pxe_ipv4_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[16]; ++} grub_efi_pxe_ipv6_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[32]; ++} grub_efi_pxe_mac_address_t; ++ ++typedef union { ++ grub_uint32_t addr[4]; ++ grub_efi_pxe_ipv4_address_t v4; ++ grub_efi_pxe_ipv6_address_t v6; ++} grub_efi_pxe_ip_address_t; ++ ++#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 ++typedef struct grub_efi_pxe_ip_filter ++{ ++ grub_efi_uint8_t filters; ++ grub_efi_uint8_t ip_count; ++ grub_efi_uint16_t reserved; ++ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT]; ++} grub_efi_pxe_ip_filter_t; ++ ++typedef struct { ++ grub_efi_pxe_ip_address_t ip_addr; ++ grub_efi_pxe_mac_address_t mac_addr; ++} grub_efi_pxe_arp_entry_t; ++ ++typedef struct { ++ grub_efi_pxe_ip_address_t ip_addr; ++ grub_efi_pxe_ip_address_t subnet_mask; ++ grub_efi_pxe_ip_address_t gw_addr; ++} grub_efi_pxe_route_entry_t; ++ ++ ++#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 ++#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 ++ + typedef struct grub_efi_pxe_mode + { + grub_efi_boolean_t started; +@@ -1605,9 +1622,9 @@ typedef struct grub_efi_pxe_mode + grub_efi_pxe_packet_t pxe_bis_reply; + grub_efi_pxe_ip_filter_t ip_filter; + grub_efi_uint32_t arp_cache_entries; +- grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES]; ++ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; + grub_efi_uint32_t route_table_entries; +- grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES]; ++ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; + grub_efi_pxe_icmp_error_t icmp_error; + grub_efi_pxe_tftp_error_t tftp_error; + } grub_efi_pxe_mode_t; diff --git a/SOURCES/0074-Add-BLS-support-to-grub-mkconfig.patch b/SOURCES/0074-Add-BLS-support-to-grub-mkconfig.patch deleted file mode 100644 index 6c65440..0000000 --- a/SOURCES/0074-Add-BLS-support-to-grub-mkconfig.patch +++ /dev/null @@ -1,397 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 9 Dec 2016 15:40:29 -0500 -Subject: [PATCH] Add BLS support to grub-mkconfig - -GRUB now has BootLoaderSpec support, the user can choose to use this by -setting GRUB_ENABLE_BLSCFG to true in /etc/default/grub. On this setup, -the boot menu entries are not added to the grub.cfg, instead BLS config -files are parsed by blscfg command and the entries created dynamically. - -A 10_linux_bls grub.d snippet to generate menu entries from BLS files -is also added that can be used on platforms where the bootloader doesn't -have BLS support and only can parse a normal grub configuration file. - -Portions of the 10_linux_bls were taken from the ostree-grub-generator -script that's included in the OSTree project. - -Fixes to support multi-devices and generate a BLS section even if no -kernels are found in the boot directory were proposed by Yclept Nemo -and Tom Gundersen respectively. - -Signed-off-by: Peter Jones -Signed-off-by: Javier Martinez Canillas ---- - util/grub-mkconfig.8 | 4 + - util/grub-mkconfig.in | 9 +- - util/grub-mkconfig_lib.in | 22 ++++- - util/grub.d/10_linux.in | 223 +++++++++++++++++++++++++++++++++++++++++++++- - 4 files changed, 252 insertions(+), 6 deletions(-) - -diff --git a/util/grub-mkconfig.8 b/util/grub-mkconfig.8 -index a2d1f577b9b..434fa4deda4 100644 ---- a/util/grub-mkconfig.8 -+++ b/util/grub-mkconfig.8 -@@ -13,5 +13,9 @@ - \fB--output\fR=\fIFILE\fR - Write generated output to \fIFILE\fR. - -+.TP -+\fB--no-grubenv-update\fR -+Do not update variables in the grubenv file. -+ - .SH SEE ALSO - .BR "info grub" -diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in -index 535c0f02499..f55339a3f64 100644 ---- a/util/grub-mkconfig.in -+++ b/util/grub-mkconfig.in -@@ -50,6 +50,8 @@ grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@" - export TEXTDOMAIN=@PACKAGE@ - export TEXTDOMAINDIR="@localedir@" - -+export GRUB_GRUBENV_UPDATE="yes" -+ - . "${pkgdatadir}/grub-mkconfig_lib" - - # Usage: usage -@@ -59,6 +61,7 @@ usage () { - gettext "Generate a grub config file"; echo - echo - print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")" -+ print_option_help "--no-grubenv-update" "$(gettext "do not update variables in the grubenv file")" - print_option_help "-h, --help" "$(gettext "print this message and exit")" - print_option_help "-V, --version" "$(gettext "print the version information and exit")" - echo -@@ -94,6 +97,9 @@ do - --output=*) - grub_cfg=`echo "$option" | sed 's/--output=//'` - ;; -+ --no-grubenv-update) -+ GRUB_GRUBENV_UPDATE="no" -+ ;; - -*) - gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 - usage -@@ -253,7 +259,8 @@ export GRUB_DEFAULT \ - GRUB_OS_PROBER_SKIP_LIST \ - GRUB_DISABLE_SUBMENU \ - GRUB_DEFAULT_DTB \ -- SUSE_BTRFS_SNAPSHOT_BOOTING -+ SUSE_BTRFS_SNAPSHOT_BOOTING \ -+ GRUB_ENABLE_BLSCFG - - if test "x${grub_cfg}" != "x"; then - rm -f "${grub_cfg}.new" -diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in -index fafeac95061..d8bb4069360 100644 ---- a/util/grub-mkconfig_lib.in -+++ b/util/grub-mkconfig_lib.in -@@ -30,6 +30,9 @@ fi - if test "x$grub_file" = x; then - grub_file="${bindir}/@grub_file@" - fi -+if test "x$grub_editenv" = x; then -+ grub_editenv="${bindir}/@grub_editenv@" -+fi - if test "x$grub_mkrelpath" = x; then - grub_mkrelpath="${bindir}/@grub_mkrelpath@" - fi -@@ -125,8 +128,19 @@ EOF - fi - } - -+prepare_grub_to_access_device_with_variable () -+{ -+ device_variable="$1" -+ shift -+ prepare_grub_to_access_device "$@" -+ unset "device_variable" -+} -+ - prepare_grub_to_access_device () - { -+ if [ -z "$device_variable" ]; then -+ device_variable="root" -+ fi - old_ifs="$IFS" - IFS=' - ' -@@ -161,18 +175,18 @@ prepare_grub_to_access_device () - # otherwise set root as per value in device.map. - fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`" - if [ "x$fs_hint" != x ]; then -- echo "set root='$fs_hint'" -+ echo "set ${device_variable}='$fs_hint'" - fi - if [ "x${GRUB_DISABLE_UUID}" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then - hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints= - if [ "x$hints" != x ]; then - echo "if [ x\$feature_platform_search_hint = xy ]; then" -- echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}" -+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${hints} ${fs_uuid}" - echo "else" -- echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}" -+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}" - echo "fi" - else -- echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" -+ echo "search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}" - fi - fi - IFS="$old_ifs" -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index cbfaca34cc7..68adb55d893 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -82,6 +82,223 @@ case x"$GRUB_FS" in - ;; - esac - -+populate_header_warn() -+{ -+if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then -+ bls_parser="10_linux script" -+else -+ bls_parser="blscfg command" -+fi -+cat </dev/null | tac)) || : -+ -+ echo "${files[@]}" -+} -+ -+update_bls_cmdline() -+{ -+ local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" -+ local -a files=($(get_sorted_bls)) -+ -+ for bls in "${files[@]}"; do -+ local options="${cmdline}" -+ if [ -z "${bls##*debug*}" ]; then -+ options="${options} ${GRUB_CMDLINE_LINUX_DEBUG}" -+ fi -+ options="$(echo "${options}" | sed -e 's/\//\\\//g')" -+ sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf" -+ done -+} -+ -+populate_menu() -+{ -+ local -a files=($(get_sorted_bls)) -+ -+ gettext_printf "Generating boot entries from BLS files...\n" >&2 -+ -+ for bls in "${files[@]}"; do -+ read_config "${blsdir}/${bls}.conf" -+ -+ menu="${menu}menuentry '${title}' ${grub_arg} --id=${bls} {\n" -+ menu="${menu}\t linux ${linux} ${options}\n" -+ if [ -n "${initrd}" ] ; then -+ menu="${menu}\t initrd ${boot_prefix}${initrd}\n" -+ fi -+ menu="${menu}}\n\n" -+ done -+ # The printf command seems to be more reliable across shells for special character (\n, \t) evaluation -+ printf "$menu" -+} -+ -+# Make BLS the default if GRUB_ENABLE_BLSCFG was not set and grubby is not installed. -+if [ -z "${GRUB_ENABLE_BLSCFG}" ] && [ -z "$(which new-kernel-pkg 2> /dev/null)" ]; then -+ GRUB_ENABLE_BLSCFG="true" -+fi -+ -+if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then -+ if [ x$dirname = x/ ]; then -+ if [ -z "${prepare_root_cache}" ]; then -+ prepare_grub_to_access_device ${GRUB_DEVICE} -+ fi -+ else -+ if [ -z "${prepare_boot_cache}" ]; then -+ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} -+ fi -+ fi -+ -+ if [ -d /sys/firmware/efi ]; then -+ bootefi_device="`${grub_probe} --target=device /boot/efi/`" -+ prepare_grub_to_access_device_with_variable boot ${bootefi_device} -+ else -+ boot_device="`${grub_probe} --target=device /boot/`" -+ prepare_grub_to_access_device_with_variable boot ${boot_device} -+ fi -+ -+ arch="$(uname -m)" -+ if [ "x${arch}" = "xppc64le" ] && [ -d /sys/firmware/opal ]; then -+ -+ BLS_POPULATE_MENU="true" -+ petitboot_path="/sys/firmware/devicetree/base/ibm,firmware-versions/petitboot" -+ -+ if test -e ${petitboot_path}; then -+ read -r -d '' petitboot_version < ${petitboot_path} -+ petitboot_version="$(echo ${petitboot_version//v})" -+ -+ if test -n ${petitboot_version}; then -+ major_version="$(echo ${petitboot_version} | cut -d . -f1)" -+ minor_version="$(echo ${petitboot_version} | cut -d . -f2)" -+ -+ re='^[0-9]+$' -+ if [[ $major_version =~ $re ]] && [[ $minor_version =~ $re ]] && -+ ([[ ${major_version} -gt 1 ]] || -+ [[ ${major_version} -eq 1 && -+ ${minor_version} -ge 8 ]]); then -+ BLS_POPULATE_MENU="false" -+ fi -+ fi -+ fi -+ fi -+ -+ populate_header_warn -+ -+ cat << EOF -+# The kernelopts variable should be defined in the grubenv file. But to ensure that menu -+# entries populated from BootLoaderSpec files that use this variable work correctly even -+# without a grubenv file, define a fallback kernelopts variable if this has not been set. -+# -+# The kernelopts variable in the grubenv file can be modified using the grubby tool or by -+# executing the grub2-mkconfig tool. For the latter, the values of the GRUB_CMDLINE_LINUX -+# and GRUB_CMDLINE_LINUX_DEFAULT options from /etc/default/grub file are used to set both -+# the kernelopts variable in the grubenv file and the fallback kernelopts variable. -+if [ -z "\${kernelopts}" ]; then -+ set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" -+fi -+EOF -+ -+ update_bls_cmdline -+ -+ if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then -+ populate_menu -+ else -+ cat << EOF -+ -+insmod blscfg -+blscfg -+EOF -+ fi -+ -+ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then -+ blsdir="/boot/loader/entries" -+ [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})" -+ if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then -+ blsdir=$(make_system_path_relative_to_its_root "${blsdir}") -+ if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then -+ ${grub_editenv} - set blsdir="${blsdir}" -+ fi -+ fi -+ -+ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then -+ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}" -+ fi -+ -+ if [ -n "${GRUB_DEFAULT_DTB}" ]; then -+ ${grub_editenv} - set devicetree="${GRUB_DEFAULT_DTB}" -+ fi -+ -+ if [ -n "${GRUB_SAVEDEFAULT}" ]; then -+ ${grub_editenv} - set save_default="${GRUB_SAVEDEFAULT}" -+ fi -+ fi -+ -+ exit 0 -+fi -+ - mktitle () - { - local title_type -@@ -121,6 +338,7 @@ linux_entry () - if [ -z "$boot_device_id" ]; then - boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" - fi -+ - if [ x$type != xsimple ] ; then - title=$(mktitle "$type" "$version") - if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then -@@ -224,6 +442,7 @@ is_top_level=true - while [ "x$list" != "x" ] ; do - linux=`version_find_latest $list` - gettext_printf "Found linux image: %s\n" "$linux" >&2 -+ - basename=`basename $linux` - dirname=`dirname $linux` - rel_dirname=`make_system_path_relative_to_its_root $dirname` -@@ -262,7 +481,9 @@ while [ "x$list" != "x" ] ; do - for i in ${initrd}; do - initrd_display="${initrd_display} ${dirname}/${i}" - done -- gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2 -+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then -+ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2 -+ fi - fi - - fdt= diff --git a/SOURCES/0074-grub.texi-Add-net_bootp6-doument.patch b/SOURCES/0074-grub.texi-Add-net_bootp6-doument.patch new file mode 100644 index 0000000..b42e09b --- /dev/null +++ b/SOURCES/0074-grub.texi-Add-net_bootp6-doument.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 5 May 2015 14:19:24 +0800 +Subject: [PATCH] grub.texi: Add net_bootp6 doument + +Update grub documentation for net_bootp6 command. + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +--- + docs/grub.texi | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/docs/grub.texi b/docs/grub.texi +index 0615d0ed97..04ed6ac1f0 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -5487,6 +5487,7 @@ This command is only available on AArch64 systems. + * net_add_dns:: Add a DNS server + * net_add_route:: Add routing entry + * net_bootp:: Perform a bootp/DHCP autoconfiguration ++* net_bootp6:: Perform a DHCPv6 autoconfiguration + * net_del_addr:: Remove IP address from interface + * net_del_dns:: Remove a DNS server + * net_del_route:: Remove a route entry +@@ -5611,6 +5612,22 @@ Sets environment variable @samp{net_}@var{}@samp{_boot_file} + + @end deffn + ++@node net_bootp6 ++@subsection net_bootp6 ++ ++@deffn Command net_bootp6 [@var{card}] ++Perform configuration of @var{card} using DHCPv6 protocol. If no card name is ++specified, try to configure all existing cards. If configuration was ++successful, interface with name @var{card}@samp{:dhcp6} and configured address ++is added to @var{card}. ++ ++@table @samp ++@item 1 (Domain Name Server) ++Adds all servers from option value to the list of servers used during name ++resolution. ++@end table ++ ++@end deffn + + @node net_get_dhcp_option + @subsection net_get_dhcp_option diff --git a/SOURCES/0075-Don-t-attempt-to-backtrace-on-grub_abort-for-grub-em.patch b/SOURCES/0075-Don-t-attempt-to-backtrace-on-grub_abort-for-grub-em.patch deleted file mode 100644 index 9ff4c8b..0000000 --- a/SOURCES/0075-Don-t-attempt-to-backtrace-on-grub_abort-for-grub-em.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 6 Feb 2018 11:16:28 +0100 -Subject: [PATCH] Don't attempt to backtrace on grub_abort() for grub-emu - -The emu platform doesn't have a grub_backtrace() implementation, so this -causes a build error. Don't attempt to call this when building grub-emu. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/kern/misc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index a3e215155bd..c60601b699d 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -1201,7 +1201,7 @@ static void __attribute__ ((noreturn)) - grub_abort (void) - { - #ifndef GRUB_UTIL --#if defined(__i386__) || defined(__x86_64__) -+#if (defined(__i386__) || defined(__x86_64__)) && !defined(GRUB_MACHINE_EMU) - grub_backtrace(); - #endif - #endif diff --git a/SOURCES/0075-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch b/SOURCES/0075-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch new file mode 100644 index 0000000..abff9eb --- /dev/null +++ b/SOURCES/0075-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 10 Jul 2019 23:58:28 +0200 +Subject: [PATCH] bootp: Add processing DHCPACK packet from HTTP Boot + +The vendor class identifier with the string "HTTPClient" is used to denote the +packet as responding to HTTP boot request. In DHCP4 config, the filename for +HTTP boot is the URL of the boot file while for PXE boot it is the path to the +boot file. As a consequence, the next-server becomes obseleted because the HTTP +URL already contains the server address for the boot file. For DHCP6 config, +there's no difference definition in existing config as dhcp6.bootfile-url can +be used to specify URL for both HTTP and PXE boot file. + +This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK +packet by treating it as HTTP format, not as the PXE format. + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +--- + grub-core/net/bootp.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ + include/grub/net.h | 1 + + 2 files changed, 56 insertions(+) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index fe93b80f1c..8fb8918ae7 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -500,6 +501,60 @@ grub_net_configure_by_dhcp_ack (const char *name, + if (opt && opt_len) + grub_env_set_net_property (name, "rootpath", (const char *) opt, opt_len); + ++ opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER, &opt_len); ++ if (opt && opt_len) ++ { ++ grub_env_set_net_property (name, "vendor_class_identifier", (const char *) opt, opt_len); ++ if (opt && grub_strcmp (opt, "HTTPClient") == 0) ++ { ++ char *proto, *ip, *pa; ++ ++ if (!dissect_url (bp->boot_file, &proto, &ip, &pa)) ++ return inter; ++ ++ grub_env_set_net_property (name, "boot_file", pa, grub_strlen (pa)); ++ if (is_def) ++ { ++ grub_net_default_server = grub_strdup (ip); ++ grub_env_set ("net_default_interface", name); ++ grub_env_export ("net_default_interface"); ++ } ++ if (device && !*device) ++ { ++ *device = grub_xasprintf ("%s,%s", proto, ip); ++ grub_print_error (); ++ } ++ if (path) ++ { ++ *path = grub_strdup (pa); ++ grub_print_error (); ++ if (*path) ++ { ++ char *slash; ++ slash = grub_strrchr (*path, '/'); ++ if (slash) ++ *slash = 0; ++ else ++ **path = 0; ++ } ++ } ++ grub_net_add_ipv4_local (inter, mask); ++ inter->dhcp_ack = grub_malloc (size); ++ if (inter->dhcp_ack) ++ { ++ grub_memcpy (inter->dhcp_ack, bp, size); ++ inter->dhcp_acklen = size; ++ } ++ else ++ grub_errno = GRUB_ERR_NONE; ++ ++ grub_free (proto); ++ grub_free (ip); ++ grub_free (pa); ++ return inter; ++ } ++ } ++ + opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_EXTENSIONS_PATH, &opt_len); + if (opt && opt_len) + grub_env_set_net_property (name, "extensionspath", (const char *) opt, opt_len); +diff --git a/include/grub/net.h b/include/grub/net.h +index 543251f727..42af7de250 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -531,6 +531,7 @@ enum + GRUB_NET_DHCP_MESSAGE_TYPE = 53, + GRUB_NET_DHCP_SERVER_IDENTIFIER = 54, + GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55, ++ GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 60, + GRUB_NET_BOOTP_CLIENT_ID = 61, + GRUB_NET_DHCP_TFTP_SERVER_NAME = 66, + GRUB_NET_DHCP_BOOTFILE_NAME = 67, diff --git a/SOURCES/0076-Add-linux-and-initrd-commands-for-grub-emu.patch b/SOURCES/0076-Add-linux-and-initrd-commands-for-grub-emu.patch deleted file mode 100644 index dd69b13..0000000 --- a/SOURCES/0076-Add-linux-and-initrd-commands-for-grub-emu.patch +++ /dev/null @@ -1,347 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Tue, 6 Feb 2018 09:09:00 +0100 -Subject: [PATCH] Add linux and initrd commands for grub-emu - -When using grub-emu, the linux and initrd commands are used as arguments -to the kexec command line tool, to allow booting the selected menu entry. ---- - grub-core/Makefile.core.def | 1 - - grub-core/kern/emu/main.c | 4 + - grub-core/kern/emu/misc.c | 18 ++++- - grub-core/loader/emu/linux.c | 172 +++++++++++++++++++++++++++++++++++++++++++ - include/grub/emu/exec.h | 4 +- - include/grub/emu/hostfile.h | 3 +- - include/grub/emu/misc.h | 3 + - grub-core/Makefile.am | 1 + - 8 files changed, 202 insertions(+), 4 deletions(-) - create mode 100644 grub-core/loader/emu/linux.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 058c88ac3af..5354f9613d3 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1826,7 +1826,6 @@ module = { - - common = loader/linux.c; - common = lib/cmdline.c; -- enable = noemu; - - efi = loader/efi/linux.c; - }; -diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c -index 55ea5a11ccd..846fe9715ec 100644 ---- a/grub-core/kern/emu/main.c -+++ b/grub-core/kern/emu/main.c -@@ -107,6 +107,7 @@ static struct argp_option options[] = { - N_("use GRUB files in the directory DIR [default=%s]"), 0}, - {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, - {"hold", 'H', N_("SECS"), OPTION_ARG_OPTIONAL, N_("wait until a debugger will attach"), 0}, -+ {"kexec", 'X', 0, 0, N_("try the untryable."), 0}, - { 0, 0, 0, 0, 0, 0 } - }; - -@@ -164,6 +165,9 @@ argp_parser (int key, char *arg, struct argp_state *state) - case 'v': - verbosity++; - break; -+ case 'X': -+ grub_util_set_kexecute(); -+ break; - - case ARGP_KEY_ARG: - { -diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c -index 0ff13bcaf8c..eeea092752d 100644 ---- a/grub-core/kern/emu/misc.c -+++ b/grub-core/kern/emu/misc.c -@@ -39,6 +39,7 @@ - #include - - int verbosity; -+int kexecute; - - void - grub_util_warn (const char *fmt, ...) -@@ -82,7 +83,7 @@ grub_util_error (const char *fmt, ...) - vfprintf (stderr, fmt, ap); - va_end (ap); - fprintf (stderr, ".\n"); -- exit (1); -+ grub_exit (1); - } - - void * -@@ -154,6 +155,9 @@ void - __attribute__ ((noreturn)) - grub_exit (int rc) - { -+#if defined (GRUB_KERNEL) -+ grub_reboot(); -+#endif - exit (rc < 0 ? 1 : rc); - } - #endif -@@ -215,3 +219,15 @@ grub_util_load_image (const char *path, char *buf) - - fclose (fp); - } -+ -+void -+grub_util_set_kexecute(void) -+{ -+ kexecute++; -+} -+ -+int -+grub_util_get_kexecute(void) -+{ -+ return kexecute; -+} -diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c -new file mode 100644 -index 00000000000..fda9e00d24c ---- /dev/null -+++ b/grub-core/loader/emu/linux.c -@@ -0,0 +1,172 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static grub_dl_t my_mod; -+ -+static char *kernel_path; -+static char *initrd_path; -+static char *boot_cmdline; -+ -+static grub_err_t -+grub_linux_boot (void) -+{ -+ grub_err_t rc = GRUB_ERR_NONE; -+ char *initrd_param; -+ const char *kexec[] = { "kexec", "-l", kernel_path, boot_cmdline, NULL, NULL }; -+ const char *systemctl[] = { "systemctl", "kexec", NULL }; -+ int kexecute = grub_util_get_kexecute(); -+ -+ if (initrd_path) { -+ initrd_param = grub_xasprintf("--initrd=%s", initrd_path); -+ kexec[3] = initrd_param; -+ kexec[4] = boot_cmdline; -+ } else { -+ initrd_param = grub_xasprintf("%s", ""); -+ } -+ -+ grub_printf("%serforming 'kexec -l %s %s %s'\n", -+ (kexecute) ? "P" : "Not p", -+ kernel_path, initrd_param, boot_cmdline); -+ -+ if (kexecute) -+ rc = grub_util_exec(kexec); -+ -+ grub_free(initrd_param); -+ -+ if (rc != GRUB_ERR_NONE) { -+ grub_error (rc, N_("Error trying to perform kexec load operation.")); -+ grub_sleep (3); -+ return rc; -+ } -+ if (kexecute < 1) -+ grub_fatal (N_("Use '"PACKAGE"-emu --kexec' to force a system restart.")); -+ -+ grub_printf("Performing 'systemctl kexec' (%s) ", -+ (kexecute==1) ? "do-or-die" : "just-in-case"); -+ rc = grub_util_exec (systemctl); -+ -+ if (kexecute == 1) -+ grub_fatal (N_("Error trying to perform 'systemctl kexec'")); -+ -+ /* need to check read-only root before resetting hard!? */ -+ grub_printf("Performing 'kexec -e'"); -+ kexec[1] = "-e"; -+ kexec[2] = NULL; -+ rc = grub_util_exec(kexec); -+ if ( rc != GRUB_ERR_NONE ) -+ grub_fatal (N_("Error trying to directly perform 'kexec -e'.")); -+ -+ return rc; -+} -+ -+static grub_err_t -+grub_linux_unload (void) -+{ -+ grub_dl_unref (my_mod); -+ if ( boot_cmdline != NULL ) -+ grub_free (boot_cmdline); -+ boot_cmdline = NULL; -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) -+{ -+ int i; -+ char *tempstr; -+ -+ grub_dl_ref (my_mod); -+ -+ if (argc == 0) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ -+ if ( !grub_util_is_regular(argv[0]) ) -+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("Cannot find kernel file %s"), argv[0]); -+ -+ if ( kernel_path != NULL ) -+ grub_free(kernel_path); -+ -+ kernel_path = grub_xasprintf("%s", argv[0]); -+ -+ if ( boot_cmdline != NULL ) { -+ grub_free(boot_cmdline); -+ boot_cmdline = NULL; -+ } -+ -+ if ( argc > 1 ) -+ { -+ boot_cmdline = grub_xasprintf("--command-line=%s", argv[1]); -+ for ( i = 2; i < argc; i++ ) { -+ tempstr = grub_xasprintf("%s %s", boot_cmdline, argv[i]); -+ grub_free(boot_cmdline); -+ boot_cmdline = tempstr; -+ } -+ } -+ -+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) -+{ -+ if (argc == 0) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -+ -+ if ( !grub_util_is_regular(argv[0]) ) -+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("Cannot find initrd file %s"), argv[0]); -+ -+ if ( initrd_path != NULL ) -+ grub_free(initrd_path); -+ -+ initrd_path = grub_xasprintf("%s", argv[0]); -+ -+ grub_dl_unref (my_mod); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_command_t cmd_linux, cmd_initrd; -+ -+GRUB_MOD_INIT(linux) -+{ -+ cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0, N_("Load Linux.")); -+ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0, N_("Load initrd.")); -+ my_mod = mod; -+ kernel_path = NULL; -+ initrd_path = NULL; -+ boot_cmdline = NULL; -+} -+ -+GRUB_MOD_FINI(linux) -+{ -+ grub_unregister_command (cmd_linux); -+ grub_unregister_command (cmd_initrd); -+} -diff --git a/include/grub/emu/exec.h b/include/grub/emu/exec.h -index d1073ef86af..1b61b4a2e5d 100644 ---- a/include/grub/emu/exec.h -+++ b/include/grub/emu/exec.h -@@ -23,6 +23,8 @@ - #include - - #include -+#include -+ - pid_t - grub_util_exec_pipe (const char *const *argv, int *fd); - pid_t -@@ -32,7 +34,7 @@ int - grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file, - const char *stdout_file, const char *stderr_file); - int --grub_util_exec (const char *const *argv); -+EXPORT_FUNC(grub_util_exec) (const char *const *argv); - int - grub_util_exec_redirect (const char *const *argv, const char *stdin_file, - const char *stdout_file); -diff --git a/include/grub/emu/hostfile.h b/include/grub/emu/hostfile.h -index cfb1e2b5661..a61568e36e9 100644 ---- a/include/grub/emu/hostfile.h -+++ b/include/grub/emu/hostfile.h -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - - int -@@ -29,7 +30,7 @@ grub_util_is_directory (const char *path); - int - grub_util_is_special_file (const char *path); - int --grub_util_is_regular (const char *path); -+EXPORT_FUNC(grub_util_is_regular) (const char *path); - - char * - grub_util_path_concat (size_t n, ...); -diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h -index ff9c48a6490..01056954b96 100644 ---- a/include/grub/emu/misc.h -+++ b/include/grub/emu/misc.h -@@ -57,6 +57,9 @@ void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format ( - void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); - void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2), noreturn)); - -+void EXPORT_FUNC(grub_util_set_kexecute) (void); -+int EXPORT_FUNC(grub_util_get_kexecute) (void) WARN_UNUSED_RESULT; -+ - grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void); - - #ifdef HAVE_DEVICE_MAPPER -diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index ee88e44e97a..80e7a83edf9 100644 ---- a/grub-core/Makefile.am -+++ b/grub-core/Makefile.am -@@ -307,6 +307,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/exec.h - if COND_GRUB_EMU_SDL - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h - endif diff --git a/SOURCES/0076-efinet-Setting-network-from-UEFI-device-path.patch b/SOURCES/0076-efinet-Setting-network-from-UEFI-device-path.patch new file mode 100644 index 0000000..f4faf27 --- /dev/null +++ b/SOURCES/0076-efinet-Setting-network-from-UEFI-device-path.patch @@ -0,0 +1,405 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Sun, 10 Jul 2016 23:46:31 +0800 +Subject: [PATCH] efinet: Setting network from UEFI device path + +The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no +longer provided for HTTP Boot. Instead, we have to get the HTTP boot +information from the device path nodes defined in following UEFI Specification +sections. + + 9.3.5.12 IPv4 Device Path + 9.3.5.13 IPv6 Device Path + 9.3.5.23 Uniform Resource Identifiers (URI) Device Path + +This patch basically does: + +include/grub/efi/api.h: +Add new structure of Uniform Resource Identifiers (URI) Device Path + +grub-core/net/drivers/efi/efinet.c: +Check if PXE Base Code is available, if not it will try to obtain the netboot +information from the device path where the image booted from. The DHCPACK +packet is recoverd from the information in device patch and feed into the same +DHCP packet processing functions to ensure the network interface is setting up +the same way it used to be. + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +--- + grub-core/net/drivers/efi/efinet.c | 284 +++++++++++++++++++++++++++++++++++-- + include/grub/efi/api.h | 11 ++ + 2 files changed, 280 insertions(+), 15 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 014e5bf980..8171ecaa5e 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -331,6 +332,227 @@ grub_efinet_findcards (void) + grub_free (handles); + } + ++static struct grub_net_buff * ++grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6) ++{ ++ grub_efi_uint16_t uri_len; ++ grub_efi_device_path_t *ldp, *ddp; ++ grub_efi_uri_device_path_t *uri_dp; ++ struct grub_net_buff *nb; ++ grub_err_t err; ++ ++ ddp = grub_efi_duplicate_device_path (dp); ++ if (!ddp) ++ return NULL; ++ ++ ldp = grub_efi_find_last_device_path (ddp); ++ ++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0; ++ ++ if (!uri_len) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ uri_dp = (grub_efi_uri_device_path_t *) ldp; ++ ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ ++ ldp = grub_efi_find_last_device_path (ddp); ++ ++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ nb = grub_netbuff_alloc (512); ++ if (!nb) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp; ++ struct grub_net_bootp_packet *bp; ++ grub_uint8_t *ptr; ++ ++ bp = (struct grub_net_bootp_packet *) nb->tail; ++ err = grub_netbuff_put (nb, sizeof (*bp) + 4); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ ++ if (sizeof(bp->boot_file) < uri_len) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ grub_memcpy (bp->boot_file, uri_dp->uri, uri_len); ++ grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip)); ++ grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip)); ++ ++ bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0; ++ bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1; ++ bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2; ++ bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3; ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *ptr++ = GRUB_NET_BOOTP_NETMASK; ++ *ptr++ = sizeof (ipv4->subnet_mask); ++ grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask)); ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *ptr++ = GRUB_NET_BOOTP_ROUTER; ++ *ptr++ = sizeof (ipv4->gateway_ip_address); ++ grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address)); ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER; ++ *ptr++ = sizeof ("HTTPClient") - 1; ++ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1); ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, 1); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *ptr = GRUB_NET_BOOTP_END; ++ *use_ipv6 = 0; ++ ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ ldp = grub_efi_find_last_device_path (ddp); ++ ++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp; ++ bp->hw_type = mac->if_type; ++ bp->hw_len = sizeof (bp->mac_addr); ++ grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len); ++ } ++ } ++ else ++ { ++ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp; ++ ++ struct grub_net_dhcp6_packet *d6p; ++ struct grub_net_dhcp6_option *opt; ++ struct grub_net_dhcp6_option_iana *iana; ++ struct grub_net_dhcp6_option_iaaddr *iaaddr; ++ ++ d6p = (struct grub_net_dhcp6_packet *)nb->tail; ++ err = grub_netbuff_put (nb, sizeof(*d6p)); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ d6p->message_type = GRUB_NET_DHCP6_REPLY; ++ ++ opt = (struct grub_net_dhcp6_option *)nb->tail; ++ err = grub_netbuff_put (nb, sizeof(*opt)); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); ++ opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr)); ++ ++ err = grub_netbuff_put (nb, sizeof(*iana)); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ ++ opt = (struct grub_net_dhcp6_option *)nb->tail; ++ err = grub_netbuff_put (nb, sizeof(*opt)); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR); ++ opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr)); ++ ++ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail; ++ err = grub_netbuff_put (nb, sizeof(*iaaddr)); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address)); ++ ++ opt = (struct grub_net_dhcp6_option *)nb->tail; ++ err = grub_netbuff_put (nb, sizeof(*opt) + uri_len); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL); ++ opt->len = grub_cpu_to_be16 (uri_len); ++ grub_memcpy (opt->data, uri_dp->uri, uri_len); ++ ++ *use_ipv6 = 1; ++ } ++ ++ grub_free (ddp); ++ return nb; ++} ++ + static void + grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + char **path) +@@ -346,7 +568,11 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + { + grub_efi_device_path_t *cdp; + struct grub_efi_pxe *pxe; +- struct grub_efi_pxe_mode *pxe_mode; ++ struct grub_efi_pxe_mode *pxe_mode = NULL; ++ grub_uint8_t *packet_buf; ++ grub_size_t packet_bufsz ; ++ int ipv6; ++ struct grub_net_buff *nb = NULL; + + if (card->driver != &efidriver) + continue; +@@ -370,11 +596,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + */ + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE +- && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) + continue; + dup_dp = grub_efi_duplicate_device_path (dp); + if (!dup_dp) + continue; ++ ++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) ++ { ++ dup_ldp = grub_efi_find_last_device_path (dup_dp); ++ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ dup_ldp->length = sizeof (*dup_ldp); ++ } ++ + dup_ldp = grub_efi_find_last_device_path (dup_dp); + dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; +@@ -387,23 +623,37 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + + pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); +- if (! pxe) +- continue; ++ if (!pxe) ++ { ++ nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6); ++ if (!nb) ++ { ++ grub_print_error (); ++ continue; ++ } ++ packet_buf = nb->head; ++ packet_bufsz = nb->tail - nb->head; ++ } ++ else ++ { ++ pxe_mode = pxe->mode; ++ packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack; ++ packet_bufsz = sizeof (pxe_mode->dhcp_ack); ++ ipv6 = pxe_mode->using_ipv6; ++ } + +- pxe_mode = pxe->mode; +- if (pxe_mode->using_ipv6) ++ if (ipv6) + { + grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); +- grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", +- pxe_mode->dhcp_ack_received ? "yes" : "no", +- pxe_mode->dhcp_ack_received ? "" : " cannot continue"); +- if (!pxe_mode->dhcp_ack_received) +- continue; ++ if (pxe_mode) ++ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", ++ pxe_mode->dhcp_ack_received ? "yes" : "no", ++ pxe_mode->dhcp_ack_received ? "" : " cannot continue"); + + grub_net_configure_by_dhcpv6_reply (card->name, card, 0, + (struct grub_net_dhcp6_packet *) +- &pxe_mode->dhcp_ack, +- sizeof (pxe_mode->dhcp_ack), ++ packet_buf, ++ packet_bufsz, + 1, device, path); + if (grub_errno) + grub_print_error (); +@@ -417,11 +667,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + grub_dprintf ("efinet", "using ipv4 and dhcp\n"); + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) +- &pxe_mode->dhcp_ack, +- sizeof (pxe_mode->dhcp_ack), ++ packet_buf, ++ packet_bufsz, + 1, device, path); + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } ++ ++ if (nb) ++ grub_netbuff_free (nb); ++ + return; + } + } +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 91ab528e4d..4a51667adb 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -864,6 +864,8 @@ struct grub_efi_ipv4_device_path + grub_efi_uint16_t remote_port; + grub_efi_uint16_t protocol; + grub_efi_uint8_t static_ip_address; ++ grub_efi_ipv4_address_t gateway_ip_address; ++ grub_efi_ipv4_address_t subnet_mask; + } GRUB_PACKED; + typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t; + +@@ -918,6 +920,15 @@ struct grub_efi_sata_device_path + } GRUB_PACKED; + typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t; + ++#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24 ++ ++struct grub_efi_uri_device_path ++{ ++ grub_efi_device_path_t header; ++ grub_efi_uint8_t uri[0]; ++} GRUB_PACKED; ++typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t; ++ + #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 + + /* Media Device Path. */ diff --git a/SOURCES/0077-Add-grub2-switch-to-blscfg.patch b/SOURCES/0077-Add-grub2-switch-to-blscfg.patch deleted file mode 100644 index ce40e90..0000000 --- a/SOURCES/0077-Add-grub2-switch-to-blscfg.patch +++ /dev/null @@ -1,410 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 15 Mar 2018 14:12:40 -0400 -Subject: [PATCH] Add grub2-switch-to-blscfg - -Signed-off-by: Peter Jones -Signed-off-by: Javier Martinez Canillas -[jhlavac: Use ${etcdefaultgrub} instead of /etc/default/grub] -Signed-off-by: Jan Hlavac ---- - Makefile.util.def | 7 + - util/grub-set-password.in | 2 +- - util/grub-switch-to-blscfg.8 | 33 +++++ - util/grub-switch-to-blscfg.in | 317 ++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 358 insertions(+), 1 deletion(-) - create mode 100644 util/grub-switch-to-blscfg.8 - create mode 100644 util/grub-switch-to-blscfg.in - -diff --git a/Makefile.util.def b/Makefile.util.def -index cdd2f51fe4b..afc4d7b0c3e 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -1364,6 +1364,13 @@ program = { - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - }; - -+script = { -+ name = grub-switch-to-blscfg; -+ common = util/grub-switch-to-blscfg.in; -+ mansection = 8; -+ installdir = sbin; -+}; -+ - program = { - name = grub-glue-efi; - mansection = 1; -diff --git a/util/grub-set-password.in b/util/grub-set-password.in -index 5ebf50576d6..c0b5ebbfdc5 100644 ---- a/util/grub-set-password.in -+++ b/util/grub-set-password.in -@@ -1,6 +1,6 @@ - #!/bin/sh -e - --EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/') -+EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') - if [ -d /sys/firmware/efi/efivars/ ]; then - grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` - else -diff --git a/util/grub-switch-to-blscfg.8 b/util/grub-switch-to-blscfg.8 -new file mode 100644 -index 00000000000..9a886282976 ---- /dev/null -+++ b/util/grub-switch-to-blscfg.8 -@@ -0,0 +1,33 @@ -+.TH GRUB-SWITCH-TO-BLSCFG 1 "Wed Feb 26 2014" -+.SH NAME -+\fBgrub-switch-to-blscfg\fR \(em Switch to using BLS config files. -+ -+.SH SYNOPSIS -+\fBgrub-switch-to-blscfg\fR [--grub-directory=\fIDIR\fR] [--config-file=\fIFILE\fR] [--grub-defaults=\fIFILE\fR] -+ -+.SH DESCRIPTION -+\fBgrub-switch-to-blscfg\fR reconfigures grub-mkconfig to use BLS-style config files, and then regenerates the GRUB configuration. -+ -+.SH OPTIONS -+.TP -+--grub-directory=\fIDIR\fR -+Search for grub.cfg under \fIDIR\fR. The default value is \fI/boot/efi/EFI/\fBVENDOR\fR on UEFI machines and \fI/boot/grub2\fR elsewhere. -+ -+.TP -+--config-file=\fIFILE\fR -+The grub config file to use. The default value is \fI/etc/grub2-efi.cfg\fR on UEFI machines and \fI/etc/grub2.cfg\fR elsewhere. Symbolic links will be followed. -+ -+.TP -+--grub-defaults=\fIFILE\fR -+The defaults file for grub-mkconfig. The default value is \fI/etc/default/grub\fR. -+ -+.TP -+--bls-directory=\fIDIR\fR -+Create BootLoaderSpec fragments in \fIDIR\fR. The default value is \fI/boot/loader/entries\fR. -+ -+.TP -+--backup-suffix=\fSUFFIX\fR -+The suffix to use for saved backup files. The default value is \fI.bak\fR. -+ -+.SH SEE ALSO -+.BR "info grub" -diff --git a/util/grub-switch-to-blscfg.in b/util/grub-switch-to-blscfg.in -new file mode 100644 -index 00000000000..a851424beb2 ---- /dev/null -+++ b/util/grub-switch-to-blscfg.in -@@ -0,0 +1,317 @@ -+#! /bin/sh -+# -+# Set a default boot entry for GRUB. -+# Copyright (C) 2004,2009 Free Software Foundation, Inc. -+# -+# GRUB is free software: you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation, either version 3 of the License, or -+# (at your option) any later version. -+# -+# GRUB is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with GRUB. If not, see . -+ -+#set -eu -+ -+# Initialize some variables. -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+sbindir=@sbindir@ -+bindir=@bindir@ -+sysconfdir="@sysconfdir@" -+PACKAGE_NAME=@PACKAGE_NAME@ -+PACKAGE_VERSION=@PACKAGE_VERSION@ -+datarootdir="@datarootdir@" -+datadir="@datadir@" -+if [ ! -v pkgdatadir ]; then -+ pkgdatadir="${datadir}/@PACKAGE@" -+fi -+ -+self=`basename $0` -+ -+grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@" -+grub_editenv=${bindir}/@grub_editenv@ -+etcdefaultgrub=/etc/default/grub -+ -+eval "$("${grub_get_kernel_settings}")" || true -+ -+EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') -+if [ -d /sys/firmware/efi/efivars/ ]; then -+ startlink=/etc/grub2-efi.cfg -+ grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` -+else -+ startlink=/etc/grub2.cfg -+ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` -+fi -+ -+blsdir=`echo "/@bootdirname@/loader/entries" | sed 's,//*,/,g'` -+ -+backupsuffix=.bak -+ -+arch="$(uname -m)" -+ -+export TEXTDOMAIN=@PACKAGE@ -+export TEXTDOMAINDIR="@localedir@" -+ -+. "${pkgdatadir}/grub-mkconfig_lib" -+ -+# Usage: usage -+# Print the usage. -+usage () { -+ gettext_printf "Usage: %s\n" "$self" -+ gettext "Switch to BLS config files.\n"; echo -+ echo -+ print_option_help "-h, --help" "$(gettext "print this message and exit")" -+ print_option_help "-V, --version" "$(gettext "print the version information and exit")" -+ echo -+ print_option_help "--backup-suffix=$(gettext "SUFFIX")" "$backupsuffix" -+ print_option_help "--bls-directory=$(gettext "DIR")" "$blsdir" -+ print_option_help "--config-file=$(gettext "FILE")" "$startlink" -+ print_option_help "--grub-defaults=$(gettext "FILE")" "$etcdefaultgrub" -+ print_option_help "--grub-directory=$(gettext "DIR")" "$grubdir" -+ # echo -+ # gettext "Report bugs to ."; echo -+} -+ -+argument () { -+ opt=$1 -+ shift -+ -+ if test $# -eq 0; then -+ gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2 -+ exit 1 -+ fi -+ echo $1 -+} -+ -+# Check the arguments. -+while test $# -gt 0 -+do -+ option=$1 -+ shift -+ -+ case "$option" in -+ -h | --help) -+ usage -+ exit 0 ;; -+ -V | --version) -+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" -+ exit 0 ;; -+ -+ --backup-suffix) -+ backupsuffix=`argument $option "$@"` -+ shift -+ ;; -+ --backup-suffix=*) -+ backupsuffix=`echo "$option" | sed 's/--backup-suffix=//'` -+ ;; -+ -+ --bls-directory) -+ blsdir=`argument $option "$@"` -+ shift -+ ;; -+ --bls-directory=*) -+ blsdir=`echo "$option" | sed 's/--bls-directory=//'` -+ ;; -+ -+ --config-file) -+ startlink=`argument $option "$@"` -+ shift -+ ;; -+ --config-file=*) -+ startlink=`echo "$option" | sed 's/--config-file=//'` -+ ;; -+ -+ --grub-defaults) -+ etcdefaultgrub=`argument $option "$@"` -+ shift -+ ;; -+ --grub-defaults=*) -+ etcdefaultgrub=`echo "$option" | sed 's/--grub-defaults=//'` -+ ;; -+ -+ --grub-directory) -+ grubdir=`argument $option "$@"` -+ shift -+ ;; -+ --grub-directory=*) -+ grubdir=`echo "$option" | sed 's/--grub-directory=//'` -+ ;; -+ -+ *) -+ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 -+ usage -+ exit 1 -+ ;; -+ esac -+done -+ -+find_grub_cfg() { -+ local candidate="" -+ while [ -e "${candidate}" -o $# -gt 0 ] -+ do -+ if [ ! -e "${candidate}" ] ; then -+ candidate="$1" -+ shift -+ fi -+ -+ if [ -L "${candidate}" ]; then -+ candidate="$(realpath "${candidate}")" -+ fi -+ -+ if [ -f "${candidate}" ]; then -+ export GRUB_CONFIG_FILE="${candidate}" -+ return 0 -+ fi -+ done -+ return 1 -+} -+ -+if ! find_grub_cfg ${startlink} ${grubdir}/grub.cfg ; then -+ gettext_printf "Couldn't find config file\n" 1>&2 -+ exit 1 -+fi -+ -+if [ ! -d "${blsdir}" ]; then -+ install -m 700 -d "${blsdir}" -+fi -+ -+if [ -f /etc/machine-id ]; then -+ MACHINE_ID=$(cat /etc/machine-id) -+else -+ MACHINE_ID=$(dmesg | sha256sum) -+fi -+ -+mkbls() { -+ local kernelver=$1 && shift -+ local datetime=$1 && shift -+ local kernelopts=$1 && shift -+ -+ local debugname="" -+ local debugid="" -+ local flavor="" -+ -+ if [ "$kernelver" == *\+* ] ; then -+ local flavor=-"${kernelver##*+}" -+ if [ "${flavor}" == "-debug" ]; then -+ local debugname=" with debugging" -+ local debugid="-debug" -+ fi -+ fi -+ ( -+ source /etc/os-release -+ -+ cat <"${bls_target}" -+ -+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then -+ bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")" -+ cp -aT "${bls_target}" "${bls_debug}" -+ title="$(grep '^title[ \t]' "${bls_debug}" | sed -e 's/^title[ \t]*//')" -+ options="$(echo "${cmdline} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')" -+ sed -i -e "s/^title.*/title ${title}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${bls_debug}" -+ sed -i -e "s/^options.*/options ${options}/" "${bls_debug}" -+ fi -+ done -+ -+ if [ -f "/boot/vmlinuz-0-rescue-${MACHINE_ID}" ]; then -+ mkbls "0-rescue-${MACHINE_ID}" "0" "${bootprefix}" >"${blsdir}/${MACHINE_ID}-0-rescue.conf" -+ fi -+} -+ -+# The grub2 EFI binary is not copied to the ESP as a part of an ostree -+# transaction. Make sure a grub2 version with BLS support is installed -+# but only do this if the blsdir is not set, to make sure that the BLS -+# parsing module will search for the BLS snippets in the default path. -+if test -f /run/ostree-booted && test -d /sys/firmware/efi/efivars && \ -+ ! ${grub_editenv} - list | grep -q blsdir && \ -+ mountpoint -q /boot; then -+ grub_binary="$(find /usr/lib/ostree-boot/efi/EFI/${EFIDIR}/ -name grub*.efi)" -+ install -m 700 ${grub_binary} ${grubdir} || exit 1 -+ # Create a hidden file to indicate that grub2 now has BLS support. -+ touch /boot/grub2/.grub2-blscfg-supported -+fi -+ -+GENERATE=0 -+if grep '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" \ -+ | grep -vq '^GRUB_ENABLE_BLSCFG="*true"*\s*$' ; then -+ if ! sed -i"${backupsuffix}" \ -+ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=true,' \ -+ "${etcdefaultgrub}" ; then -+ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}" -+ exit 1 -+ fi -+ GENERATE=1 -+elif ! grep -q '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" ; then -+ if ! echo 'GRUB_ENABLE_BLSCFG=true' >> "${etcdefaultgrub}" ; then -+ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}" -+ exit 1 -+ fi -+ GENERATE=1 -+fi -+ -+if [ "${GENERATE}" -eq 1 ] ; then -+ copy_bls -+ -+ if [ $arch = "x86_64" ] && [ ! -d /sys/firmware/efi ]; then -+ mod_dir="i386-pc" -+ elif [ $arch = "ppc64" -o $arch = "ppc64le" ] && [ ! -d /sys/firmware/opal ]; then -+ mod_dir="powerpc-ieee1275" -+ fi -+ -+ if [ -n "${mod_dir}" ]; then -+ for mod in blscfg increment; do -+ install -m 700 ${prefix}/lib/grub/${mod_dir}/${mod}.mod ${grubdir}/$mod_dir/ || exit 1 -+ done -+ fi -+ -+ cp -af "${GRUB_CONFIG_FILE}" "${GRUB_CONFIG_FILE}${backupsuffix}" -+ if ! grub2-mkconfig -o "${GRUB_CONFIG_FILE}" ; then -+ install -m 700 "${GRUB_CONFIG_FILE}${backupsuffix}" "${GRUB_CONFIG_FILE}" -+ sed -i"${backupsuffix}" \ -+ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=false,' \ -+ "${etcdefaultgrub}" -+ gettext_printf "Updating %s failed\n" "${GRUB_CONFIG_FILE}" -+ exit 1 -+ fi -+fi -+ -+# Bye. -+exit 0 diff --git a/SOURCES/0077-efinet-Setting-DNS-server-from-UEFI-protocol.patch b/SOURCES/0077-efinet-Setting-DNS-server-from-UEFI-protocol.patch new file mode 100644 index 0000000..2d92ff0 --- /dev/null +++ b/SOURCES/0077-efinet-Setting-DNS-server-from-UEFI-protocol.patch @@ -0,0 +1,336 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 14 Jul 2016 17:48:45 +0800 +Subject: [PATCH] efinet: Setting DNS server from UEFI protocol + +In the URI device path node, any name rahter than address can be used for +looking up the resources so that DNS service become needed to get answer of the +name's address. Unfortunately the DNS is not defined in any of the device path +nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL +to obtain it. + +These two protcols are defined the sections of UEFI specification. + + 27.5 EFI IPv4 Configuration II Protocol + 27.7 EFI IPv6 Configuration Protocol + +include/grub/efi/api.h: +Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and +EFI_IP6_CONFIG_PROTOCOL. + +grub-core/net/drivers/efi/efinet.c: +Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list +of DNS server address for IPv4 and IPv6 respectively. The address of DNS +servers is structured into DHCPACK packet and feed into the same DHCP packet +processing functions to ensure the network interface is setting up the same way +it used to be. + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +--- + grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++ + include/grub/efi/api.h | 75 +++++++++++++++++ + 2 files changed, 238 insertions(+) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 8171ecaa5e..715a6168d7 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -33,6 +33,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + /* GUID. */ + static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; + static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; ++static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID; ++static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID; + + static grub_err_t + send_card_buffer (struct grub_net_card *dev, +@@ -332,6 +334,125 @@ grub_efinet_findcards (void) + grub_free (handles); + } + ++static grub_efi_handle_t ++grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path, ++ grub_efi_device_path_t **r_device_path) ++{ ++ grub_efi_handle_t handle; ++ grub_efi_status_t status; ++ ++ status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path, ++ protocol, &device_path, &handle); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ ++ if (r_device_path) ++ *r_device_path = device_path; ++ ++ return handle; ++} ++ ++static grub_efi_ipv4_address_t * ++grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns) ++{ ++ grub_efi_handle_t hnd; ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_protocol_t *conf; ++ grub_efi_ipv4_address_t *addrs; ++ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t); ++ ++ hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL); ++ ++ if (!hnd) ++ return 0; ++ ++ conf = grub_efi_open_protocol (hnd, &ip4_config_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!conf) ++ return 0; ++ ++ addrs = grub_malloc (data_size); ++ if (!addrs) ++ return 0; ++ ++ status = efi_call_4 (conf->get_data, conf, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, ++ &data_size, addrs); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ grub_free (addrs); ++ addrs = grub_malloc (data_size); ++ if (!addrs) ++ return 0; ++ ++ status = efi_call_4 (conf->get_data, conf, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, ++ &data_size, addrs); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (addrs); ++ return 0; ++ } ++ ++ *num_dns = data_size / sizeof (grub_efi_ipv4_address_t); ++ return addrs; ++} ++ ++static grub_efi_ipv6_address_t * ++grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns) ++{ ++ grub_efi_handle_t hnd; ++ grub_efi_status_t status; ++ grub_efi_ip6_config_protocol_t *conf; ++ grub_efi_ipv6_address_t *addrs; ++ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t); ++ ++ hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL); ++ ++ if (!hnd) ++ return 0; ++ ++ conf = grub_efi_open_protocol (hnd, &ip6_config_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!conf) ++ return 0; ++ ++ addrs = grub_malloc (data_size); ++ if (!addrs) ++ return 0; ++ ++ status = efi_call_4 (conf->get_data, conf, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, ++ &data_size, addrs); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ grub_free (addrs); ++ addrs = grub_malloc (data_size); ++ if (!addrs) ++ return 0; ++ ++ status = efi_call_4 (conf->get_data, conf, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, ++ &data_size, addrs); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (addrs); ++ return 0; ++ } ++ ++ *num_dns = data_size / sizeof (grub_efi_ipv6_address_t); ++ return addrs; ++} ++ + static struct grub_net_buff * + grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6) + { +@@ -390,6 +511,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u + grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp; + struct grub_net_bootp_packet *bp; + grub_uint8_t *ptr; ++ grub_efi_ipv4_address_t *dns; ++ grub_efi_uintn_t num_dns; + + bp = (struct grub_net_bootp_packet *) nb->tail; + err = grub_netbuff_put (nb, sizeof (*bp) + 4); +@@ -451,6 +574,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u + *ptr++ = sizeof ("HTTPClient") - 1; + grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1); + ++ dns = grub_dns_server_ip4_address (dp, &num_dns); ++ if (dns) ++ { ++ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns; ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, size_dns + 2); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *ptr++ = GRUB_NET_BOOTP_DNS; ++ *ptr++ = size_dns; ++ grub_memcpy (ptr, dns, size_dns); ++ grub_free (dns); ++ } ++ + ptr = nb->tail; + err = grub_netbuff_put (nb, 1); + if (err) +@@ -483,6 +625,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u + struct grub_net_dhcp6_option *opt; + struct grub_net_dhcp6_option_iana *iana; + struct grub_net_dhcp6_option_iaaddr *iaaddr; ++ grub_efi_ipv6_address_t *dns; ++ grub_efi_uintn_t num_dns; + + d6p = (struct grub_net_dhcp6_packet *)nb->tail; + err = grub_netbuff_put (nb, sizeof(*d6p)); +@@ -546,6 +690,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u + opt->len = grub_cpu_to_be16 (uri_len); + grub_memcpy (opt->data, uri_dp->uri, uri_len); + ++ dns = grub_dns_server_ip6_address (dp, &num_dns); ++ if (dns) ++ { ++ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns; ++ ++ opt = (struct grub_net_dhcp6_option *)nb->tail; ++ err = grub_netbuff_put (nb, sizeof(*opt) + size_dns); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS); ++ opt->len = grub_cpu_to_be16 (size_dns); ++ grub_memcpy (opt->data, dns, size_dns); ++ grub_free (dns); ++ } ++ + *use_ipv6 = 1; + } + +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 4a51667adb..0b490195ad 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -352,6 +352,15 @@ + #define GRUB_EFI_RNG_PROTOCOL_GUID \ + { 0x3152bca5, 0xeade, 0x433d, \ + { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \ ++ ++#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \ ++ { 0x5b446ed1, 0xe30b, 0x4faa, \ ++ { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \ ++ } ++ ++#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \ ++ { 0x937fe521, 0x95ae, 0x4d1a, \ ++ { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ + } + + struct grub_efi_sal_system_table +@@ -1883,6 +1892,72 @@ struct grub_efi_rng_protocol + }; + typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t; + ++enum grub_efi_ip4_config2_data_type { ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM ++}; ++typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t; ++ ++struct grub_efi_ip4_config2_protocol ++{ ++ grub_efi_status_t (*set_data) (struct grub_efi_ip4_config2_protocol *this, ++ grub_efi_ip4_config2_data_type_t data_type, ++ grub_efi_uintn_t data_size, ++ void *data); ++ ++ grub_efi_status_t (*get_data) (struct grub_efi_ip4_config2_protocol *this, ++ grub_efi_ip4_config2_data_type_t data_type, ++ grub_efi_uintn_t *data_size, ++ void *data); ++ ++ grub_efi_status_t (*register_data_notify) (struct grub_efi_ip4_config2_protocol *this, ++ grub_efi_ip4_config2_data_type_t data_type, ++ grub_efi_event_t event); ++ ++ grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this, ++ grub_efi_ip4_config2_data_type_t data_type, ++ grub_efi_event_t event); ++}; ++typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t; ++ ++enum grub_efi_ip6_config_data_type { ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM ++}; ++typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t; ++ ++struct grub_efi_ip6_config_protocol ++{ ++ grub_efi_status_t (*set_data) (struct grub_efi_ip6_config_protocol *this, ++ grub_efi_ip6_config_data_type_t data_type, ++ grub_efi_uintn_t data_size, ++ void *data); ++ ++ grub_efi_status_t (*get_data) (struct grub_efi_ip6_config_protocol *this, ++ grub_efi_ip6_config_data_type_t data_type, ++ grub_efi_uintn_t *data_size, ++ void *data); ++ ++ grub_efi_status_t (*register_data_notify) (struct grub_efi_ip6_config_protocol *this, ++ grub_efi_ip6_config_data_type_t data_type, ++ grub_efi_event_t event); ++ ++ grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip6_config_protocol *this, ++ grub_efi_ip6_config_data_type_t data_type, ++ grub_efi_event_t event); ++}; ++typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t; ++ + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ + || defined(__riscv) diff --git a/SOURCES/0078-Support-UEFI-networking-protocols.patch b/SOURCES/0078-Support-UEFI-networking-protocols.patch new file mode 100644 index 0000000..145becf --- /dev/null +++ b/SOURCES/0078-Support-UEFI-networking-protocols.patch @@ -0,0 +1,5053 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 22 Feb 2017 14:27:50 +0800 +Subject: [PATCH] Support UEFI networking protocols + +References: fate#320130, bsc#1015589, bsc#1076132 +Patch-Mainline: no + +V1: + * Add preliminary support of UEFI networking protocols + * Support UEFI HTTPS Boot + +V2: + * Workaround http data access in firmware + * Fix DNS device path parsing for efinet device + * Relaxed UEFI Protocol requirement + * Support Intel OPA (Omni-Path Architecture) PXE Boot + +V3: + * Fix bufio in calculating address of next_buf + * Check HTTP respond code + * Use HEAD request method to test before GET + * Finish HTTP transaction in one go + * Fix bsc#1076132 + +Signed-off-by: Michael Chang +[pjones: make efi_netfs not duplicate symbols from efinet] +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 12 + + grub-core/io/bufio.c | 2 +- + grub-core/kern/efi/efi.c | 96 ++- + grub-core/net/drivers/efi/efinet.c | 27 + + grub-core/net/efi/dhcp.c | 397 ++++++++++ + grub-core/net/efi/efi_netfs.c | 57 ++ + grub-core/net/efi/http.c | 419 +++++++++++ + grub-core/net/efi/ip4_config.c | 398 ++++++++++ + grub-core/net/efi/ip6_config.c | 422 +++++++++++ + grub-core/net/efi/net.c | 1428 ++++++++++++++++++++++++++++++++++++ + grub-core/net/efi/pxe.c | 424 +++++++++++ + grub-core/net/net.c | 74 ++ + util/grub-mknetdir.c | 23 +- + include/grub/efi/api.h | 180 ++++- + include/grub/efi/dhcp.h | 343 +++++++++ + include/grub/efi/http.h | 215 ++++++ + include/grub/net/efi.h | 144 ++++ + 17 files changed, 4620 insertions(+), 41 deletions(-) + create mode 100644 grub-core/net/efi/dhcp.c + create mode 100644 grub-core/net/efi/efi_netfs.c + create mode 100644 grub-core/net/efi/http.c + create mode 100644 grub-core/net/efi/ip4_config.c + create mode 100644 grub-core/net/efi/ip6_config.c + create mode 100644 grub-core/net/efi/net.c + create mode 100644 grub-core/net/efi/pxe.c + create mode 100644 include/grub/efi/dhcp.h + create mode 100644 include/grub/efi/http.h + create mode 100644 include/grub/net/efi.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 52ec0fafcd..12797336c9 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2300,6 +2300,12 @@ module = { + common = hook/datehook.c; + }; + ++module = { ++ name = efi_netfs; ++ common = net/efi/efi_netfs.c; ++ enable = efi; ++}; ++ + module = { + name = net; + common = net/net.c; +@@ -2313,6 +2319,12 @@ module = { + common = net/ethernet.c; + common = net/arp.c; + common = net/netbuff.c; ++ efi = net/efi/net.c; ++ efi = net/efi/http.c; ++ efi = net/efi/pxe.c; ++ efi = net/efi/ip4_config.c; ++ efi = net/efi/ip6_config.c; ++ efi = net/efi/dhcp.c; + }; + + module = { +diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c +index a458c3aca7..1637731535 100644 +--- a/grub-core/io/bufio.c ++++ b/grub-core/io/bufio.c +@@ -139,7 +139,7 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len) + return res; + + /* Need to read some more. */ +- next_buf = (file->offset + res + len - 1) & ~((grub_off_t) bufio->block_size - 1); ++ next_buf = (grub_divmod64 (file->offset + res + len - 1, bufio->block_size, NULL)) * bufio->block_size; + /* Now read between file->offset + res and bufio->buffer_at. */ + if (file->offset + res < next_buf) + { +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index d6a2fb5778..2a446f5031 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -755,7 +755,7 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) + { + grub_efi_ipv4_device_path_t *ipv4 + = (grub_efi_ipv4_device_path_t *) dp; +- grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)", ++ grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x", + (unsigned) ipv4->local_ip_address[0], + (unsigned) ipv4->local_ip_address[1], + (unsigned) ipv4->local_ip_address[2], +@@ -768,33 +768,60 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) + (unsigned) ipv4->remote_port, + (unsigned) ipv4->protocol, + (unsigned) ipv4->static_ip_address); ++ if (len == sizeof (*ipv4)) ++ { ++ grub_printf (",%u.%u.%u.%u,%u.%u.%u.%u", ++ (unsigned) ipv4->gateway_ip_address[0], ++ (unsigned) ipv4->gateway_ip_address[1], ++ (unsigned) ipv4->gateway_ip_address[2], ++ (unsigned) ipv4->gateway_ip_address[3], ++ (unsigned) ipv4->subnet_mask[0], ++ (unsigned) ipv4->subnet_mask[1], ++ (unsigned) ipv4->subnet_mask[2], ++ (unsigned) ipv4->subnet_mask[3]); ++ } ++ grub_printf (")"); + } + break; + case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE: + { + grub_efi_ipv6_device_path_t *ipv6 + = (grub_efi_ipv6_device_path_t *) dp; +- grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)", +- (unsigned) ipv6->local_ip_address[0], +- (unsigned) ipv6->local_ip_address[1], +- (unsigned) ipv6->local_ip_address[2], +- (unsigned) ipv6->local_ip_address[3], +- (unsigned) ipv6->local_ip_address[4], +- (unsigned) ipv6->local_ip_address[5], +- (unsigned) ipv6->local_ip_address[6], +- (unsigned) ipv6->local_ip_address[7], +- (unsigned) ipv6->remote_ip_address[0], +- (unsigned) ipv6->remote_ip_address[1], +- (unsigned) ipv6->remote_ip_address[2], +- (unsigned) ipv6->remote_ip_address[3], +- (unsigned) ipv6->remote_ip_address[4], +- (unsigned) ipv6->remote_ip_address[5], +- (unsigned) ipv6->remote_ip_address[6], +- (unsigned) ipv6->remote_ip_address[7], ++ grub_printf ("/IPv6(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%u,%u,%x,%x", ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[0]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[1]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[2]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[3]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[4]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[5]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[6]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[7]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[0]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[1]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[2]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[3]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[4]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[5]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[6]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[7]), + (unsigned) ipv6->local_port, + (unsigned) ipv6->remote_port, + (unsigned) ipv6->protocol, + (unsigned) ipv6->static_ip_address); ++ if (len == sizeof (*ipv6)) ++ { ++ grub_printf (",%u,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ++ (unsigned) ipv6->prefix_length, ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[0]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[1]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[2]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[3]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[4]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[5]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[6]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[7])); ++ } ++ grub_printf (")"); + } + break; + case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE: +@@ -834,6 +861,39 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) + dump_vendor_path ("Messaging", + (grub_efi_vendor_device_path_t *) dp); + break; ++ case GRUB_EFI_URI_DEVICE_PATH_SUBTYPE: ++ { ++ grub_efi_uri_device_path_t *uri ++ = (grub_efi_uri_device_path_t *) dp; ++ grub_printf ("/URI(%s)", uri->uri); ++ } ++ break; ++ case GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE: ++ { ++ grub_efi_dns_device_path_t *dns ++ = (grub_efi_dns_device_path_t *) dp; ++ if (dns->is_ipv6) ++ { ++ grub_printf ("/DNS(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)", ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0])), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1])), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2])), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]))); ++ } ++ else ++ { ++ grub_printf ("/DNS(%d.%d.%d.%d)", ++ dns->dns_server_ip[0].v4.addr[0], ++ dns->dns_server_ip[0].v4.addr[1], ++ dns->dns_server_ip[0].v4.addr[2], ++ dns->dns_server_ip[0].v4.addr[3]); ++ } ++ } ++ break; + default: + grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype); + break; +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 715a6168d7..e11d759f19 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -491,6 +492,17 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u + + ldp = grub_efi_find_last_device_path (ddp); + ++ /* Skip the DNS Device */ ++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE) ++ { ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ ++ ldp = grub_efi_find_last_device_path (ddp); ++ } ++ + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) +@@ -760,6 +772,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) + continue; + dup_dp = grub_efi_duplicate_device_path (dp); +@@ -774,6 +787,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + dup_ldp->length = sizeof (*dup_ldp); + } + ++ dup_ldp = grub_efi_find_last_device_path (dup_dp); ++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE) ++ { ++ dup_ldp = grub_efi_find_last_device_path (dup_dp); ++ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ dup_ldp->length = sizeof (*dup_ldp); ++ } ++ + dup_ldp = grub_efi_find_last_device_path (dup_dp); + dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; +@@ -845,6 +867,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + + GRUB_MOD_INIT(efinet) + { ++ if (grub_efi_net_config) ++ return; ++ + grub_efinet_findcards (); + grub_efi_net_config = grub_efi_net_config_real; + } +@@ -856,5 +881,7 @@ GRUB_MOD_FINI(efinet) + FOR_NET_CARDS_SAFE (card, next) + if (card->driver == &efidriver) + grub_net_card_unregister (card); ++ ++ grub_efi_net_config = NULL; + } + +diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c +new file mode 100644 +index 0000000000..dbef63d8c0 +--- /dev/null ++++ b/grub-core/net/efi/dhcp.c +@@ -0,0 +1,397 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef GRUB_EFI_NET_DEBUG ++static void ++dhcp4_mode_print (grub_efi_dhcp4_mode_data_t *mode) ++{ ++ switch (mode->state) ++ { ++ case GRUB_EFI_DHCP4_STOPPED: ++ grub_printf ("STATE: STOPPED\n"); ++ break; ++ case GRUB_EFI_DHCP4_INIT: ++ grub_printf ("STATE: INIT\n"); ++ break; ++ case GRUB_EFI_DHCP4_SELECTING: ++ grub_printf ("STATE: SELECTING\n"); ++ break; ++ case GRUB_EFI_DHCP4_REQUESTING: ++ grub_printf ("STATE: REQUESTING\n"); ++ break; ++ case GRUB_EFI_DHCP4_BOUND: ++ grub_printf ("STATE: BOUND\n"); ++ break; ++ case GRUB_EFI_DHCP4_RENEWING: ++ grub_printf ("STATE: RENEWING\n"); ++ break; ++ case GRUB_EFI_DHCP4_REBINDING: ++ grub_printf ("STATE: REBINDING\n"); ++ break; ++ case GRUB_EFI_DHCP4_INIT_REBOOT: ++ grub_printf ("STATE: INIT_REBOOT\n"); ++ break; ++ case GRUB_EFI_DHCP4_REBOOTING: ++ grub_printf ("STATE: REBOOTING\n"); ++ break; ++ default: ++ grub_printf ("STATE: UNKNOWN\n"); ++ break; ++ } ++ ++ grub_printf ("CLIENT_ADDRESS: %u.%u.%u.%u\n", ++ mode->client_address[0], ++ mode->client_address[1], ++ mode->client_address[2], ++ mode->client_address[3]); ++ grub_printf ("SERVER_ADDRESS: %u.%u.%u.%u\n", ++ mode->server_address[0], ++ mode->server_address[1], ++ mode->server_address[2], ++ mode->server_address[3]); ++ grub_printf ("SUBNET_MASK: %u.%u.%u.%u\n", ++ mode->subnet_mask[0], ++ mode->subnet_mask[1], ++ mode->subnet_mask[2], ++ mode->subnet_mask[3]); ++ grub_printf ("ROUTER_ADDRESS: %u.%u.%u.%u\n", ++ mode->router_address[0], ++ mode->router_address[1], ++ mode->router_address[2], ++ mode->router_address[3]); ++} ++#endif ++ ++static grub_efi_ipv4_address_t * ++grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packet_t *reply_packet) ++{ ++ grub_efi_dhcp4_packet_option_t **option_list; ++ grub_efi_status_t status; ++ grub_efi_uint32_t option_count = 0; ++ grub_efi_uint32_t i; ++ ++ status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, NULL); ++ ++ if (status != GRUB_EFI_BUFFER_TOO_SMALL) ++ return NULL; ++ ++ option_list = grub_malloc (option_count * sizeof(*option_list)); ++ if (!option_list) ++ return NULL; ++ ++ status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, option_list); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (option_list); ++ return NULL; ++ } ++ ++ for (i = 0; i < option_count; ++i) ++ { ++ if (option_list[i]->op_code == 6) ++ { ++ grub_efi_ipv4_address_t *dns_address; ++ ++ if (((option_list[i]->length & 0x3) != 0) || (option_list[i]->length == 0)) ++ continue; ++ ++ /* We only contact primary dns */ ++ dns_address = grub_malloc (sizeof (*dns_address)); ++ if (!dns_address) ++ { ++ grub_free (option_list); ++ return NULL; ++ } ++ grub_memcpy (dns_address, option_list[i]->data, sizeof (dns_address)); ++ grub_free (option_list); ++ return dns_address; ++ } ++ } ++ ++ grub_free (option_list); ++ return NULL; ++} ++ ++#if 0 ++/* Somehow this doesn't work ... */ ++static grub_err_t ++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_pxe_t *pxe = dev->ip4_pxe; ++ grub_efi_pxe_mode_t *mode = pxe->mode; ++ grub_efi_status_t status; ++ ++ if (!mode->started) ++ { ++ status = efi_call_2 (pxe->start, pxe, 0); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't start PXE\n"); ++ } ++ ++ status = efi_call_2 (pxe->dhcp, pxe, 0); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 configure failed, %d\n", (int)status); ++ continue; ++ } ++ ++ dev->prefer_ip6 = 0; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++#endif ++ ++static grub_err_t ++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, ++ char **args) ++{ ++ struct grub_efi_net_device *netdev; ++ ++ for (netdev = net_devices; netdev; netdev = netdev->next) ++ { ++ grub_efi_status_t status; ++ grub_efi_dhcp4_mode_data_t mode; ++ grub_efi_dhcp4_config_data_t config; ++ grub_efi_dhcp4_packet_option_t *options; ++ grub_efi_ipv4_address_t *dns_address; ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_net_ip_address_t ip_addr; ++ grub_efi_net_interface_t *inf = NULL; ++ ++ if (argc > 0 && grub_strcmp (netdev->card_name, args[0]) != 0) ++ continue; ++ ++ grub_memset (&config, 0, sizeof(config)); ++ ++ config.option_count = 1; ++ options = grub_malloc (sizeof(*options) + 2); ++ /* Parameter request list */ ++ options->op_code = 55; ++ options->length = 3; ++ /* subnet mask */ ++ options->data[0] = 1; ++ /* router */ ++ options->data[1] = 3; ++ /* DNS */ ++ options->data[2] = 6; ++ config.option_list = &options; ++ ++ /* FIXME: What if the dhcp has bounded */ ++ status = efi_call_2 (netdev->dhcp4->configure, netdev->dhcp4, &config); ++ grub_free (options); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 configure failed, %d\n", (int)status); ++ continue; ++ } ++ ++ status = efi_call_2 (netdev->dhcp4->start, netdev->dhcp4, NULL); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 start failed, %d\n", (int)status); ++ continue; ++ } ++ ++ status = efi_call_2 (netdev->dhcp4->get_mode_data, netdev->dhcp4, &mode); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 get mode failed, %d\n", (int)status); ++ continue; ++ } ++ ++#ifdef GRUB_EFI_NET_DEBUG ++ dhcp4_mode_print (&mode); ++#endif ++ ++ for (inf = netdev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6 == 0) ++ break; ++ ++ grub_memcpy (net_ip.ip4.address, mode.client_address, sizeof (net_ip.ip4.address)); ++ grub_memcpy (net_ip.ip4.subnet_mask, mode.subnet_mask, sizeof (net_ip.ip4.subnet_mask)); ++ ++ if (!inf) ++ { ++ char *name = grub_xasprintf ("%s:dhcp", netdev->card_name); ++ ++ net_ip.is_ip6 = 0; ++ inf = grub_efi_net_create_interface (netdev, ++ name, ++ &net_ip, ++ 1); ++ grub_free (name); ++ } ++ else ++ { ++ efi_net_interface_set_address (inf, &net_ip, 1); ++ } ++ ++ grub_memcpy (ip_addr.ip4, mode.router_address, sizeof (ip_addr.ip4)); ++ efi_net_interface_set_gateway (inf, &ip_addr); ++ ++ dns_address = grub_efi_dhcp4_parse_dns (netdev->dhcp4, mode.reply_packet); ++ if (dns_address) ++ efi_net_interface_set_dns (inf, (grub_efi_net_ip_address_t *)&dns_address); ++ ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++ ++static grub_err_t ++grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, ++ char **args) ++{ ++ struct grub_efi_net_device *dev; ++ grub_efi_uint32_t ia_id; ++ ++ for (dev = net_devices, ia_id = 0; dev; dev = dev->next, ia_id++) ++ { ++ grub_efi_dhcp6_config_data_t config; ++ grub_efi_dhcp6_packet_option_t *option_list[1]; ++ grub_efi_dhcp6_packet_option_t *opt; ++ grub_efi_status_t status; ++ grub_efi_dhcp6_mode_data_t mode; ++ grub_efi_dhcp6_retransmission_t retrans; ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; ++ grub_efi_net_interface_t *inf = NULL; ++ ++ if (argc > 0 && grub_strcmp (dev->card_name, args[0]) != 0) ++ continue; ++ ++ opt = grub_malloc (sizeof(*opt) + 2 * sizeof (grub_efi_uint16_t)); ++ ++#define GRUB_EFI_DHCP6_OPT_ORO 6 ++ ++ opt->op_code = grub_cpu_to_be16_compile_time (GRUB_EFI_DHCP6_OPT_ORO); ++ opt->op_len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_efi_uint16_t)); ++ ++#define GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL 59 ++#define GRUB_EFI_DHCP6_OPT_DNS_SERVERS 23 ++ ++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL)); ++ grub_set_unaligned16 (opt->data + 1 * sizeof (grub_efi_uint16_t), ++ grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS)); ++ ++ option_list[0] = opt; ++ retrans.irt = 4; ++ retrans.mrc = 4; ++ retrans.mrt = 32; ++ retrans.mrd = 60; ++ ++ config.dhcp6_callback = NULL; ++ config.callback_context = NULL; ++ config.option_count = 1; ++ config.option_list = option_list; ++ config.ia_descriptor.ia_id = ia_id; ++ config.ia_descriptor.type = GRUB_EFI_DHCP6_IA_TYPE_NA; ++ config.ia_info_event = NULL; ++ config.reconfigure_accept = 0; ++ config.rapid_commit = 0; ++ config.solicit_retransmission = &retrans; ++ ++ status = efi_call_2 (dev->dhcp6->configure, dev->dhcp6, &config); ++ grub_free (opt); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp6 configure failed, %d\n", (int)status); ++ continue; ++ } ++ status = efi_call_1 (dev->dhcp6->start, dev->dhcp6); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp6 start failed, %d\n", (int)status); ++ continue; ++ } ++ ++ status = efi_call_3 (dev->dhcp6->get_mode_data, dev->dhcp6, &mode, NULL); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 get mode failed, %d\n", (int)status); ++ continue; ++ } ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6 == 1) ++ break; ++ ++ grub_memcpy (net_ip.ip6.address, mode.ia->ia_address[0].ip_address, sizeof (net_ip.ip6.address)); ++ net_ip.ip6.prefix_length = 64; ++ net_ip.ip6.is_anycast = 0; ++ net_ip.is_ip6 = 1; ++ ++ if (!inf) ++ { ++ char *name = grub_xasprintf ("%s:dhcp", dev->card_name); ++ ++ inf = grub_efi_net_create_interface (dev, ++ name, ++ &net_ip, ++ 1); ++ grub_free (name); ++ } ++ else ++ { ++ efi_net_interface_set_address (inf, &net_ip, 1); ++ } ++ ++ { ++ grub_efi_uint32_t count = 0; ++ grub_efi_dhcp6_packet_option_t **options = NULL; ++ grub_efi_uint32_t i; ++ ++ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, NULL); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL && count) ++ { ++ options = grub_malloc (count * sizeof(*options)); ++ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (options) ++ grub_free (options); ++ continue; ++ } ++ ++ for (i = 0; i < count; ++i) ++ { ++ if (options[i]->op_code == grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS)) ++ { ++ grub_efi_net_ip_address_t dns; ++ grub_memcpy (dns.ip6, options[i]->data, sizeof(net_ip.ip6)); ++ efi_net_interface_set_dns (inf, &dns); ++ break; ++ } ++ } ++ ++ if (options) ++ grub_free (options); ++ } ++ ++ efi_call_1 (b->free_pool, mode.client_id); ++ efi_call_1 (b->free_pool, mode.ia); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_command_func_t grub_efi_net_bootp = grub_cmd_efi_bootp; ++grub_command_func_t grub_efi_net_bootp6 = grub_cmd_efi_bootp6; +diff --git a/grub-core/net/efi/efi_netfs.c b/grub-core/net/efi/efi_netfs.c +new file mode 100644 +index 0000000000..ef371d885e +--- /dev/null ++++ b/grub-core/net/efi/efi_netfs.c +@@ -0,0 +1,57 @@ ++#include ++#include ++#define EFI_NET_CMD_PREFIX "net_efi" ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_command_t cmd_efi_lsroutes; ++static grub_command_t cmd_efi_lscards; ++static grub_command_t cmd_efi_lsaddrs; ++static grub_command_t cmd_efi_addaddr; ++static grub_command_t cmd_efi_bootp; ++static grub_command_t cmd_efi_bootp6; ++ ++static int initialized; ++ ++GRUB_MOD_INIT(efi_netfs) ++{ ++ if (grub_net_open) ++ return; ++ ++ if (grub_efi_net_fs_init ()) ++ { ++ cmd_efi_lsroutes = grub_register_command ("net_efi_ls_routes", grub_efi_net_list_routes, ++ "", N_("list network routes")); ++ cmd_efi_lscards = grub_register_command ("net_efi_ls_cards", grub_efi_net_list_cards, ++ "", N_("list network cards")); ++ cmd_efi_lsaddrs = grub_register_command ("net_efi_ls_addr", grub_efi_net_list_addrs, ++ "", N_("list network addresses")); ++ cmd_efi_addaddr = grub_register_command ("net_efi_add_addr", grub_efi_net_add_addr, ++ N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), ++ N_("Add a network address.")); ++ cmd_efi_bootp = grub_register_command ("net_efi_bootp", grub_efi_net_bootp, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ cmd_efi_bootp6 = grub_register_command ("net_efi_bootp6", grub_efi_net_bootp6, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ initialized = 1; ++ } ++} ++ ++GRUB_MOD_FINI(efi_netfs) ++{ ++ if (initialized) ++ { ++ grub_unregister_command (cmd_efi_lsroutes); ++ grub_unregister_command (cmd_efi_lscards); ++ grub_unregister_command (cmd_efi_lsaddrs); ++ grub_unregister_command (cmd_efi_addaddr); ++ grub_unregister_command (cmd_efi_bootp); ++ grub_unregister_command (cmd_efi_bootp6); ++ grub_efi_net_fs_fini (); ++ initialized = 0; ++ return; ++ } ++} +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +new file mode 100644 +index 0000000000..3f61fd2fa5 +--- /dev/null ++++ b/grub-core/net/efi/http.c +@@ -0,0 +1,419 @@ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++http_configure (struct grub_efi_net_device *dev, int prefer_ip6) ++{ ++ grub_efi_http_config_data_t http_config; ++ grub_efi_httpv4_access_point_t httpv4_node; ++ grub_efi_httpv6_access_point_t httpv6_node; ++ grub_efi_status_t status; ++ ++ grub_efi_http_t *http = dev->http; ++ ++ grub_memset (&http_config, 0, sizeof(http_config)); ++ http_config.http_version = GRUB_EFI_HTTPVERSION11; ++ http_config.timeout_millisec = 5000; ++ ++ if (prefer_ip6) ++ { ++ grub_efi_uintn_t sz; ++ grub_efi_ip6_config_manual_address_t manual_address; ++ ++ http_config.local_address_is_ipv6 = 1; ++ sz = sizeof (manual_address); ++ status = efi_call_4 (dev->ip6_config->get_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, &manual_address); ++ ++ if (status == GRUB_EFI_NOT_FOUND) ++ { ++ grub_printf ("The MANUAL ADDRESS is not found\n"); ++ } ++ ++ /* FIXME: The manual interface would return BUFFER TOO SMALL !!! */ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("??? %d\n",(int) status); ++ return; ++ } ++ ++ grub_memcpy (httpv6_node.local_address, manual_address.address, sizeof (httpv6_node.local_address)); ++ httpv6_node.local_port = 0; ++ http_config.access_point.ipv6_node = &httpv6_node; ++ } ++ else ++ { ++ http_config.local_address_is_ipv6 = 0; ++ grub_memset (&httpv4_node, 0, sizeof(httpv4_node)); ++ httpv4_node.use_default_address = 1; ++ ++ /* Use random port here */ ++ /* See TcpBind() in edk2/NetworkPkg/TcpDxe/TcpDispatcher.c */ ++ httpv4_node.local_port = 0; ++ http_config.access_point.ipv4_node = &httpv4_node; ++ } ++ ++ status = efi_call_2 (http->configure, http, &http_config); ++ ++ if (status == GRUB_EFI_ALREADY_STARTED) ++ { ++ /* XXX: This hangs HTTPS boot */ ++#if 0 ++ if (efi_call_2 (http->configure, http, NULL) != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_IO, N_("couldn't reset http instance")); ++ grub_print_error (); ++ return; ++ } ++ status = efi_call_2 (http->configure, http, &http_config); ++#endif ++ return; ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_IO, N_("couldn't configure http protocol, reason: %d"), (int)status); ++ grub_print_error (); ++ return ; ++ } ++} ++ ++static grub_efi_boolean_t request_callback_done; ++static grub_efi_boolean_t response_callback_done; ++ ++static void ++grub_efi_http_request_callback (grub_efi_event_t event __attribute__ ((unused)), ++ void *context __attribute__ ((unused))) ++{ ++ request_callback_done = 1; ++} ++ ++static void ++grub_efi_http_response_callback (grub_efi_event_t event __attribute__ ((unused)), ++ void *context __attribute__ ((unused))) ++{ ++ response_callback_done = 1; ++} ++ ++static grub_err_t ++efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, int headeronly, grub_off_t *file_size) ++{ ++ grub_efi_http_request_data_t request_data; ++ grub_efi_http_message_t request_message; ++ grub_efi_http_token_t request_token; ++ grub_efi_http_response_data_t response_data; ++ grub_efi_http_message_t response_message; ++ grub_efi_http_token_t response_token; ++ grub_efi_http_header_t request_headers[3]; ++ ++ grub_efi_status_t status; ++ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; ++ char *url = NULL; ++ ++ request_headers[0].field_name = (grub_efi_char8_t *)"Host"; ++ request_headers[0].field_value = (grub_efi_char8_t *)server; ++ request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; ++ request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; ++ request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; ++ request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0"; ++ ++ { ++ grub_efi_ipv6_address_t address; ++ const char *rest; ++ grub_efi_char16_t *ucs2_url; ++ grub_size_t url_len, ucs2_url_len; ++ const char *protocol = (use_https == 1) ? "https" : "http"; ++ ++ if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0) ++ url = grub_xasprintf ("%s://[%s]%s", protocol, server, name); ++ else ++ url = grub_xasprintf ("%s://%s%s", protocol, server, name); ++ ++ if (!url) ++ { ++ return grub_errno; ++ } ++ ++ url_len = grub_strlen (url); ++ ucs2_url_len = url_len * GRUB_MAX_UTF16_PER_UTF8; ++ ucs2_url = grub_malloc ((ucs2_url_len + 1) * sizeof (ucs2_url[0])); ++ ++ if (!ucs2_url) ++ { ++ grub_free (url); ++ return grub_errno; ++ } ++ ++ ucs2_url_len = grub_utf8_to_utf16 (ucs2_url, ucs2_url_len, (grub_uint8_t *)url, url_len, NULL); /* convert string format from ascii to usc2 */ ++ ucs2_url[ucs2_url_len] = 0; ++ grub_free (url); ++ request_data.url = ucs2_url; ++ } ++ ++ request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET; ++ ++ request_message.data.request = &request_data; ++ request_message.header_count = 3; ++ request_message.headers = request_headers; ++ request_message.body_length = 0; ++ request_message.body = NULL; ++ ++ /* request token */ ++ request_token.event = NULL; ++ request_token.status = GRUB_EFI_NOT_READY; ++ request_token.message = &request_message; ++ ++ request_callback_done = 0; ++ status = efi_call_5 (b->create_event, ++ GRUB_EFI_EVT_NOTIFY_SIGNAL, ++ GRUB_EFI_TPL_CALLBACK, ++ grub_efi_http_request_callback, ++ NULL, ++ &request_token.event); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status); ++ } ++ ++ status = efi_call_2 (http->request, http, &request_token); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to send a request! status=0x%x\n", status); ++ } ++ /* TODO: Add Timeout */ ++ while (!request_callback_done) ++ efi_call_1(http->poll, http); ++ ++ response_data.status_code = GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS; ++ response_message.data.response = &response_data; ++ /* herader_count will be updated by the HTTP driver on response */ ++ response_message.header_count = 0; ++ /* headers will be populated by the driver on response */ ++ response_message.headers = NULL; ++ /* use zero BodyLength to only receive the response headers */ ++ response_message.body_length = 0; ++ response_message.body = NULL; ++ response_token.event = NULL; ++ ++ status = efi_call_5 (b->create_event, ++ GRUB_EFI_EVT_NOTIFY_SIGNAL, ++ GRUB_EFI_TPL_CALLBACK, ++ grub_efi_http_response_callback, ++ NULL, ++ &response_token.event); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status); ++ } ++ ++ response_token.status = GRUB_EFI_SUCCESS; ++ response_token.message = &response_message; ++ ++ /* wait for HTTP response */ ++ response_callback_done = 0; ++ status = efi_call_2 (http->response, http, &response_token); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, response_token.event); ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to receive a response! status=%d\n", (int)status); ++ } ++ ++ /* TODO: Add Timeout */ ++ while (!response_callback_done) ++ efi_call_1 (http->poll, http); ++ ++ if (response_message.data.response->status_code != GRUB_EFI_HTTP_STATUS_200_OK) ++ { ++ grub_efi_http_status_code_t status_code = response_message.data.response->status_code; ++ ++ if (response_message.headers) ++ efi_call_1 (b->free_pool, response_message.headers); ++ efi_call_1 (b->close_event, response_token.event); ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ if (status_code == GRUB_EFI_HTTP_STATUS_404_NOT_FOUND) ++ { ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, _("file `%s' not found"), name); ++ } ++ else ++ { ++ return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR, ++ _("unsupported uefi http status code 0x%x"), status_code); ++ } ++ } ++ ++ if (file_size) ++ { ++ int i; ++ /* parse the length of the file from the ContentLength header */ ++ for (*file_size = 0, i = 0; i < (int)response_message.header_count; ++i) ++ { ++ if (!grub_strcmp((const char*)response_message.headers[i].field_name, "Content-Length")) ++ { ++ *file_size = grub_strtoul((const char*)response_message.headers[i].field_value, 0, 10); ++ break; ++ } ++ } ++ } ++ ++ if (response_message.headers) ++ efi_call_1 (b->free_pool, response_message.headers); ++ efi_call_1 (b->close_event, response_token.event); ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++efihttp_read (struct grub_efi_net_device *dev, ++ char *buf, ++ grub_size_t len) ++{ ++ grub_efi_http_message_t response_message; ++ grub_efi_http_token_t response_token; ++ ++ grub_efi_status_t status; ++ grub_size_t sum = 0; ++ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; ++ grub_efi_http_t *http = dev->http; ++ ++ if (!len) ++ { ++ grub_error (GRUB_ERR_BUG, "Invalid arguments to EFI HTTP Read"); ++ return -1; ++ } ++ ++ efi_call_5 (b->create_event, ++ GRUB_EFI_EVT_NOTIFY_SIGNAL, ++ GRUB_EFI_TPL_CALLBACK, ++ grub_efi_http_response_callback, ++ NULL, ++ &response_token.event); ++ ++ while (len) ++ { ++ response_message.data.response = NULL; ++ response_message.header_count = 0; ++ response_message.headers = NULL; ++ response_message.body_length = len; ++ response_message.body = buf; ++ ++ response_token.message = &response_message; ++ response_token.status = GRUB_EFI_NOT_READY; ++ ++ response_callback_done = 0; ++ ++ status = efi_call_2 (http->response, http, &response_token); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, response_token.event); ++ grub_error (GRUB_ERR_IO, "Error! status=%d\n", (int)status); ++ return -1; ++ } ++ ++ while (!response_callback_done) ++ efi_call_1(http->poll, http); ++ ++ sum += response_message.body_length; ++ buf += response_message.body_length; ++ len -= response_message.body_length; ++ } ++ ++ efi_call_1 (b->close_event, response_token.event); ++ ++ return sum; ++} ++ ++static grub_err_t ++grub_efihttp_open (struct grub_efi_net_device *dev, ++ int prefer_ip6 __attribute__ ((unused)), ++ grub_file_t file, ++ const char *filename __attribute__ ((unused)), ++ int type) ++{ ++ grub_err_t err; ++ grub_off_t size; ++ char *buf; ++ ++ err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ ++ err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ ++ buf = grub_malloc (size); ++ efihttp_read (dev, buf, size); ++ ++ file->size = size; ++ file->data = buf; ++ file->not_easily_seekable = 0; ++ file->device->net->offset = 0; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_efihttp_close (struct grub_efi_net_device *dev __attribute__ ((unused)), ++ int prefer_ip6 __attribute__ ((unused)), ++ grub_file_t file) ++{ ++ if (file->data) ++ grub_free (file->data); ++ ++ file->data = 0; ++ file->offset = 0; ++ file->size = 0; ++ file->device->net->offset = 0; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++grub_efihttp_read (struct grub_efi_net_device *dev __attribute__((unused)), ++ int prefer_ip6 __attribute__((unused)), ++ grub_file_t file, ++ char *buf, ++ grub_size_t len) ++{ ++ grub_size_t r = len; ++ ++ if (!file->data || !buf || !len) ++ return 0; ++ ++ if ((file->device->net->offset + len) > file->size) ++ r = file->size - file->device->net->offset; ++ ++ if (r) ++ { ++ grub_memcpy (buf, (char *)file->data + file->device->net->offset, r); ++ file->device->net->offset += r; ++ } ++ ++ return r; ++} ++ ++struct grub_efi_net_io io_http = ++ { ++ .configure = http_configure, ++ .open = grub_efihttp_open, ++ .read = grub_efihttp_read, ++ .close = grub_efihttp_close ++ }; +diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c +new file mode 100644 +index 0000000000..b711a5d945 +--- /dev/null ++++ b/grub-core/net/efi/ip4_config.c +@@ -0,0 +1,398 @@ ++ ++#include ++#include ++#include ++#include ++#include ++ ++char * ++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address) ++{ ++ char *hw_addr, *p; ++ int sz, s; ++ int i; ++ ++ sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1; ++ ++ hw_addr = grub_malloc (sz); ++ if (!hw_addr) ++ return NULL; ++ ++ p = hw_addr; ++ s = sz; ++ for (i = 0; i < (int)hw_address_size; i++) ++ { ++ grub_snprintf (p, sz, "%02x:", hw_address[i]); ++ p += sizeof ("XX:") - 1; ++ s -= sizeof ("XX:") - 1; ++ } ++ ++ hw_addr[sz - 2] = '\0'; ++ return hw_addr; ++} ++ ++char * ++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address) ++{ ++ char *addr; ++ ++ addr = grub_malloc (sizeof ("XXX.XXX.XXX.XXX")); ++ if (!addr) ++ return NULL; ++ ++ /* FIXME: Use grub_xasprintf ? */ ++ grub_snprintf (addr, ++ sizeof ("XXX.XXX.XXX.XXX"), ++ "%u.%u.%u.%u", ++ (*address)[0], ++ (*address)[1], ++ (*address)[2], ++ (*address)[3]); ++ ++ return addr; ++} ++ ++int ++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest) ++{ ++ grub_uint32_t newip = 0; ++ int i; ++ const char *ptr = val; ++ ++ for (i = 0; i < 4; i++) ++ { ++ unsigned long t; ++ t = grub_strtoul (ptr, (char **) &ptr, 0); ++ if (grub_errno) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ if (*ptr != '.' && i == 0) ++ { ++ /* XXX: t is in host byte order */ ++ newip = t; ++ break; ++ } ++ if (t & ~0xff) ++ return 0; ++ newip <<= 8; ++ newip |= t; ++ if (i != 3 && *ptr != '.') ++ return 0; ++ ptr++; ++ } ++ ++ newip = grub_cpu_to_be32 (newip); ++ ++ grub_memcpy (address, &newip, sizeof(*address)); ++ ++ if (rest) ++ *rest = (ptr - 1); ++ return 1; ++} ++ ++static grub_efi_ip4_config2_interface_info_t * ++efi_ip4_config_interface_info (grub_efi_ip4_config2_protocol_t *ip4_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ ++ sz = sizeof (*interface_info) + sizeof (*interface_info->route_table); ++ interface_info = grub_malloc (sz); ++ if (!interface_info) ++ return NULL; ++ ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ grub_free (interface_info); ++ interface_info = grub_malloc (sz); ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ return interface_info; ++} ++ ++static grub_efi_ip4_config2_manual_address_t * ++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++char * ++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ char *name; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE ++ * GRUB_MAX_UTF8_PER_UTF16 + 1); ++ *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name, ++ GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0; ++ grub_free (interface_info); ++ return name; ++} ++ ++static char * ++grub_efi_ip4_interface_hw_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ char *hw_addr; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address); ++ grub_free (interface_info); ++ ++ return hw_addr; ++} ++ ++static char * ++grub_efi_ip4_interface_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ char *addr; ++ ++ manual_address = efi_ip4_config_manual_address (dev->ip4_config); ++ ++ if (!manual_address) ++ return NULL; ++ ++ addr = grub_efi_ip4_address_to_string (&manual_address->address); ++ grub_free (manual_address); ++ return addr; ++} ++ ++ ++static int ++address_mask_size (grub_efi_ipv4_address_t *address) ++{ ++ grub_uint8_t i; ++ grub_uint32_t u32_addr = grub_be_to_cpu32 (grub_get_unaligned32 (address)); ++ ++ if (u32_addr == 0) ++ return 0; ++ ++ for (i = 0; i < 32 ; ++i) ++ { ++ if (u32_addr == ((0xffffffff >> i) << i)) ++ return (32 - i); ++ } ++ ++ return -1; ++} ++ ++static char ** ++grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ char **ret; ++ int i, id; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ if (!interface_info) ++ return NULL; ++ ++ ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1)); ++ ++ if (!ret) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ id = 0; ++ for (i = 0; i < (int)interface_info->route_table_size; i++) ++ { ++ char *subnet, *gateway, *mask; ++ grub_uint32_t u32_subnet, u32_gateway; ++ int mask_size; ++ grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i; ++ grub_efi_net_interface_t *inf; ++ char *interface_name = NULL; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (!inf->prefer_ip6) ++ interface_name = inf->name; ++ ++ u32_gateway = grub_get_unaligned32 (&route_table->gateway_address); ++ gateway = grub_efi_ip4_address_to_string (&route_table->gateway_address); ++ u32_subnet = grub_get_unaligned32 (&route_table->subnet_address); ++ subnet = grub_efi_ip4_address_to_string (&route_table->subnet_address); ++ mask_size = address_mask_size (&route_table->subnet_mask); ++ mask = grub_efi_ip4_address_to_string (&route_table->subnet_mask); ++ if (u32_subnet && !u32_gateway && interface_name) ++ ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, subnet, mask_size, interface_name); ++ else if (u32_subnet && u32_gateway) ++ ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, subnet, mask_size, gateway); ++ else if (!u32_subnet && u32_gateway) ++ ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, subnet, mask_size, gateway); ++ grub_free (subnet); ++ grub_free (gateway); ++ grub_free (mask); ++ } ++ ++ ret[id] = NULL; ++ grub_free (interface_info); ++ return ret; ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_ip4_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ grub_efi_net_interface_t *inf; ++ int i; ++ grub_efi_ipv4_address_t *address = &ip_address->ip4; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ if (!interface_info) ++ return NULL; ++ ++ for (i = 0; i < (int)interface_info->route_table_size; i++) ++ { ++ grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i; ++ grub_uint32_t u32_address, u32_mask, u32_subnet; ++ ++ u32_address = grub_get_unaligned32 (address); ++ u32_subnet = grub_get_unaligned32 (route_table->subnet_address); ++ u32_mask = grub_get_unaligned32 (route_table->subnet_mask); ++ ++ /* SKIP Default GATEWAY */ ++ if (!u32_subnet && !u32_mask) ++ continue; ++ ++ if ((u32_address & u32_mask) == u32_subnet) ++ { ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (!inf->prefer_ip6) ++ { ++ grub_free (interface_info); ++ return inf; ++ } ++ } ++ } ++ ++ grub_free (interface_info); ++ return NULL; ++} ++ ++static int ++grub_efi_ip4_interface_set_manual_address (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int with_subnet) ++{ ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_manual_address_t *address = &net_ip->ip4; ++ ++ if (!with_subnet) ++ { ++ grub_efi_ip4_config2_manual_address_t *manual_address = ++ efi_ip4_config_manual_address (dev->ip4_config); ++ ++ if (manual_address) ++ { ++ grub_memcpy (address->subnet_mask, manual_address->subnet_mask, sizeof(address->subnet_mask)); ++ grub_free (manual_address); ++ } ++ else ++ { ++ /* XXX: */ ++ address->subnet_mask[0] = 0xff; ++ address->subnet_mask[1] = 0xff; ++ address->subnet_mask[2] = 0xff; ++ address->subnet_mask[3] = 0; ++ } ++ } ++ ++ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, ++ sizeof(*address), address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++grub_efi_ip4_interface_set_gateway (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY, ++ sizeof (address->ip4), &address->ip4); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++/* FIXME: Multiple DNS */ ++static int ++grub_efi_ip4_interface_set_dns (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, ++ sizeof (address->ip4), &address->ip4); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++grub_efi_net_ip_config_t *efi_net_ip4_config = &(grub_efi_net_ip_config_t) ++ { ++ .get_hw_address = grub_efi_ip4_interface_hw_address, ++ .get_address = grub_efi_ip4_interface_address, ++ .get_route_table = grub_efi_ip4_interface_route_table, ++ .best_interface = grub_efi_ip4_interface_match, ++ .set_address = grub_efi_ip4_interface_set_manual_address, ++ .set_gateway = grub_efi_ip4_interface_set_gateway, ++ .set_dns = grub_efi_ip4_interface_set_dns ++ }; +diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c +new file mode 100644 +index 0000000000..017c4d05bc +--- /dev/null ++++ b/grub-core/net/efi/ip6_config.c +@@ -0,0 +1,422 @@ ++#include ++#include ++#include ++#include ++#include ++ ++char * ++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address) ++{ ++ char *str = grub_malloc (sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX")); ++ char *p; ++ int i; ++ int squash; ++ ++ if (!str) ++ return NULL; ++ ++ p = str; ++ squash = 0; ++ for (i = 0; i < 8; ++i) ++ { ++ grub_uint16_t addr; ++ ++ if (i == 7) ++ squash = 2; ++ ++ addr = grub_get_unaligned16 (address->addr + i * 2); ++ ++ if (grub_be_to_cpu16 (addr)) ++ { ++ char buf[sizeof ("XXXX")]; ++ if (i > 0) ++ *p++ = ':'; ++ grub_snprintf (buf, sizeof (buf), "%x", grub_be_to_cpu16 (addr)); ++ grub_strcpy (p, buf); ++ p += grub_strlen (buf); ++ ++ if (squash == 1) ++ squash = 2; ++ } ++ else ++ { ++ if (squash == 0) ++ { ++ *p++ = ':'; ++ squash = 1; ++ } ++ else if (squash == 2) ++ { ++ *p++ = ':'; ++ *p++ = '0'; ++ } ++ } ++ } ++ *p = '\0'; ++ return str; ++} ++ ++int ++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest) ++{ ++ grub_uint16_t newip[8]; ++ const char *ptr = val; ++ int word, quaddot = -1; ++ int bracketed = 0; ++ ++ if (ptr[0] == '[') { ++ bracketed = 1; ++ ptr++; ++ } ++ ++ if (ptr[0] == ':' && ptr[1] != ':') ++ return 0; ++ if (ptr[0] == ':') ++ ptr++; ++ ++ for (word = 0; word < 8; word++) ++ { ++ unsigned long t; ++ if (*ptr == ':') ++ { ++ quaddot = word; ++ word--; ++ ptr++; ++ continue; ++ } ++ t = grub_strtoul (ptr, (char **) &ptr, 16); ++ if (grub_errno) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ break; ++ } ++ if (t & ~0xffff) ++ return 0; ++ newip[word] = grub_cpu_to_be16 (t); ++ if (*ptr != ':') ++ break; ++ ptr++; ++ } ++ if (quaddot == -1 && word < 7) ++ return 0; ++ if (quaddot != -1) ++ { ++ grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], ++ (word - quaddot + 1) * sizeof (newip[0])); ++ grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); ++ } ++ grub_memcpy (address, newip, 16); ++ if (bracketed && *ptr == ']') { ++ ptr++; ++ } ++ if (rest) ++ *rest = ptr; ++ return 1; ++} ++ ++static grub_efi_ip6_config_interface_info_t * ++efi_ip6_config_interface_info (grub_efi_ip6_config_protocol_t *ip6_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ ++ sz = sizeof (*interface_info) + sizeof (*interface_info->route_table); ++ interface_info = grub_malloc (sz); ++ ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ grub_free (interface_info); ++ interface_info = grub_malloc (sz); ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ return interface_info; ++} ++ ++static grub_efi_ip6_config_manual_address_t * ++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++char * ++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ char *name; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE ++ * GRUB_MAX_UTF8_PER_UTF16 + 1); ++ *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name, ++ GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0; ++ grub_free (interface_info); ++ return name; ++} ++ ++static char * ++grub_efi_ip6_interface_hw_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ char *hw_addr; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address); ++ grub_free (interface_info); ++ ++ return hw_addr; ++} ++ ++static char * ++grub_efi_ip6_interface_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ char *addr; ++ ++ manual_address = efi_ip6_config_manual_address (dev->ip6_config); ++ ++ if (!manual_address) ++ return NULL; ++ ++ addr = grub_efi_ip6_address_to_string ((grub_efi_pxe_ipv6_address_t *)&manual_address->address); ++ grub_free (manual_address); ++ return addr; ++} ++ ++static char ** ++grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ char **ret; ++ int i, id; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ if (!interface_info) ++ return NULL; ++ ++ ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1)); ++ ++ if (!ret) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ id = 0; ++ for (i = 0; i < (int)interface_info->route_count ; i++) ++ { ++ char *gateway, *destination; ++ grub_uint64_t u64_gateway[2]; ++ grub_uint64_t u64_destination[2]; ++ grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i; ++ grub_efi_net_interface_t *inf; ++ char *interface_name = NULL; ++ ++ gateway = grub_efi_ip6_address_to_string (&route_table->gateway); ++ destination = grub_efi_ip6_address_to_string (&route_table->destination); ++ ++ u64_gateway[0] = grub_get_unaligned64 (route_table->gateway.addr); ++ u64_gateway[1] = grub_get_unaligned64 (route_table->gateway.addr + 8); ++ u64_destination[0] = grub_get_unaligned64 (route_table->destination.addr); ++ u64_destination[1] = grub_get_unaligned64 (route_table->destination.addr + 8); ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6) ++ interface_name = inf->name; ++ ++ if ((!u64_gateway[0] && !u64_gateway[1]) ++ && (u64_destination[0] || u64_destination[1])) ++ { ++ if (interface_name) ++ { ++ if ((grub_be_to_cpu64 (u64_destination[0]) == 0xfe80000000000000ULL) ++ && (!u64_destination[1]) ++ && (route_table->prefix_length == 64)) ++ ret[id++] = grub_xasprintf ("%s:link %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name); ++ else ++ ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name); ++ } ++ } ++ else if ((u64_gateway[0] || u64_gateway[1]) ++ && (u64_destination[0] || u64_destination[1])) ++ ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway); ++ else if ((u64_gateway[0] || u64_gateway[1]) ++ && (!u64_destination[0] && !u64_destination[1])) ++ ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway); ++ ++ grub_free (gateway); ++ grub_free (destination); ++ } ++ ++ ret[id] = NULL; ++ grub_free (interface_info); ++ return ret; ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_ip6_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ grub_efi_net_interface_t *inf; ++ int i; ++ grub_efi_ipv6_address_t *address = &ip_address->ip6; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ if (!interface_info) ++ return NULL; ++ ++ for (i = 0; i < (int)interface_info->route_count ; i++) ++ { ++ grub_uint64_t u64_addr[2]; ++ grub_uint64_t u64_subnet[2]; ++ grub_uint64_t u64_mask[2]; ++ ++ grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i; ++ ++ /* SKIP Default GATEWAY */ ++ if (route_table->prefix_length == 0) ++ continue; ++ ++ u64_addr[0] = grub_get_unaligned64 (address); ++ u64_addr[1] = grub_get_unaligned64 (address + 4); ++ u64_subnet[0] = grub_get_unaligned64 (route_table->destination.addr); ++ u64_subnet[1] = grub_get_unaligned64 (route_table->destination.addr + 8); ++ u64_mask[0] = (route_table->prefix_length <= 64) ? ++ 0xffffffffffffffffULL << (64 - route_table->prefix_length) : ++ 0xffffffffffffffffULL; ++ u64_mask[1] = (route_table->prefix_length <= 64) ? ++ 0 : ++ 0xffffffffffffffffULL << (128 - route_table->prefix_length); ++ ++ if (((u64_addr[0] & u64_mask[0]) == u64_subnet[0]) ++ && ((u64_addr[1] & u64_mask[1]) == u64_subnet[1])) ++ { ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6) ++ { ++ grub_free (interface_info); ++ return inf; ++ } ++ } ++ } ++ ++ grub_free (interface_info); ++ return NULL; ++} ++ ++static int ++grub_efi_ip6_interface_set_manual_address (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int with_subnet) ++{ ++ grub_efi_status_t status; ++ grub_efi_ip6_config_manual_address_t *address = &net_ip->ip6; ++ ++ if (!with_subnet) ++ { ++ grub_efi_ip6_config_manual_address_t *manual_address = ++ efi_ip6_config_manual_address (dev->ip6_config); ++ ++ if (manual_address) ++ { ++ address->prefix_length = manual_address->prefix_length; ++ grub_free (manual_address); ++ } ++ else ++ { ++ /* XXX: */ ++ address->prefix_length = 64; ++ } ++ } ++ ++ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ sizeof(*address), address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++grub_efi_ip6_interface_set_gateway (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY, ++ sizeof (address->ip6), &address->ip6); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++static int ++grub_efi_ip6_interface_set_dns (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, ++ sizeof (address->ip6), &address->ip6); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++grub_efi_net_ip_config_t *efi_net_ip6_config = &(grub_efi_net_ip_config_t) ++ { ++ .get_hw_address = grub_efi_ip6_interface_hw_address, ++ .get_address = grub_efi_ip6_interface_address, ++ .get_route_table = grub_efi_ip6_interface_route_table, ++ .best_interface = grub_efi_ip6_interface_match, ++ .set_address = grub_efi_ip6_interface_set_manual_address, ++ .set_gateway = grub_efi_ip6_interface_set_gateway, ++ .set_dns = grub_efi_ip6_interface_set_dns ++ }; +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +new file mode 100644 +index 0000000000..86bce6535d +--- /dev/null ++++ b/grub-core/net/efi/net.c +@@ -0,0 +1,1428 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#define GRUB_EFI_IP6_PREFIX_LENGTH 64 ++ ++static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID; ++static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID; ++static grub_efi_guid_t http_service_binding_guid = GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID; ++static grub_efi_guid_t http_guid = GRUB_EFI_HTTP_PROTOCOL_GUID; ++static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; ++static grub_efi_guid_t dhcp4_service_binding_guid = GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID; ++static grub_efi_guid_t dhcp4_guid = GRUB_EFI_DHCP4_PROTOCOL_GUID; ++static grub_efi_guid_t dhcp6_service_binding_guid = GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID; ++static grub_efi_guid_t dhcp6_guid = GRUB_EFI_DHCP6_PROTOCOL_GUID; ++ ++struct grub_efi_net_device *net_devices; ++ ++static char *default_server; ++static grub_efi_net_interface_t *net_interface; ++static grub_efi_net_interface_t *net_default_interface; ++ ++#define efi_net_interface_configure(inf) inf->io->configure (inf->dev, inf->prefer_ip6) ++#define efi_net_interface_open(inf, file, name) inf->io->open (inf->dev, inf->prefer_ip6, file, name, inf->io_type) ++#define efi_net_interface_read(inf, file, buf, sz) inf->io->read (inf->dev, inf->prefer_ip6, file, buf, sz) ++#define efi_net_interface_close(inf, file) inf->io->close (inf->dev, inf->prefer_ip6, file) ++#define efi_net_interface(m,...) efi_net_interface_ ## m (net_interface, ## __VA_ARGS__) ++ ++static grub_efi_handle_t ++grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path, ++ grub_efi_device_path_t **r_device_path) ++{ ++ grub_efi_handle_t handle; ++ grub_efi_status_t status; ++ ++ status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path, ++ protocol, &device_path, &handle); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ ++ if (r_device_path) ++ *r_device_path = device_path; ++ ++ return handle; ++} ++ ++static int ++url_parse_fields (const char *url, char **proto, char **host, char **path) ++{ ++ const char *p, *ps; ++ grub_size_t l; ++ ++ *proto = *host = *path = NULL; ++ ps = p = url; ++ ++ while ((p = grub_strchr (p, ':'))) ++ { ++ if (grub_strlen (p) < sizeof ("://") - 1) ++ break; ++ if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0) ++ { ++ l = p - ps; ++ *proto = grub_malloc (l + 1); ++ if (!*proto) ++ { ++ grub_print_error (); ++ return 0; ++ } ++ ++ grub_memcpy (*proto, ps, l); ++ (*proto)[l] = '\0'; ++ p += sizeof ("://") - 1; ++ break; ++ } ++ ++p; ++ } ++ ++ if (!*proto) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url); ++ return 0; ++ } ++ ++ ps = p; ++ p = grub_strchr (p, '/'); ++ ++ if (!p) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ ++ l = p - ps; ++ ++ if (l > 2 && ps[0] == '[' && ps[l - 1] == ']') ++ { ++ *host = grub_malloc (l - 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps + 1, l - 2); ++ (*host)[l - 2] = 0; ++ } ++ else ++ { ++ *host = grub_malloc (l + 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps, l); ++ (*host)[l] = 0; ++ } ++ ++ *path = grub_strdup (p); ++ if (!*path) ++ { ++ grub_print_error (); ++ grub_free (*host); ++ grub_free (*proto); ++ *host = NULL; ++ *proto = NULL; ++ return 0; ++ } ++ return 1; ++} ++ ++static void ++url_get_boot_location (const char *url, char **device, char **path, int is_default) ++{ ++ char *protocol, *server, *file; ++ char *slash; ++ ++ if (!url_parse_fields (url, &protocol, &server, &file)) ++ return; ++ ++ if ((slash = grub_strrchr (file, '/'))) ++ *slash = 0; ++ else ++ *file = 0; ++ ++ *device = grub_xasprintf ("%s,%s", protocol, server); ++ *path = grub_strdup(file); ++ ++ if (is_default) ++ default_server = server; ++ else ++ grub_free (server); ++ ++ grub_free (protocol); ++ grub_free (file); ++} ++ ++static void ++pxe_get_boot_location (const struct grub_net_bootp_packet *bp, ++ char **device, ++ char **path, ++ int is_default) ++{ ++ char *server = grub_xasprintf ("%d.%d.%d.%d", ++ ((grub_uint8_t *) &bp->server_ip)[0], ++ ((grub_uint8_t *) &bp->server_ip)[1], ++ ((grub_uint8_t *) &bp->server_ip)[2], ++ ((grub_uint8_t *) &bp->server_ip)[3]); ++ ++ *device = grub_xasprintf ("tftp,%s", server); ++ ++ *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); ++ ++ if (*path) ++ { ++ char *slash; ++ slash = grub_strrchr (*path, '/'); ++ if (slash) ++ *slash = 0; ++ else ++ **path = 0; ++ } ++ ++ if (is_default) ++ default_server = server; ++ else ++ grub_free (server); ++} ++ ++static void ++pxe_get_boot_location_v6 (const struct grub_net_dhcp6_packet *dp, ++ grub_size_t dhcp_size, ++ char **device, ++ char **path) ++{ ++ ++ struct grub_net_dhcp6_option *dhcp_opt; ++ grub_size_t dhcp_remain_size; ++ *device = *path = 0; ++ ++ if (dhcp_size < sizeof (*dp)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small")); ++ return; ++ } ++ ++ dhcp_remain_size = dhcp_size - sizeof (*dp); ++ dhcp_opt = (struct grub_net_dhcp6_option *)dp->dhcp_options; ++ ++ while (dhcp_remain_size) ++ { ++ grub_uint16_t code = grub_be_to_cpu16 (dhcp_opt->code); ++ grub_uint16_t len = grub_be_to_cpu16 (dhcp_opt->len); ++ grub_uint16_t option_size = sizeof (*dhcp_opt) + len; ++ ++ if (dhcp_remain_size < option_size || code == 0) ++ break; ++ ++ if (code == GRUB_NET_DHCP6_OPTION_BOOTFILE_URL) ++ { ++ char *url = grub_malloc (len + 1); ++ ++ grub_memcpy (url, dhcp_opt->data, len); ++ url[len] = 0; ++ ++ url_get_boot_location ((const char *)url, device, path, 1); ++ grub_free (url); ++ break; ++ } ++ ++ dhcp_remain_size -= option_size; ++ dhcp_opt = (struct grub_net_dhcp6_option *)((grub_uint8_t *)dhcp_opt + option_size); ++ } ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_net_config_from_device_path (grub_efi_device_path_t *dp, ++ struct grub_efi_net_device *netdev, ++ char **device, ++ char **path) ++{ ++ grub_efi_net_interface_t *inf = NULL; ++ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); ++ ++ if (type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) ++ { ++ if (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_uri_device_path_t *uri_dp; ++ uri_dp = (grub_efi_uri_device_path_t *) dp; ++ /* Beware that uri_dp->uri may not be null terminated */ ++ url_get_boot_location ((const char *)uri_dp->uri, device, path, 1); ++ } ++ else if (subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) dp; ++ ++ if (inf) ++ continue; ++ grub_memcpy (net_ip.ip4.address, ipv4->local_ip_address, sizeof (net_ip.ip4.address)); ++ grub_memcpy (net_ip.ip4.subnet_mask, ipv4->subnet_mask, sizeof (net_ip.ip4.subnet_mask)); ++ net_ip.is_ip6 = 0; ++ inf = grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1); ++ } ++ else if (subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) dp; ++ ++ if (inf) ++ continue; ++ grub_memcpy (net_ip.ip6.address, ipv6->local_ip_address, sizeof (net_ip.ip6.address)); ++ net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH; ++ net_ip.ip6.is_anycast = 0; ++ net_ip.is_ip6 = 1; ++ inf = grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1); ++ } ++ } ++ ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) ++ break; ++ dp = (grub_efi_device_path_t *) ((char *) dp + len); ++ } ++ ++ return inf; ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_net_config_from_handle (grub_efi_handle_t *hnd, ++ struct grub_efi_net_device *netdev, ++ char **device, ++ char **path) ++{ ++ grub_efi_pxe_t *pxe = NULL; ++ ++ if (hnd == netdev->ip4_pxe_handle) ++ pxe = netdev->ip4_pxe; ++ else if (hnd == netdev->ip6_pxe_handle) ++ pxe = netdev->ip6_pxe; ++ ++ if (!pxe) ++ return (grub_efi_net_config_from_device_path ( ++ grub_efi_get_device_path (hnd), ++ netdev, ++ device, ++ path)); ++ ++ if (pxe->mode->using_ipv6) ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ ++ pxe_get_boot_location_v6 ( ++ (const struct grub_net_dhcp6_packet *) &pxe->mode->dhcp_ack, ++ sizeof (pxe->mode->dhcp_ack), ++ device, ++ path); ++ ++ grub_memcpy (net_ip.ip6.address, pxe->mode->station_ip.v6, sizeof(net_ip.ip6.address)); ++ net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH; ++ net_ip.ip6.is_anycast = 0; ++ net_ip.is_ip6 = 1; ++ return (grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1)); ++ } ++ else ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ ++ pxe_get_boot_location ( ++ (const struct grub_net_bootp_packet *) &pxe->mode->dhcp_ack, ++ device, ++ path, ++ 1); ++ ++ grub_memcpy (net_ip.ip4.address, pxe->mode->station_ip.v4, sizeof (net_ip.ip4.address)); ++ grub_memcpy (net_ip.ip4.subnet_mask, pxe->mode->subnet_mask.v4, sizeof (net_ip.ip4.subnet_mask)); ++ net_ip.is_ip6 = 0; ++ return (grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1)); ++ } ++} ++ ++static const char * ++grub_efi_net_var_get_address (struct grub_env_var *var, ++ const char *val __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *var_name; ++ ++ var_name = grub_xasprintf ("net_%s_ip", inf->name); ++ if (grub_strcmp (var_name, var->name) == 0) ++ return efi_net_interface_get_address (inf); ++ grub_free (var_name); ++ var_name = grub_xasprintf ("net_%s_mac", inf->name); ++ if (grub_strcmp (var_name, var->name) == 0) ++ return efi_net_interface_get_hw_address (inf); ++ grub_free (var_name); ++ } ++ } ++ ++ return NULL; ++} ++ ++static char * ++grub_efi_net_var_set_interface (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val) ++{ ++ struct grub_efi_net_device *dev; ++ grub_efi_net_interface_t *inf; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (grub_strcmp (inf->name, val) == 0) ++ { ++ net_default_interface = inf; ++ return grub_strdup (val); ++ } ++ ++ return NULL; ++} ++ ++static char * ++grub_efi_net_var_set_server (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val) ++{ ++ grub_free (default_server); ++ default_server = grub_strdup (val); ++ return grub_strdup (val); ++} ++ ++static const char * ++grub_efi_net_var_get_server (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ return default_server ? : ""; ++} ++ ++static const char * ++grub_efi_net_var_get_ip (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ const char *intf = grub_env_get ("net_default_interface"); ++ const char *ret = NULL; ++ if (intf) ++ { ++ char *buf = grub_xasprintf ("net_%s_ip", intf); ++ if (buf) ++ ret = grub_env_get (buf); ++ grub_free (buf); ++ } ++ return ret; ++} ++ ++static const char * ++grub_efi_net_var_get_mac (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ const char *intf = grub_env_get ("net_default_interface"); ++ const char *ret = NULL; ++ if (intf) ++ { ++ char *buf = grub_xasprintf ("net_%s_mac", intf); ++ if (buf) ++ ret = grub_env_get (buf); ++ grub_free (buf); ++ } ++ return ret; ++} ++ ++static void ++grub_efi_net_export_interface_vars (void) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *var; ++ ++ var = grub_xasprintf ("net_%s_ip", inf->name); ++ grub_register_variable_hook (var, grub_efi_net_var_get_address, 0); ++ grub_env_export (var); ++ grub_free (var); ++ var = grub_xasprintf ("net_%s_mac", inf->name); ++ grub_register_variable_hook (var, grub_efi_net_var_get_address, 0); ++ grub_env_export (var); ++ grub_free (var); ++ } ++ } ++} ++ ++static void ++grub_efi_net_unset_interface_vars (void) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *var; ++ ++ var = grub_xasprintf ("net_%s_ip", inf->name); ++ grub_register_variable_hook (var, 0, 0); ++ grub_env_unset (var); ++ grub_free (var); ++ var = grub_xasprintf ("net_%s_mac", inf->name); ++ grub_register_variable_hook (var, 0, 0); ++ grub_env_unset (var); ++ grub_free (var); ++ } ++ } ++} ++ ++grub_efi_net_interface_t * ++grub_efi_net_create_interface (struct grub_efi_net_device *dev, ++ const char *interface_name, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int has_subnet) ++{ ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ if (inf->prefer_ip6 == net_ip->is_ip6) ++ break; ++ } ++ ++ if (!inf) ++ { ++ inf = grub_malloc (sizeof(*inf)); ++ inf->name = grub_strdup (interface_name); ++ inf->prefer_ip6 = net_ip->is_ip6; ++ inf->dev = dev; ++ inf->next = dev->net_interfaces; ++ inf->ip_config = (net_ip->is_ip6) ? efi_net_ip6_config : efi_net_ip4_config ; ++ dev->net_interfaces = inf; ++ } ++ else ++ { ++ grub_free (inf->name); ++ inf->name = grub_strdup (interface_name); ++ } ++ ++ if (!efi_net_interface_set_address (inf, net_ip, has_subnet)) ++ { ++ grub_error (GRUB_ERR_BUG, N_("Set Address Failed")); ++ return NULL; ++ } ++ ++ return inf; ++} ++ ++static void ++grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, ++ char **path) ++{ ++ grub_efi_handle_t config_hnd; ++ ++ struct grub_efi_net_device *netdev; ++ grub_efi_net_interface_t *inf; ++ ++ config_hnd = grub_efi_locate_device_path (&ip4_config_guid, grub_efi_get_device_path (hnd), NULL); ++ ++ if (!config_hnd) ++ return; ++ ++ for (netdev = net_devices; netdev; netdev = netdev->next) ++ if (netdev->handle == config_hnd) ++ break; ++ ++ if (!netdev) ++ return; ++ ++ if (!(inf = grub_efi_net_config_from_handle (hnd, netdev, device, path))) ++ return; ++ ++ grub_env_set ("net_default_interface", inf->name); ++ grub_efi_net_export_interface_vars (); ++} ++ ++static grub_err_t ++grub_efi_netfs_dir (grub_device_t device, const char *path __attribute__ ((unused)), ++ grub_fs_dir_hook_t hook __attribute__ ((unused)), ++ void *hook_data __attribute__ ((unused))) ++{ ++ if (!device->net) ++ return grub_error (GRUB_ERR_BUG, "invalid net device"); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_efi_netfs_open (struct grub_file *file_out __attribute__ ((unused)), ++ const char *name __attribute__ ((unused))) ++{ ++ struct grub_file *file, *bufio; ++ ++ file = grub_malloc (sizeof (*file)); ++ if (!file) ++ return grub_errno; ++ ++ grub_memcpy (file, file_out, sizeof (struct grub_file)); ++ file->device->net->name = grub_strdup (name); ++ ++ if (!file->device->net->name) ++ { ++ grub_free (file); ++ return grub_errno; ++ } ++ ++ efi_net_interface(open, file, name); ++ grub_print_error (); ++ ++ bufio = grub_bufio_open (file, 32768); ++ if (!bufio) ++ { ++ grub_free (file->device->net->name); ++ grub_free (file); ++ return grub_errno; ++ } ++ grub_memcpy (file_out, bufio, sizeof (struct grub_file)); ++ grub_free (bufio); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++grub_efihttp_chunk_read (grub_file_t file, char *buf, ++ grub_size_t len, grub_size_t chunk_size) ++{ ++ char *chunk = grub_malloc (chunk_size); ++ grub_size_t sum = 0; ++ ++ while (len) ++ { ++ grub_ssize_t rd; ++ grub_size_t sz = (len > chunk_size) ? chunk_size : len; ++ ++ rd = efi_net_interface (read, file, chunk, sz); ++ ++ if (rd <= 0) ++ return rd; ++ ++ if (buf) ++ { ++ grub_memcpy (buf, chunk, rd); ++ buf += rd; ++ } ++ sum += rd; ++ len -= rd; ++ } ++ ++ grub_free (chunk); ++ return sum; ++} ++ ++static grub_ssize_t ++grub_efi_netfs_read (grub_file_t file __attribute__ ((unused)), ++ char *buf __attribute__ ((unused)), grub_size_t len __attribute__ ((unused))) ++{ ++ if (file->offset > file->device->net->offset) ++ { ++ grub_efihttp_chunk_read (file, NULL, file->offset - file->device->net->offset, 10240); ++ } ++ else if (file->offset < file->device->net->offset) ++ { ++ efi_net_interface (close, file); ++ efi_net_interface (open, file, file->device->net->name); ++ if (file->offset) ++ grub_efihttp_chunk_read (file, NULL, file->offset, 10240); ++ } ++ ++ return efi_net_interface (read, file, buf, len); ++} ++ ++static grub_err_t ++grub_efi_netfs_close (grub_file_t file) ++{ ++ efi_net_interface (close, file); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_efi_handle_t ++grub_efi_service_binding (grub_efi_handle_t dev, grub_efi_guid_t *service_binding_guid) ++{ ++ grub_efi_service_binding_t *service; ++ grub_efi_status_t status; ++ grub_efi_handle_t child_dev = NULL; ++ ++ service = grub_efi_open_protocol (dev, service_binding_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!service) ++ { ++ grub_error (GRUB_ERR_IO, N_("couldn't open efi service binding protocol")); ++ return NULL; ++ } ++ ++ status = efi_call_2 (service->create_child, service, &child_dev); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_IO, N_("Failed to create child device of http service %x"), status); ++ return NULL; ++ } ++ ++ return child_dev; ++} ++ ++static grub_err_t ++grub_efi_net_parse_address (const char *address, ++ grub_efi_ip4_config2_manual_address_t *ip4, ++ grub_efi_ip6_config_manual_address_t *ip6, ++ int *is_ip6, ++ int *has_cidr) ++{ ++ const char *rest; ++ ++ if (grub_efi_string_to_ip4_address (address, &ip4->address, &rest)) ++ { ++ *is_ip6 = 0; ++ if (*rest == '/') ++ { ++ grub_uint32_t subnet_mask_size; ++ ++ subnet_mask_size = grub_strtoul (rest + 1, (char **) &rest, 0); ++ ++ if (!grub_errno && subnet_mask_size <= 32 && *rest == 0) ++ { ++ grub_uint32_t subnet_mask; ++ ++ subnet_mask = grub_cpu_to_be32 ((0xffffffffU << (32 - subnet_mask_size))); ++ grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); ++ if (has_cidr) ++ *has_cidr = 1; ++ return GRUB_ERR_NONE; ++ } ++ } ++ else if (*rest == 0) ++ { ++ grub_uint32_t subnet_mask = 0xffffffffU; ++ grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); ++ if (has_cidr) ++ *has_cidr = 0; ++ return GRUB_ERR_NONE; ++ } ++ } ++ else if (grub_efi_string_to_ip6_address (address, &ip6->address, &rest)) ++ { ++ *is_ip6 = 1; ++ if (*rest == '/') ++ { ++ grub_efi_uint8_t prefix_length; ++ ++ prefix_length = grub_strtoul (rest + 1, (char **) &rest, 0); ++ if (!grub_errno && prefix_length <= 128 && *rest == 0) ++ { ++ ip6->prefix_length = prefix_length; ++ ip6->is_anycast = 0; ++ if (has_cidr) ++ *has_cidr = 1; ++ return GRUB_ERR_NONE; ++ } ++ } ++ else if (*rest == 0) ++ { ++ ip6->prefix_length = 128; ++ ip6->is_anycast = 0; ++ if (has_cidr) ++ *has_cidr = 0; ++ return GRUB_ERR_NONE; ++ } ++ } ++ ++ return grub_error (GRUB_ERR_NET_BAD_ADDRESS, ++ N_("unrecognised network address `%s'"), ++ address); ++} ++ ++static grub_efi_net_interface_t * ++match_route (const char *server) ++{ ++ grub_err_t err; ++ grub_efi_ip4_config2_manual_address_t ip4; ++ grub_efi_ip6_config_manual_address_t ip6; ++ grub_efi_net_interface_t *inf; ++ int is_ip6 = 0; ++ ++ err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0); ++ ++ if (err) ++ { ++ grub_print_error (); ++ return NULL; ++ } ++ ++ if (is_ip6) ++ { ++ struct grub_efi_net_device *dev; ++ grub_efi_net_ip_address_t addr; ++ ++ grub_memcpy (addr.ip6, ip6.address, sizeof(ip6.address)); ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ if ((inf = efi_net_ip6_config->best_interface (dev, &addr))) ++ return inf; ++ } ++ else ++ { ++ struct grub_efi_net_device *dev; ++ grub_efi_net_ip_address_t addr; ++ ++ grub_memcpy (addr.ip4, ip4.address, sizeof(ip4.address)); ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ if ((inf = efi_net_ip4_config->best_interface (dev, &addr))) ++ return inf; ++ } ++ ++ return 0; ++} ++ ++static void ++grub_efi_net_add_pxebc_to_cards (void) ++{ ++ grub_efi_uintn_t num_handles; ++ grub_efi_handle_t *handles; ++ grub_efi_handle_t *handle; ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &pxe_io_guid, ++ 0, &num_handles); ++ if (!handles) ++ return; ++ ++ for (handle = handles; num_handles--; handle++) ++ { ++ grub_efi_device_path_t *dp, *ddp, *ldp; ++ grub_efi_pxe_t *pxe; ++ struct grub_efi_net_device *d; ++ int is_ip6 = 0; ++ ++ dp = grub_efi_get_device_path (*handle); ++ if (!dp) ++ continue; ++ ++ ddp = grub_efi_duplicate_device_path (dp); ++ ldp = grub_efi_find_last_device_path (ddp); ++ ++ if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && ldp->subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) ++ { ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ } ++ else if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && ldp->subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) ++ { ++ is_ip6 = 1; ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ } ++ ++ for (d = net_devices; d; d = d->next) ++ if (grub_efi_compare_device_paths (ddp, grub_efi_get_device_path (d->handle)) == 0) ++ break; ++ ++ if (!d) ++ { ++ grub_free (ddp); ++ continue; ++ } ++ ++ pxe = grub_efi_open_protocol (*handle, &pxe_io_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!pxe) ++ { ++ grub_free (ddp); ++ continue; ++ } ++ ++ if (is_ip6) ++ { ++ d->ip6_pxe_handle = *handle; ++ d->ip6_pxe = pxe; ++ } ++ else ++ { ++ d->ip4_pxe_handle = *handle; ++ d->ip4_pxe = pxe; ++ } ++ ++ grub_free (ddp); ++ } ++ ++ grub_free (handles); ++} ++ ++static void ++set_ip_policy_to_static (void) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_ip4_config2_policy_t ip4_policy = GRUB_EFI_IP4_CONFIG2_POLICY_STATIC; ++ ++ if (efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, ++ sizeof (ip4_policy), &ip4_policy) != GRUB_EFI_SUCCESS) ++ grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP4_CONFIG2_POLICY_STATIC on dev `%s'", dev->card_name); ++ ++ if (dev->ip6_config) ++ { ++ grub_efi_ip6_config_policy_t ip6_policy = GRUB_EFI_IP6_CONFIG_POLICY_MANUAL; ++ ++ if (efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, ++ sizeof (ip6_policy), &ip6_policy) != GRUB_EFI_SUCCESS) ++ grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP6_CONFIG_POLICY_MANUAL on dev `%s'", dev->card_name); ++ } ++ } ++} ++ ++/* FIXME: Do not fail if the card did not support any of the protocol (Eg http) */ ++static void ++grub_efi_net_find_cards (void) ++{ ++ grub_efi_uintn_t num_handles; ++ grub_efi_handle_t *handles; ++ grub_efi_handle_t *handle; ++ int id; ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &ip4_config_guid, ++ 0, &num_handles); ++ if (!handles) ++ return; ++ ++ for (id = 0, handle = handles; num_handles--; handle++, id++) ++ { ++ grub_efi_device_path_t *dp; ++ grub_efi_ip4_config2_protocol_t *ip4_config; ++ grub_efi_ip6_config_protocol_t *ip6_config; ++ grub_efi_handle_t http_handle; ++ grub_efi_http_t *http; ++ grub_efi_handle_t dhcp4_handle; ++ grub_efi_dhcp4_protocol_t *dhcp4; ++ grub_efi_handle_t dhcp6_handle; ++ grub_efi_dhcp6_protocol_t *dhcp6; ++ ++ struct grub_efi_net_device *d; ++ ++ dp = grub_efi_get_device_path (*handle); ++ if (!dp) ++ continue; ++ ++ ip4_config = grub_efi_open_protocol (*handle, &ip4_config_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!ip4_config) ++ continue; ++ ++ ip6_config = grub_efi_open_protocol (*handle, &ip6_config_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ http_handle = grub_efi_service_binding (*handle, &http_service_binding_guid); ++ grub_errno = GRUB_ERR_NONE; ++ http = (http_handle) ++ ? grub_efi_open_protocol (http_handle, &http_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) ++ : NULL; ++ ++ dhcp4_handle = grub_efi_service_binding (*handle, &dhcp4_service_binding_guid); ++ grub_errno = GRUB_ERR_NONE; ++ dhcp4 = (dhcp4_handle) ++ ? grub_efi_open_protocol (dhcp4_handle, &dhcp4_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) ++ : NULL; ++ ++ ++ dhcp6_handle = grub_efi_service_binding (*handle, &dhcp6_service_binding_guid); ++ grub_errno = GRUB_ERR_NONE; ++ dhcp6 = (dhcp6_handle) ++ ? grub_efi_open_protocol (dhcp6_handle, &dhcp6_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) ++ : NULL; ++ ++ d = grub_malloc (sizeof (*d)); ++ if (!d) ++ { ++ grub_free (handles); ++ while (net_devices) ++ { ++ d = net_devices->next; ++ grub_free (net_devices); ++ net_devices = d; ++ } ++ return; ++ } ++ d->handle = *handle; ++ d->ip4_config = ip4_config; ++ d->ip6_config = ip6_config; ++ d->http_handle = http_handle; ++ d->http = http; ++ d->dhcp4_handle = dhcp4_handle; ++ d->dhcp4 = dhcp4; ++ d->dhcp6_handle = dhcp6_handle; ++ d->dhcp6 = dhcp6; ++ d->next = net_devices; ++ d->card_name = grub_xasprintf ("efinet%d", id); ++ d->net_interfaces = NULL; ++ net_devices = d; ++ } ++ ++ grub_efi_net_add_pxebc_to_cards (); ++ grub_free (handles); ++ set_ip_policy_to_static (); ++} ++ ++static void ++listroutes_ip4 (struct grub_efi_net_device *netdev) ++{ ++ char **routes; ++ ++ routes = NULL; ++ ++ if ((routes = efi_net_ip4_config->get_route_table (netdev))) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_printf ("%s\n", *r); ++ } ++ ++ if (routes) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_free (*r); ++ grub_free (routes); ++ } ++} ++ ++static void ++listroutes_ip6 (struct grub_efi_net_device *netdev) ++{ ++ char **routes; ++ ++ routes = NULL; ++ ++ if ((routes = efi_net_ip6_config->get_route_table (netdev))) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_printf ("%s\n", *r); ++ } ++ ++ if (routes) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_free (*r); ++ grub_free (routes); ++ } ++} ++ ++static grub_err_t ++grub_cmd_efi_listroutes (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *netdev; ++ ++ for (netdev = net_devices; netdev; netdev = netdev->next) ++ { ++ listroutes_ip4 (netdev); ++ listroutes_ip6 (netdev); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++static grub_err_t ++grub_cmd_efi_listcards (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ char *hw_addr; ++ ++ hw_addr = efi_net_ip4_config->get_hw_address (dev); ++ ++ if (hw_addr) ++ { ++ grub_printf ("%s %s\n", dev->card_name, hw_addr); ++ grub_free (hw_addr); ++ } ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_efi_listaddrs (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ grub_efi_net_interface_t *inf; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *hw_addr = NULL; ++ char *addr = NULL; ++ ++ if ((hw_addr = efi_net_interface_get_hw_address (inf)) ++ && (addr = efi_net_interface_get_address (inf))) ++ grub_printf ("%s %s %s\n", inf->name, hw_addr, addr); ++ ++ if (hw_addr) ++ grub_free (hw_addr); ++ if (addr) ++ grub_free (addr); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++/* FIXME: support MAC specifying. */ ++static grub_err_t ++grub_cmd_efi_addaddr (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, char **args) ++{ ++ struct grub_efi_net_device *dev; ++ grub_err_t err; ++ grub_efi_ip4_config2_manual_address_t ip4; ++ grub_efi_ip6_config_manual_address_t ip6; ++ grub_efi_net_ip_manual_address_t net_ip; ++ int is_ip6 = 0; ++ int cidr = 0; ++ ++ if (argc != 3) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ if (grub_strcmp (dev->card_name, args[1]) == 0) ++ break; ++ } ++ ++ if (!dev) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); ++ ++ err = grub_efi_net_parse_address (args[2], &ip4, &ip6, &is_ip6, &cidr); ++ ++ if (err) ++ return err; ++ ++ net_ip.is_ip6 = is_ip6; ++ if (is_ip6) ++ grub_memcpy (&net_ip.ip6, &ip6, sizeof(net_ip.ip6)); ++ else ++ grub_memcpy (&net_ip.ip4, &ip4, sizeof(net_ip.ip4)); ++ ++ if (!grub_efi_net_create_interface (dev, ++ args[0], ++ &net_ip, ++ cidr)) ++ return grub_errno; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static struct grub_fs grub_efi_netfs; ++ ++static grub_net_t ++grub_net_open_real (const char *name __attribute__ ((unused))) ++{ ++ grub_size_t protnamelen; ++ const char *protname, *server; ++ grub_net_t ret; ++ ++ net_interface = NULL; ++ ++ if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) ++ { ++ protname = "tftp"; ++ protnamelen = sizeof ("tftp") - 1; ++ server = name + sizeof ("pxe:") - 1; ++ } ++ else if (grub_strcmp (name, "pxe") == 0) ++ { ++ protname = "tftp"; ++ protnamelen = sizeof ("tftp") - 1; ++ server = default_server; ++ } ++ else ++ { ++ const char *comma; ++ ++ comma = grub_strchr (name, ','); ++ if (comma) ++ { ++ protnamelen = comma - name; ++ server = comma + 1; ++ protname = name; ++ } ++ else ++ { ++ protnamelen = grub_strlen (name); ++ server = default_server; ++ protname = name; ++ } ++ } ++ ++ if (!server) ++ { ++ grub_error (GRUB_ERR_NET_BAD_ADDRESS, ++ N_("no server is specified")); ++ return NULL; ++ } ++ ++ /*FIXME: Use DNS translate name to address */ ++ net_interface = match_route (server); ++ ++ /*XXX: should we check device with default gateway ? */ ++ if (!net_interface && !(net_interface = net_default_interface)) ++ { ++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"), ++ name); ++ return NULL; ++ } ++ ++ if ((protnamelen == (sizeof ("https") - 1) ++ && grub_memcmp ("https", protname, protnamelen) == 0)) ++ { ++ net_interface->io = &io_http; ++ net_interface->io_type = 1; ++ } ++ else if ((protnamelen == (sizeof ("http") - 1) ++ && grub_memcmp ("http", protname, protnamelen) == 0)) ++ { ++ net_interface->io = &io_http; ++ net_interface->io_type = 0; ++ } ++ else if (protnamelen == (sizeof ("tftp") - 1) ++ && grub_memcmp ("tftp", protname, protnamelen) == 0) ++ { ++ net_interface->io = &io_pxe; ++ net_interface->io_type = 0; ++ } ++ else ++ { ++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), ++ name); ++ return NULL; ++ } ++ ++ /*XXX: Should we try to avoid doing excess "reconfigure" here ??? */ ++ efi_net_interface (configure); ++ ++ ret = grub_zalloc (sizeof (*ret)); ++ if (!ret) ++ return NULL; ++ ++ ret->server = grub_strdup (server); ++ if (!ret->server) ++ { ++ grub_free (ret); ++ return NULL; ++ } ++ ++ ret->fs = &grub_efi_netfs; ++ return ret; ++} ++#if 0 ++static grub_command_t cmd_efi_lsaddr; ++static grub_command_t cmd_efi_lscards; ++static grub_command_t cmd_efi_lsroutes; ++static grub_command_t cmd_efi_addaddr; ++#endif ++ ++static struct grub_fs grub_efi_netfs = ++ { ++ .name = "efi netfs", ++ .fs_dir = grub_efi_netfs_dir, ++ .fs_open = grub_efi_netfs_open, ++ .fs_read = grub_efi_netfs_read, ++ .fs_close = grub_efi_netfs_close, ++ .fs_label = NULL, ++ .fs_uuid = NULL, ++ .fs_mtime = NULL, ++ }; ++ ++int ++grub_efi_net_boot_from_https (void) ++{ ++ grub_efi_loaded_image_t *image = NULL; ++ grub_efi_device_path_t *dp; ++ ++ image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!image) ++ return 0; ++ ++ dp = grub_efi_get_device_path (image->device_handle); ++ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); ++ ++ if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) ++ && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) ++ { ++ grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp; ++ return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0; ++ } ++ ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) ++ break; ++ dp = (grub_efi_device_path_t *) ((char *) dp + len); ++ } ++ ++ return 0; ++} ++ ++int ++grub_efi_net_boot_from_opa (void) ++{ ++ grub_efi_loaded_image_t *image = NULL; ++ grub_efi_device_path_t *dp; ++ ++ image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!image) ++ return 0; ++ ++ dp = grub_efi_get_device_path (image->device_handle); ++ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); ++ ++ if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) ++ && (subtype == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)) ++ { ++ grub_efi_mac_address_device_path_t *mac_dp = (grub_efi_mac_address_device_path_t *)dp; ++ return (mac_dp->if_type == 0xC7) ? 1 : 0; ++ } ++ ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) ++ break; ++ dp = (grub_efi_device_path_t *) ((char *) dp + len); ++ } ++ ++ return 0; ++} ++ ++static char * ++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ return NULL; ++} ++ ++grub_command_func_t grub_efi_net_list_routes = grub_cmd_efi_listroutes; ++grub_command_func_t grub_efi_net_list_cards = grub_cmd_efi_listcards; ++grub_command_func_t grub_efi_net_list_addrs = grub_cmd_efi_listaddrs; ++grub_command_func_t grub_efi_net_add_addr = grub_cmd_efi_addaddr; ++ ++int ++grub_efi_net_fs_init () ++{ ++ grub_efi_net_find_cards (); ++ grub_efi_net_config = grub_efi_net_config_real; ++ grub_net_open = grub_net_open_real; ++ grub_register_variable_hook ("net_default_server", grub_efi_net_var_get_server, ++ grub_efi_net_var_set_server); ++ grub_env_export ("net_default_server"); ++ grub_register_variable_hook ("pxe_default_server", grub_efi_net_var_get_server, ++ grub_efi_net_var_set_server); ++ grub_env_export ("pxe_default_server"); ++ grub_register_variable_hook ("net_default_interface", 0, ++ grub_efi_net_var_set_interface); ++ grub_env_export ("net_default_interface"); ++ grub_register_variable_hook ("net_default_ip", grub_efi_net_var_get_ip, ++ 0); ++ grub_env_export ("net_default_ip"); ++ grub_register_variable_hook ("net_default_mac", grub_efi_net_var_get_mac, ++ 0); ++ grub_env_export ("net_default_mac"); ++ ++ grub_env_set ("grub_netfs_type", "efi"); ++ grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly); ++ grub_env_export ("grub_netfs_type"); ++ ++ return 1; ++} ++ ++void ++grub_efi_net_fs_fini (void) ++{ ++ grub_env_unset ("grub_netfs_type"); ++ grub_efi_net_unset_interface_vars (); ++ grub_register_variable_hook ("net_default_server", 0, 0); ++ grub_env_unset ("net_default_server"); ++ grub_register_variable_hook ("net_default_interface", 0, 0); ++ grub_env_unset ("net_default_interface"); ++ grub_register_variable_hook ("pxe_default_server", 0, 0); ++ grub_env_unset ("pxe_default_server"); ++ grub_register_variable_hook ("net_default_ip", 0, 0); ++ grub_env_unset ("net_default_ip"); ++ grub_register_variable_hook ("net_default_mac", 0, 0); ++ grub_env_unset ("net_default_mac"); ++ grub_efi_net_config = NULL; ++ grub_net_open = NULL; ++ grub_fs_unregister (&grub_efi_netfs); ++} +diff --git a/grub-core/net/efi/pxe.c b/grub-core/net/efi/pxe.c +new file mode 100644 +index 0000000000..531949cba5 +--- /dev/null ++++ b/grub-core/net/efi/pxe.c +@@ -0,0 +1,424 @@ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static grub_efi_ip6_config_manual_address_t * ++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++static grub_efi_ip4_config2_manual_address_t * ++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++static void ++pxe_configure (struct grub_efi_net_device *dev, int prefer_ip6) ++{ ++ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; ++ ++ grub_efi_pxe_mode_t *mode = pxe->mode; ++ ++ if (!mode->started) ++ { ++ grub_efi_status_t status; ++ status = efi_call_2 (pxe->start, pxe, prefer_ip6); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't start PXE\n"); ++ } ++ ++#if 0 ++ grub_printf ("PXE STARTED: %u\n", mode->started); ++ grub_printf ("PXE USING IPV6: %u\n", mode->using_ipv6); ++#endif ++ ++ if (mode->using_ipv6) ++ { ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ manual_address = efi_ip6_config_manual_address (dev->ip6_config); ++ ++ if (manual_address && ++ grub_memcmp (manual_address->address, mode->station_ip.v6, sizeof (manual_address->address)) != 0) ++ { ++ grub_efi_status_t status; ++ grub_efi_pxe_ip_address_t station_ip; ++ ++ grub_memcpy (station_ip.v6.addr, manual_address->address, sizeof (station_ip.v6.addr)); ++ status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, NULL); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't set station ip\n"); ++ ++ grub_free (manual_address); ++ } ++ } ++ else ++ { ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ manual_address = efi_ip4_config_manual_address (dev->ip4_config); ++ ++ if (manual_address && ++ grub_memcmp (manual_address->address, mode->station_ip.v4, sizeof (manual_address->address)) != 0) ++ { ++ grub_efi_status_t status; ++ grub_efi_pxe_ip_address_t station_ip; ++ grub_efi_pxe_ip_address_t subnet_mask; ++ ++ grub_memcpy (station_ip.v4.addr, manual_address->address, sizeof (station_ip.v4.addr)); ++ grub_memcpy (subnet_mask.v4.addr, manual_address->subnet_mask, sizeof (subnet_mask.v4.addr)); ++ ++ status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, &subnet_mask); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't set station ip\n"); ++ ++ grub_free (manual_address); ++ } ++ } ++ ++#if 0 ++ if (mode->using_ipv6) ++ { ++ grub_printf ("PXE STATION IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", ++ mode->station_ip.v6.addr[0], ++ mode->station_ip.v6.addr[1], ++ mode->station_ip.v6.addr[2], ++ mode->station_ip.v6.addr[3], ++ mode->station_ip.v6.addr[4], ++ mode->station_ip.v6.addr[5], ++ mode->station_ip.v6.addr[6], ++ mode->station_ip.v6.addr[7], ++ mode->station_ip.v6.addr[8], ++ mode->station_ip.v6.addr[9], ++ mode->station_ip.v6.addr[10], ++ mode->station_ip.v6.addr[11], ++ mode->station_ip.v6.addr[12], ++ mode->station_ip.v6.addr[13], ++ mode->station_ip.v6.addr[14], ++ mode->station_ip.v6.addr[15]); ++ } ++ else ++ { ++ grub_printf ("PXE STATION IP: %d.%d.%d.%d\n", ++ mode->station_ip.v4.addr[0], ++ mode->station_ip.v4.addr[1], ++ mode->station_ip.v4.addr[2], ++ mode->station_ip.v4.addr[3]); ++ grub_printf ("PXE SUBNET MASK: %d.%d.%d.%d\n", ++ mode->subnet_mask.v4.addr[0], ++ mode->subnet_mask.v4.addr[1], ++ mode->subnet_mask.v4.addr[2], ++ mode->subnet_mask.v4.addr[3]); ++ } ++#endif ++ ++ /* TODO: Set The Station IP to the IP2 Config */ ++} ++ ++static int ++parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) ++{ ++ grub_uint16_t newip[8]; ++ const char *ptr = val; ++ int word, quaddot = -1; ++ int bracketed = 0; ++ ++ if (ptr[0] == '[') { ++ bracketed = 1; ++ ptr++; ++ } ++ ++ if (ptr[0] == ':' && ptr[1] != ':') ++ return 0; ++ if (ptr[0] == ':') ++ ptr++; ++ ++ for (word = 0; word < 8; word++) ++ { ++ unsigned long t; ++ if (*ptr == ':') ++ { ++ quaddot = word; ++ word--; ++ ptr++; ++ continue; ++ } ++ t = grub_strtoul (ptr, (char **) &ptr, 16); ++ if (grub_errno) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ break; ++ } ++ if (t & ~0xffff) ++ return 0; ++ newip[word] = grub_cpu_to_be16 (t); ++ if (*ptr != ':') ++ break; ++ ptr++; ++ } ++ if (quaddot == -1 && word < 7) ++ return 0; ++ if (quaddot != -1) ++ { ++ grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], ++ (word - quaddot + 1) * sizeof (newip[0])); ++ grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); ++ } ++ grub_memcpy (ip, newip, 16); ++ if (bracketed && *ptr == ']') { ++ ptr++; ++ } ++ if (rest) ++ *rest = ptr; ++ return 1; ++} ++ ++static grub_err_t ++pxe_open (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ const char *filename, ++ int type __attribute__((unused))) ++{ ++ int i; ++ char *p; ++ grub_efi_status_t status; ++ grub_efi_pxe_ip_address_t server_ip; ++ grub_efi_uint64_t file_size = 0; ++ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; ++ ++ if (pxe->mode->using_ipv6) ++ { ++ const char *rest; ++ grub_uint64_t ip6[2]; ++ if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0) ++ grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr)); ++ /* TODO: ERROR Handling Here */ ++#if 0 ++ grub_printf ("PXE SERVER IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", ++ server_ip.v6.addr[0], ++ server_ip.v6.addr[1], ++ server_ip.v6.addr[2], ++ server_ip.v6.addr[3], ++ server_ip.v6.addr[4], ++ server_ip.v6.addr[5], ++ server_ip.v6.addr[6], ++ server_ip.v6.addr[7], ++ server_ip.v6.addr[8], ++ server_ip.v6.addr[9], ++ server_ip.v6.addr[10], ++ server_ip.v6.addr[11], ++ server_ip.v6.addr[12], ++ server_ip.v6.addr[13], ++ server_ip.v6.addr[14], ++ server_ip.v6.addr[15]); ++#endif ++ } ++ else ++ { ++ for (i = 0, p = file->device->net->server; i < 4; ++i, ++p) ++ server_ip.v4.addr[i] = grub_strtoul (p, &p, 10); ++ } ++ ++ status = efi_call_10 (pxe->mtftp, ++ pxe, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, ++ NULL, ++ 0, ++ &file_size, ++ NULL, ++ &server_ip, ++ (grub_efi_char8_t *)filename, ++ NULL, ++ 0); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return grub_error (GRUB_ERR_IO, "Couldn't get file size"); ++ ++ file->size = (grub_off_t)file_size; ++ file->not_easily_seekable = 0; ++ file->data = 0; ++ file->device->net->offset = 0; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++pxe_close (struct grub_efi_net_device *dev __attribute__((unused)), ++ int prefer_ip6 __attribute__((unused)), ++ grub_file_t file __attribute__((unused))) ++{ ++ file->offset = 0; ++ file->size = 0; ++ file->device->net->offset = 0; ++ ++ if (file->data) ++ { ++ grub_free (file->data); ++ file->data = NULL; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++pxe_read (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ char *buf, ++ grub_size_t len) ++{ ++ int i; ++ char *p; ++ grub_efi_status_t status; ++ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; ++ grub_efi_uint64_t bufsz = len; ++ grub_efi_pxe_ip_address_t server_ip; ++ char *buf2 = NULL; ++ ++ if (file->data) ++ { ++ /* TODO: RANGE Check for offset and file size */ ++ grub_memcpy (buf, (char*)file->data + file->device->net->offset, len); ++ file->device->net->offset += len; ++ return len; ++ } ++ ++ if (file->device->net->offset) ++ { ++ grub_error (GRUB_ERR_BUG, "No Offet Read Possible"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ if (pxe->mode->using_ipv6) ++ { ++ const char *rest; ++ grub_uint64_t ip6[2]; ++ if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0) ++ grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr)); ++ /* TODO: ERROR Handling Here */ ++ } ++ else ++ { ++ for (i = 0, p = file->device->net->server; i < 4; ++i, ++p) ++ server_ip.v4.addr[i] = grub_strtoul (p, &p, 10); ++ } ++ ++ status = efi_call_10 (pxe->mtftp, ++ pxe, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, ++ buf, ++ 0, ++ &bufsz, ++ NULL, ++ &server_ip, ++ (grub_efi_char8_t *)file->device->net->name, ++ NULL, ++ 0); ++ ++ if (bufsz != file->size) ++ { ++ grub_error (GRUB_ERR_BUG, "Short read should not happen here"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ ++ buf2 = grub_malloc (bufsz); ++ ++ if (!buf2) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "ERROR OUT OF MEMORY"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ status = efi_call_10 (pxe->mtftp, ++ pxe, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, ++ buf2, ++ 0, ++ &bufsz, ++ NULL, ++ &server_ip, ++ (grub_efi_char8_t *)file->device->net->name, ++ NULL, ++ 0); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (buf2) ++ grub_free (buf2); ++ ++ grub_error (GRUB_ERR_IO, "Failed to Read File"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ if (buf2) ++ grub_memcpy (buf, buf2, len); ++ ++ file->device->net->offset = len; ++ ++ if (buf2) ++ file->data = buf2; ++ ++ return len; ++} ++ ++struct grub_efi_net_io io_pxe = ++ { ++ .configure = pxe_configure, ++ .open = pxe_open, ++ .read = pxe_read, ++ .close = pxe_close ++ }; ++ +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 0ce5e675ed..55aed92722 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -32,6 +32,9 @@ + #include + #include + #include ++#ifdef GRUB_MACHINE_EFI ++#include ++#endif + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -2033,8 +2036,49 @@ static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; + static grub_command_t cmd_lsroutes, cmd_lscards; + static grub_command_t cmd_lsaddr, cmd_slaac; + ++#ifdef GRUB_MACHINE_EFI ++ ++static enum { ++ INIT_MODE_NONE, ++ INIT_MODE_GRUB, ++ INIT_MODE_EFI ++} init_mode; ++ ++static grub_command_t cmd_bootp, cmd_bootp6; ++ ++#endif ++ + GRUB_MOD_INIT(net) + { ++#ifdef GRUB_MACHINE_EFI ++ if (grub_net_open) ++ return; ++ ++ if ((grub_efi_net_boot_from_https () || grub_efi_net_boot_from_opa ()) ++ && grub_efi_net_fs_init ()) ++ { ++ cmd_lsroutes = grub_register_command ("net_ls_routes", grub_efi_net_list_routes, ++ "", N_("list network routes")); ++ cmd_lscards = grub_register_command ("net_ls_cards", grub_efi_net_list_cards, ++ "", N_("list network cards")); ++ cmd_lsaddr = grub_register_command ("net_ls_addr", grub_efi_net_list_addrs, ++ "", N_("list network addresses")); ++ cmd_addaddr = grub_register_command ("net_add_addr", grub_efi_net_add_addr, ++ /* TRANSLATORS: HWADDRESS stands for ++ "hardware address". */ ++ N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), ++ N_("Add a network address.")); ++ cmd_bootp = grub_register_command ("net_bootp", grub_efi_net_bootp, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ cmd_bootp6 = grub_register_command ("net_bootp6", grub_efi_net_bootp6, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ init_mode = INIT_MODE_EFI; ++ return; ++ } ++#endif ++ + grub_register_variable_hook ("net_default_server", defserver_get_env, + defserver_set_env); + grub_env_export ("net_default_server"); +@@ -2082,10 +2126,37 @@ GRUB_MOD_INIT(net) + grub_net_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; ++ ++#ifdef GRUB_MACHINE_EFI ++ grub_env_set ("grub_netfs_type", "grub"); ++ grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly); ++ grub_env_export ("grub_netfs_type"); ++ init_mode = INIT_MODE_GRUB; ++#endif ++ + } + + GRUB_MOD_FINI(net) + { ++ ++#ifdef GRUB_MACHINE_EFI ++ if (init_mode == INIT_MODE_NONE) ++ return; ++ ++ if (init_mode == INIT_MODE_EFI) ++ { ++ grub_unregister_command (cmd_lsroutes); ++ grub_unregister_command (cmd_lscards); ++ grub_unregister_command (cmd_lsaddr); ++ grub_unregister_command (cmd_addaddr); ++ grub_unregister_command (cmd_bootp); ++ grub_unregister_command (cmd_bootp6); ++ grub_efi_net_fs_fini (); ++ init_mode = INIT_MODE_NONE; ++ return; ++ } ++#endif ++ + grub_register_variable_hook ("net_default_server", 0, 0); + grub_register_variable_hook ("pxe_default_server", 0, 0); + +@@ -2104,4 +2175,7 @@ GRUB_MOD_FINI(net) + grub_net_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; ++#ifdef GRUB_MACHINE_EFI ++ init_mode = INIT_MODE_NONE; ++#endif + } +diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c +index a2461cda1c..77958dd9dd 100644 +--- a/util/grub-mknetdir.c ++++ b/util/grub-mknetdir.c +@@ -32,13 +32,15 @@ + + static char *rootdir = NULL, *subdir = NULL; + static char *debug_image = NULL; ++static char efi_netfs = 0; + + enum + { + OPTION_NET_DIRECTORY = 0x301, + OPTION_SUBDIR, + OPTION_DEBUG, +- OPTION_DEBUG_IMAGE ++ OPTION_DEBUG_IMAGE, ++ OPTION_DEBUG_EFI_NETFS + }; + + static struct argp_option options[] = { +@@ -49,6 +51,7 @@ static struct argp_option options[] = { + 0, N_("relative subdirectory on network server"), 2}, + {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, + {"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2}, ++ {"debug-efi-netfs", OPTION_DEBUG_EFI_NETFS, 0, OPTION_HIDDEN, 0, 2}, + {0, 0, 0, 0, 0, 0} + }; + +@@ -67,6 +70,9 @@ argp_parser (int key, char *arg, struct argp_state *state) + free (subdir); + subdir = xstrdup (arg); + return 0; ++ case OPTION_DEBUG_EFI_NETFS: ++ efi_netfs = 1; ++ return 0; + /* This is an undocumented feature... */ + case OPTION_DEBUG: + verbosity++; +@@ -82,7 +88,6 @@ argp_parser (int key, char *arg, struct argp_state *state) + } + } + +- + struct argp argp = { + options, argp_parser, NULL, + "\v"N_("Prepares GRUB network boot images at net_directory/subdir " +@@ -92,7 +97,7 @@ struct argp argp = { + + static char *base; + +-static const struct ++static struct + { + const char *mkimage_target; + const char *netmodule; +@@ -156,6 +161,7 @@ process_input_dir (const char *input_dir, enum grub_install_plat platform) + grub_install_push_module (targets[platform].netmodule); + + output = grub_util_path_concat_ext (2, grubdir, "core", targets[platform].ext); ++ + grub_install_make_image_wrap (input_dir, prefix, output, + 0, load_cfg, + targets[platform].mkimage_target, 0); +@@ -195,7 +201,16 @@ main (int argc, char *argv[]) + + grub_install_mkdir_p (base); + +- grub_install_push_module ("tftp"); ++ if (!efi_netfs) ++ { ++ grub_install_push_module ("tftp"); ++ grub_install_push_module ("http"); ++ } ++ else ++ { ++ targets[GRUB_INSTALL_PLATFORM_I386_EFI].netmodule = "efi_netfs"; ++ targets[GRUB_INSTALL_PLATFORM_X86_64_EFI].netmodule = "efi_netfs"; ++ } + + if (!grub_install_source_directory) + { +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 0b490195ad..f431f49973 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -622,6 +622,23 @@ typedef union + + typedef grub_efi_uint64_t grub_efi_physical_address_t; + typedef grub_efi_uint64_t grub_efi_virtual_address_t; ++typedef struct { ++ grub_uint8_t addr[4]; ++} grub_efi_pxe_ipv4_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[16]; ++} grub_efi_pxe_ipv6_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[32]; ++} grub_efi_pxe_mac_address_t; ++ ++typedef union { ++ grub_uint32_t addr[4]; ++ grub_efi_pxe_ipv4_address_t v4; ++ grub_efi_pxe_ipv6_address_t v6; ++} grub_efi_pxe_ip_address_t; + + struct grub_efi_guid + { +@@ -889,6 +906,8 @@ struct grub_efi_ipv6_device_path + grub_efi_uint16_t remote_port; + grub_efi_uint16_t protocol; + grub_efi_uint8_t static_ip_address; ++ grub_efi_uint8_t prefix_length; ++ grub_efi_ipv6_address_t gateway_ip_address; + } GRUB_PACKED; + typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t; + +@@ -938,6 +957,15 @@ struct grub_efi_uri_device_path + } GRUB_PACKED; + typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t; + ++#define GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE 31 ++struct grub_efi_dns_device_path ++{ ++ grub_efi_device_path_t header; ++ grub_efi_uint8_t is_ipv6; ++ grub_efi_pxe_ip_address_t dns_server_ip[0]; ++} GRUB_PACKED; ++typedef struct grub_efi_dns_device_path grub_efi_dns_device_path_t; ++ + #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 + + /* Media Device Path. */ +@@ -1020,6 +1048,23 @@ struct grub_efi_bios_device_path + } GRUB_PACKED; + typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t; + ++/* Service Binding definitions */ ++struct grub_efi_service_binding; ++ ++typedef grub_efi_status_t ++(*grub_efi_service_binding_create_child) (struct grub_efi_service_binding *this, ++ grub_efi_handle_t *child_handle); ++ ++typedef grub_efi_status_t ++(*grub_efi_service_binding_destroy_child) (struct grub_efi_service_binding *this, ++ grub_efi_handle_t *child_handle); ++ ++typedef struct grub_efi_service_binding ++{ ++ grub_efi_service_binding_create_child create_child; ++ grub_efi_service_binding_destroy_child destroy_child; ++} grub_efi_service_binding_t; ++ + struct grub_efi_open_protocol_information_entry + { + grub_efi_handle_t agent_handle; +@@ -1569,23 +1614,27 @@ typedef struct grub_efi_pxe_tftp_error + grub_efi_char8_t error_string[127]; + } grub_efi_pxe_tftp_error_t; + +-typedef struct { +- grub_uint8_t addr[4]; +-} grub_efi_pxe_ipv4_address_t; ++typedef grub_efi_uint16_t grub_efi_pxe_base_code_udp_port_t; + +-typedef struct { +- grub_uint8_t addr[16]; +-} grub_efi_pxe_ipv6_address_t; ++typedef enum { ++ GRUB_EFI_PXE_BASE_CODE_TFTP_FIRST, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_FILE, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_LAST ++} grub_efi_pxe_base_code_tftp_opcode_t; + + typedef struct { +- grub_uint8_t addr[32]; +-} grub_efi_pxe_mac_address_t; +- +-typedef union { +- grub_uint32_t addr[4]; +- grub_efi_pxe_ipv4_address_t v4; +- grub_efi_pxe_ipv6_address_t v6; +-} grub_efi_pxe_ip_address_t; ++ grub_efi_ip_address_t mcast_ip; ++ grub_efi_pxe_base_code_udp_port_t c_port; ++ grub_efi_pxe_base_code_udp_port_t s_port; ++ grub_efi_uint16_t listen_timeout; ++ grub_efi_uint16_t transmit_timeout; ++} grub_efi_pxe_base_code_mtftp_info_t; + + #define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 + typedef struct grub_efi_pxe_ip_filter +@@ -1652,17 +1701,31 @@ typedef struct grub_efi_pxe_mode + typedef struct grub_efi_pxe + { + grub_uint64_t rev; +- void (*start) (void); ++ grub_efi_status_t (*start) (struct grub_efi_pxe *this, grub_efi_boolean_t use_ipv6); + void (*stop) (void); +- void (*dhcp) (void); ++ grub_efi_status_t (*dhcp) (struct grub_efi_pxe *this, ++ grub_efi_boolean_t sort_offers); + void (*discover) (void); +- void (*mftp) (void); ++ grub_efi_status_t (*mtftp) (struct grub_efi_pxe *this, ++ grub_efi_pxe_base_code_tftp_opcode_t operation, ++ void *buffer_ptr, ++ grub_efi_boolean_t overwrite, ++ grub_efi_uint64_t *buffer_size, ++ grub_efi_uintn_t *block_size, ++ grub_efi_pxe_ip_address_t *server_ip, ++ //grub_efi_ip_address_t *server_ip, ++ grub_efi_char8_t *filename, ++ grub_efi_pxe_base_code_mtftp_info_t *info, ++ grub_efi_boolean_t dont_use_buffer); + void (*udpwrite) (void); + void (*udpread) (void); + void (*setipfilter) (void); + void (*arp) (void); + void (*setparams) (void); +- void (*setstationip) (void); ++ grub_efi_status_t (*set_station_ip) (struct grub_efi_pxe *this, ++ grub_efi_pxe_ip_address_t *new_station_ip, ++ grub_efi_pxe_ip_address_t *new_subnet_mask); ++ //void (*setstationip) (void); + void (*setpackets) (void); + struct grub_efi_pxe_mode *mode; + } grub_efi_pxe_t; +@@ -1924,6 +1987,44 @@ struct grub_efi_ip4_config2_protocol + }; + typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t; + ++struct grub_efi_ip4_route_table { ++ grub_efi_ipv4_address_t subnet_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_ipv4_address_t gateway_address; ++}; ++ ++typedef struct grub_efi_ip4_route_table grub_efi_ip4_route_table_t; ++ ++#define GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32 ++ ++struct grub_efi_ip4_config2_interface_info { ++ grub_efi_char16_t name[GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE]; ++ grub_efi_uint8_t if_type; ++ grub_efi_uint32_t hw_address_size; ++ grub_efi_mac_address_t hw_address; ++ grub_efi_ipv4_address_t station_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_uint32_t route_table_size; ++ grub_efi_ip4_route_table_t *route_table; ++}; ++ ++typedef struct grub_efi_ip4_config2_interface_info grub_efi_ip4_config2_interface_info_t; ++ ++enum grub_efi_ip4_config2_policy { ++ GRUB_EFI_IP4_CONFIG2_POLICY_STATIC, ++ GRUB_EFI_IP4_CONFIG2_POLICY_DHCP, ++ GRUB_EFI_IP4_CONFIG2_POLICY_MAX ++}; ++ ++typedef enum grub_efi_ip4_config2_policy grub_efi_ip4_config2_policy_t; ++ ++struct grub_efi_ip4_config2_manual_address { ++ grub_efi_ipv4_address_t address; ++ grub_efi_ipv4_address_t subnet_mask; ++}; ++ ++typedef struct grub_efi_ip4_config2_manual_address grub_efi_ip4_config2_manual_address_t; ++ + enum grub_efi_ip6_config_data_type { + GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID, +@@ -1958,6 +2059,49 @@ struct grub_efi_ip6_config_protocol + }; + typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t; + ++enum grub_efi_ip6_config_policy { ++ GRUB_EFI_IP6_CONFIG_POLICY_MANUAL, ++ GRUB_EFI_IP6_CONFIG_POLICY_AUTOMATIC ++}; ++typedef enum grub_efi_ip6_config_policy grub_efi_ip6_config_policy_t; ++ ++struct grub_efi_ip6_address_info { ++ grub_efi_ipv6_address_t address; ++ grub_efi_uint8_t prefix_length; ++}; ++typedef struct grub_efi_ip6_address_info grub_efi_ip6_address_info_t; ++ ++struct grub_efi_ip6_route_table { ++ grub_efi_pxe_ipv6_address_t gateway; ++ grub_efi_pxe_ipv6_address_t destination; ++ grub_efi_uint8_t prefix_length; ++}; ++typedef struct grub_efi_ip6_route_table grub_efi_ip6_route_table_t; ++ ++struct grub_efi_ip6_config_interface_info { ++ grub_efi_char16_t name[32]; ++ grub_efi_uint8_t if_type; ++ grub_efi_uint32_t hw_address_size; ++ grub_efi_mac_address_t hw_address; ++ grub_efi_uint32_t address_info_count; ++ grub_efi_ip6_address_info_t *address_info; ++ grub_efi_uint32_t route_count; ++ grub_efi_ip6_route_table_t *route_table; ++}; ++typedef struct grub_efi_ip6_config_interface_info grub_efi_ip6_config_interface_info_t; ++ ++struct grub_efi_ip6_config_dup_addr_detect_transmits { ++ grub_efi_uint32_t dup_addr_detect_transmits; ++}; ++typedef struct grub_efi_ip6_config_dup_addr_detect_transmits grub_efi_ip6_config_dup_addr_detect_transmits_t; ++ ++struct grub_efi_ip6_config_manual_address { ++ grub_efi_ipv6_address_t address; ++ grub_efi_boolean_t is_anycast; ++ grub_efi_uint8_t prefix_length; ++}; ++typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; ++ + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ + || defined(__riscv) +diff --git a/include/grub/efi/dhcp.h b/include/grub/efi/dhcp.h +new file mode 100644 +index 0000000000..fdb88eb810 +--- /dev/null ++++ b/include/grub/efi/dhcp.h +@@ -0,0 +1,343 @@ ++#ifndef GRUB_EFI_DHCP_HEADER ++#define GRUB_EFI_DHCP_HEADER 1 ++ ++#define GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \ ++ { 0x9d9a39d8, 0xbd42, 0x4a73, \ ++ { 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \ ++ } ++ ++#define GRUB_EFI_DHCP4_PROTOCOL_GUID \ ++ { 0x8a219718, 0x4ef5, 0x4761, \ ++ { 0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \ ++ } ++ ++#define GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \ ++ { 0x9fb9a8a1, 0x2f4a, 0x43a6, \ ++ { 0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4 ,0x7a, 0xd5 } \ ++ } ++ ++#define GRUB_EFI_DHCP6_PROTOCOL_GUID \ ++ { 0x87c8bad7, 0x595, 0x4053, \ ++ { 0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \ ++ } ++ ++typedef struct grub_efi_dhcp4_protocol grub_efi_dhcp4_protocol_t; ++ ++enum grub_efi_dhcp4_state { ++ GRUB_EFI_DHCP4_STOPPED, ++ GRUB_EFI_DHCP4_INIT, ++ GRUB_EFI_DHCP4_SELECTING, ++ GRUB_EFI_DHCP4_REQUESTING, ++ GRUB_EFI_DHCP4_BOUND, ++ GRUB_EFI_DHCP4_RENEWING, ++ GRUB_EFI_DHCP4_REBINDING, ++ GRUB_EFI_DHCP4_INIT_REBOOT, ++ GRUB_EFI_DHCP4_REBOOTING ++}; ++ ++typedef enum grub_efi_dhcp4_state grub_efi_dhcp4_state_t; ++ ++struct grub_efi_dhcp4_header { ++ grub_efi_uint8_t op_code; ++ grub_efi_uint8_t hw_type; ++ grub_efi_uint8_t hw_addr_len; ++ grub_efi_uint8_t hops; ++ grub_efi_uint32_t xid; ++ grub_efi_uint16_t seconds; ++ grub_efi_uint16_t reserved; ++ grub_efi_ipv4_address_t client_addr; ++ grub_efi_ipv4_address_t your_addr; ++ grub_efi_ipv4_address_t server_addr; ++ grub_efi_ipv4_address_t gateway_addr; ++ grub_efi_uint8_t client_hw_addr[16]; ++ grub_efi_char8_t server_name[64]; ++ grub_efi_char8_t boot_file_name[128]; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp4_header grub_efi_dhcp4_header_t; ++ ++struct grub_efi_dhcp4_packet { ++ grub_efi_uint32_t size; ++ grub_efi_uint32_t length; ++ struct { ++ grub_efi_dhcp4_header_t header; ++ grub_efi_uint32_t magik; ++ grub_efi_uint8_t option[1]; ++ } dhcp4; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp4_packet grub_efi_dhcp4_packet_t; ++ ++struct grub_efi_dhcp4_listen_point { ++ grub_efi_ipv4_address_t listen_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_uint16_t listen_port; ++}; ++ ++typedef struct grub_efi_dhcp4_listen_point grub_efi_dhcp4_listen_point_t; ++ ++struct grub_efi_dhcp4_transmit_receive_token { ++ grub_efi_status_t status; ++ grub_efi_event_t completion_event; ++ grub_efi_ipv4_address_t remote_address; ++ grub_efi_uint16_t remote_port; ++ grub_efi_ipv4_address_t gateway_address; ++ grub_efi_uint32_t listen_point_count; ++ grub_efi_dhcp4_listen_point_t *listen_points; ++ grub_efi_uint32_t timeout_value; ++ grub_efi_dhcp4_packet_t *packet; ++ grub_efi_uint32_t response_count; ++ grub_efi_dhcp4_packet_t *response_list; ++}; ++ ++typedef struct grub_efi_dhcp4_transmit_receive_token grub_efi_dhcp4_transmit_receive_token_t; ++ ++enum grub_efi_dhcp4_event { ++ GRUB_EFI_DHCP4_SEND_DISCOVER = 0X01, ++ GRUB_EFI_DHCP4_RCVD_OFFER, ++ GRUB_EFI_DHCP4_SELECT_OFFER, ++ GRUB_EFI_DHCP4_SEND_REQUEST, ++ GRUB_EFI_DHCP4_RCVD_ACK, ++ GRUB_EFI_DHCP4_RCVD_NAK, ++ GRUB_EFI_DHCP4_SEND_DECLINE, ++ GRUB_EFI_DHCP4_BOUND_COMPLETED, ++ GRUB_EFI_DHCP4_ENTER_RENEWING, ++ GRUB_EFI_DHCP4_ENTER_REBINDING, ++ GRUB_EFI_DHCP4_ADDRESS_LOST, ++ GRUB_EFI_DHCP4_FAIL ++}; ++ ++typedef enum grub_efi_dhcp4_event grub_efi_dhcp4_event_t; ++ ++struct grub_efi_dhcp4_packet_option { ++ grub_efi_uint8_t op_code; ++ grub_efi_uint8_t length; ++ grub_efi_uint8_t data[1]; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp4_packet_option grub_efi_dhcp4_packet_option_t; ++ ++struct grub_efi_dhcp4_config_data { ++ grub_efi_uint32_t discover_try_count; ++ grub_efi_uint32_t *discover_timeout; ++ grub_efi_uint32_t request_try_count; ++ grub_efi_uint32_t *request_timeout; ++ grub_efi_ipv4_address_t client_address; ++ grub_efi_status_t (*dhcp4_callback) ( ++ grub_efi_dhcp4_protocol_t *this, ++ void *context, ++ grub_efi_dhcp4_state_t current_state, ++ grub_efi_dhcp4_event_t dhcp4_event, ++ grub_efi_dhcp4_packet_t *packet, ++ grub_efi_dhcp4_packet_t **new_packet ++ ); ++ void *callback_context; ++ grub_efi_uint32_t option_count; ++ grub_efi_dhcp4_packet_option_t **option_list; ++}; ++ ++typedef struct grub_efi_dhcp4_config_data grub_efi_dhcp4_config_data_t; ++ ++struct grub_efi_dhcp4_mode_data { ++ grub_efi_dhcp4_state_t state; ++ grub_efi_dhcp4_config_data_t config_data; ++ grub_efi_ipv4_address_t client_address; ++ grub_efi_mac_address_t client_mac_address; ++ grub_efi_ipv4_address_t server_address; ++ grub_efi_ipv4_address_t router_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_uint32_t lease_time; ++ grub_efi_dhcp4_packet_t *reply_packet; ++}; ++ ++typedef struct grub_efi_dhcp4_mode_data grub_efi_dhcp4_mode_data_t; ++ ++struct grub_efi_dhcp4_protocol { ++ grub_efi_status_t (*get_mode_data) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_mode_data_t *dhcp4_mode_data); ++ grub_efi_status_t (*configure) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_config_data_t *dhcp4_cfg_data); ++ grub_efi_status_t (*start) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_event_t completion_event); ++ grub_efi_status_t (*renew_rebind) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_boolean_t rebind_request, ++ grub_efi_event_t completion_event); ++ grub_efi_status_t (*release) (grub_efi_dhcp4_protocol_t *this); ++ grub_efi_status_t (*stop) (grub_efi_dhcp4_protocol_t *this); ++ grub_efi_status_t (*build) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_packet_t *seed_packet, ++ grub_efi_uint32_t delete_count, ++ grub_efi_uint8_t *delete_list, ++ grub_efi_uint32_t append_count, ++ grub_efi_dhcp4_packet_option_t *append_list[], ++ grub_efi_dhcp4_packet_t **new_packet); ++ grub_efi_status_t (*transmit_receive) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_transmit_receive_token_t *token); ++ grub_efi_status_t (*parse) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_packet_t *packet, ++ grub_efi_uint32_t *option_count, ++ grub_efi_dhcp4_packet_option_t *packet_option_list[]); ++}; ++ ++typedef struct grub_efi_dhcp6_protocol grub_efi_dhcp6_protocol_t; ++ ++struct grub_efi_dhcp6_retransmission { ++ grub_efi_uint32_t irt; ++ grub_efi_uint32_t mrc; ++ grub_efi_uint32_t mrt; ++ grub_efi_uint32_t mrd; ++}; ++ ++typedef struct grub_efi_dhcp6_retransmission grub_efi_dhcp6_retransmission_t; ++ ++enum grub_efi_dhcp6_event { ++ GRUB_EFI_DHCP6_SEND_SOLICIT, ++ GRUB_EFI_DHCP6_RCVD_ADVERTISE, ++ GRUB_EFI_DHCP6_SELECT_ADVERTISE, ++ GRUB_EFI_DHCP6_SEND_REQUEST, ++ GRUB_EFI_DHCP6_RCVD_REPLY, ++ GRUB_EFI_DHCP6_RCVD_RECONFIGURE, ++ GRUB_EFI_DHCP6_SEND_DECLINE, ++ GRUB_EFI_DHCP6_SEND_CONFIRM, ++ GRUB_EFI_DHCP6_SEND_RELEASE, ++ GRUB_EFI_DHCP6_SEND_RENEW, ++ GRUB_EFI_DHCP6_SEND_REBIND ++}; ++ ++typedef enum grub_efi_dhcp6_event grub_efi_dhcp6_event_t; ++ ++struct grub_efi_dhcp6_packet_option { ++ grub_efi_uint16_t op_code; ++ grub_efi_uint16_t op_len; ++ grub_efi_uint8_t data[1]; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp6_packet_option grub_efi_dhcp6_packet_option_t; ++ ++struct grub_efi_dhcp6_header { ++ grub_efi_uint32_t transaction_id:24; ++ grub_efi_uint32_t message_type:8; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp6_header grub_efi_dhcp6_header_t; ++ ++struct grub_efi_dhcp6_packet { ++ grub_efi_uint32_t size; ++ grub_efi_uint32_t length; ++ struct { ++ grub_efi_dhcp6_header_t header; ++ grub_efi_uint8_t option[1]; ++ } dhcp6; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp6_packet grub_efi_dhcp6_packet_t; ++ ++struct grub_efi_dhcp6_ia_address { ++ grub_efi_ipv6_address_t ip_address; ++ grub_efi_uint32_t preferred_lifetime; ++ grub_efi_uint32_t valid_lifetime; ++}; ++ ++typedef struct grub_efi_dhcp6_ia_address grub_efi_dhcp6_ia_address_t; ++ ++enum grub_efi_dhcp6_state { ++ GRUB_EFI_DHCP6_INIT, ++ GRUB_EFI_DHCP6_SELECTING, ++ GRUB_EFI_DHCP6_REQUESTING, ++ GRUB_EFI_DHCP6_DECLINING, ++ GRUB_EFI_DHCP6_CONFIRMING, ++ GRUB_EFI_DHCP6_RELEASING, ++ GRUB_EFI_DHCP6_BOUND, ++ GRUB_EFI_DHCP6_RENEWING, ++ GRUB_EFI_DHCP6_REBINDING ++}; ++ ++typedef enum grub_efi_dhcp6_state grub_efi_dhcp6_state_t; ++ ++#define GRUB_EFI_DHCP6_IA_TYPE_NA 3 ++#define GRUB_EFI_DHCP6_IA_TYPE_TA 4 ++ ++struct grub_efi_dhcp6_ia_descriptor { ++ grub_efi_uint16_t type; ++ grub_efi_uint32_t ia_id; ++}; ++ ++typedef struct grub_efi_dhcp6_ia_descriptor grub_efi_dhcp6_ia_descriptor_t; ++ ++struct grub_efi_dhcp6_ia { ++ grub_efi_dhcp6_ia_descriptor_t descriptor; ++ grub_efi_dhcp6_state_t state; ++ grub_efi_dhcp6_packet_t *reply_packet; ++ grub_efi_uint32_t ia_address_count; ++ grub_efi_dhcp6_ia_address_t ia_address[1]; ++}; ++ ++typedef struct grub_efi_dhcp6_ia grub_efi_dhcp6_ia_t; ++ ++struct grub_efi_dhcp6_duid { ++ grub_efi_uint16_t length; ++ grub_efi_uint8_t duid[1]; ++}; ++ ++typedef struct grub_efi_dhcp6_duid grub_efi_dhcp6_duid_t; ++ ++struct grub_efi_dhcp6_mode_data { ++ grub_efi_dhcp6_duid_t *client_id; ++ grub_efi_dhcp6_ia_t *ia; ++}; ++ ++typedef struct grub_efi_dhcp6_mode_data grub_efi_dhcp6_mode_data_t; ++ ++struct grub_efi_dhcp6_config_data { ++ grub_efi_status_t (*dhcp6_callback) (grub_efi_dhcp6_protocol_t this, ++ void *context, ++ grub_efi_dhcp6_state_t current_state, ++ grub_efi_dhcp6_event_t dhcp6_event, ++ grub_efi_dhcp6_packet_t *packet, ++ grub_efi_dhcp6_packet_t **new_packet); ++ void *callback_context; ++ grub_efi_uint32_t option_count; ++ grub_efi_dhcp6_packet_option_t **option_list; ++ grub_efi_dhcp6_ia_descriptor_t ia_descriptor; ++ grub_efi_event_t ia_info_event; ++ grub_efi_boolean_t reconfigure_accept; ++ grub_efi_boolean_t rapid_commit; ++ grub_efi_dhcp6_retransmission_t *solicit_retransmission; ++}; ++ ++typedef struct grub_efi_dhcp6_config_data grub_efi_dhcp6_config_data_t; ++ ++struct grub_efi_dhcp6_protocol { ++ grub_efi_status_t (*get_mode_data) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_dhcp6_mode_data_t *dhcp6_mode_data, ++ grub_efi_dhcp6_config_data_t *dhcp6_config_data); ++ grub_efi_status_t (*configure) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_dhcp6_config_data_t *dhcp6_cfg_data); ++ grub_efi_status_t (*start) (grub_efi_dhcp6_protocol_t *this); ++ grub_efi_status_t (*info_request) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_boolean_t send_client_id, ++ grub_efi_dhcp6_packet_option_t *option_request, ++ grub_efi_uint32_t option_count, ++ grub_efi_dhcp6_packet_option_t *option_list[], ++ grub_efi_dhcp6_retransmission_t *retransmission, ++ grub_efi_event_t timeout_event, ++ grub_efi_status_t (*reply_callback) (grub_efi_dhcp6_protocol_t *this, ++ void *context, ++ grub_efi_dhcp6_packet_t *packet), ++ void *callback_context); ++ grub_efi_status_t (*renew_rebind) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_boolean_t rebind_request); ++ grub_efi_status_t (*decline) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_uint32_t address_count, ++ grub_efi_ipv6_address_t *addresses); ++ grub_efi_status_t (*release) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_uint32_t address_count, ++ grub_efi_ipv6_address_t *addresses); ++ grub_efi_status_t (*stop) (grub_efi_dhcp6_protocol_t *this); ++ grub_efi_status_t (*parse) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_dhcp6_packet_t *packet, ++ grub_efi_uint32_t *option_count, ++ grub_efi_dhcp6_packet_option_t *packet_option_list[]); ++}; ++ ++#endif /* ! GRUB_EFI_DHCP_HEADER */ +diff --git a/include/grub/efi/http.h b/include/grub/efi/http.h +new file mode 100644 +index 0000000000..c5e9a89f50 +--- /dev/null ++++ b/include/grub/efi/http.h +@@ -0,0 +1,215 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_HTTP_HEADER ++#define GRUB_EFI_HTTP_HEADER 1 ++ ++#include ++#include ++#include ++ ++#define GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \ ++ { 0xbdc8e6af, 0xd9bc, 0x4379, \ ++ { 0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \ ++ } ++ ++#define GRUB_EFI_HTTP_PROTOCOL_GUID \ ++ { 0x7A59B29B, 0x910B, 0x4171, \ ++ { 0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B } \ ++ } ++ ++#define EFIHTTP_WAIT_TIME 10000 // 10000ms = 10s ++#define EFIHTTP_RX_BUF_LEN 10240 ++ ++//****************************************** ++// Protocol Interface Structure ++//****************************************** ++struct grub_efi_http; ++ ++//****************************************** ++// EFI_HTTP_VERSION ++//****************************************** ++typedef enum { ++ GRUB_EFI_HTTPVERSION10, ++ GRUB_EFI_HTTPVERSION11, ++ GRUB_EFI_HTTPVERSIONUNSUPPORTED ++} grub_efi_http_version_t; ++ ++//****************************************** ++// EFI_HTTPv4_ACCESS_POINT ++//****************************************** ++typedef struct { ++ grub_efi_boolean_t use_default_address; ++ grub_efi_ipv4_address_t local_address; ++ grub_efi_ipv4_address_t local_subnet; ++ grub_efi_uint16_t local_port; ++} grub_efi_httpv4_access_point_t; ++ ++//****************************************** ++// EFI_HTTPv6_ACCESS_POINT ++//****************************************** ++typedef struct { ++ grub_efi_ipv6_address_t local_address; ++ grub_efi_uint16_t local_port; ++} grub_efi_httpv6_access_point_t; ++ ++//****************************************** ++// EFI_HTTP_CONFIG_DATA ++//****************************************** ++typedef struct { ++ grub_efi_http_version_t http_version; ++ grub_efi_uint32_t timeout_millisec; ++ grub_efi_boolean_t local_address_is_ipv6; ++ union { ++ grub_efi_httpv4_access_point_t *ipv4_node; ++ grub_efi_httpv6_access_point_t *ipv6_node; ++ } access_point; ++} grub_efi_http_config_data_t; ++ ++//****************************************** ++// EFI_HTTP_METHOD ++//****************************************** ++typedef enum { ++ GRUB_EFI_HTTPMETHODGET, ++ GRUB_EFI_HTTPMETHODPOST, ++ GRUB_EFI_HTTPMETHODPATCH, ++ GRUB_EFI_HTTPMETHODOPTIONS, ++ GRUB_EFI_HTTPMETHODCONNECT, ++ GRUB_EFI_HTTPMETHODHEAD, ++ GRUB_EFI_HTTPMETHODPUT, ++ GRUB_EFI_HTTPMETHODDELETE, ++ GRUB_EFI_HTTPMETHODTRACE, ++} grub_efi_http_method_t; ++ ++//****************************************** ++// EFI_HTTP_REQUEST_DATA ++//****************************************** ++typedef struct { ++ grub_efi_http_method_t method; ++ grub_efi_char16_t *url; ++} grub_efi_http_request_data_t; ++ ++typedef enum { ++ GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS = 0, ++ GRUB_EFI_HTTP_STATUS_100_CONTINUE, ++ GRUB_EFI_HTTP_STATUS_101_SWITCHING_PROTOCOLS, ++ GRUB_EFI_HTTP_STATUS_200_OK, ++ GRUB_EFI_HTTP_STATUS_201_CREATED, ++ GRUB_EFI_HTTP_STATUS_202_ACCEPTED, ++ GRUB_EFI_HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION, ++ GRUB_EFI_HTTP_STATUS_204_NO_CONTENT, ++ GRUB_EFI_HTTP_STATUS_205_RESET_CONTENT, ++ GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT, ++ GRUB_EFI_HTTP_STATUS_300_MULTIPLE_CHIOCES, ++ GRUB_EFI_HTTP_STATUS_301_MOVED_PERMANENTLY, ++ GRUB_EFI_HTTP_STATUS_302_FOUND, ++ GRUB_EFI_HTTP_STATUS_303_SEE_OTHER, ++ GRUB_EFI_HTTP_STATUS_304_NOT_MODIFIED, ++ GRUB_EFI_HTTP_STATUS_305_USE_PROXY, ++ GRUB_EFI_HTTP_STATUS_307_TEMPORARY_REDIRECT, ++ GRUB_EFI_HTTP_STATUS_400_BAD_REQUEST, ++ GRUB_EFI_HTTP_STATUS_401_UNAUTHORIZED, ++ GRUB_EFI_HTTP_STATUS_402_PAYMENT_REQUIRED, ++ GRUB_EFI_HTTP_STATUS_403_FORBIDDEN, ++ GRUB_EFI_HTTP_STATUS_404_NOT_FOUND, ++ GRUB_EFI_HTTP_STATUS_405_METHOD_NOT_ALLOWED, ++ GRUB_EFI_HTTP_STATUS_406_NOT_ACCEPTABLE, ++ GRUB_EFI_HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED, ++ GRUB_EFI_HTTP_STATUS_408_REQUEST_TIME_OUT, ++ GRUB_EFI_HTTP_STATUS_409_CONFLICT, ++ GRUB_EFI_HTTP_STATUS_410_GONE, ++ GRUB_EFI_HTTP_STATUS_411_LENGTH_REQUIRED, ++ GRUB_EFI_HTTP_STATUS_412_PRECONDITION_FAILED, ++ GRUB_EFI_HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE, ++ GRUB_EFI_HTTP_STATUS_414_REQUEST_URI_TOO_LARGE, ++ GRUB_EFI_HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE, ++ GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED, ++ GRUB_EFI_HTTP_STATUS_417_EXPECTATION_FAILED, ++ GRUB_EFI_HTTP_STATUS_500_INTERNAL_SERVER_ERROR, ++ GRUB_EFI_HTTP_STATUS_501_NOT_IMPLEMENTED, ++ GRUB_EFI_HTTP_STATUS_502_BAD_GATEWAY, ++ GRUB_EFI_HTTP_STATUS_503_SERVICE_UNAVAILABLE, ++ GRUB_EFI_HTTP_STATUS_504_GATEWAY_TIME_OUT, ++ GRUB_EFI_HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED ++} grub_efi_http_status_code_t; ++ ++//****************************************** ++// EFI_HTTP_RESPONSE_DATA ++//****************************************** ++typedef struct { ++ grub_efi_http_status_code_t status_code; ++} grub_efi_http_response_data_t; ++ ++//****************************************** ++// EFI_HTTP_HEADER ++//****************************************** ++typedef struct { ++ grub_efi_char8_t *field_name; ++ grub_efi_char8_t *field_value; ++} grub_efi_http_header_t; ++ ++//****************************************** ++// EFI_HTTP_MESSAGE ++//****************************************** ++typedef struct { ++ union { ++ grub_efi_http_request_data_t *request; ++ grub_efi_http_response_data_t *response; ++ } data; ++ grub_efi_uint32_t header_count; ++ grub_efi_http_header_t *headers; ++ grub_efi_uint32_t body_length; ++ void *body; ++} grub_efi_http_message_t; ++ ++//****************************************** ++// EFI_HTTP_TOKEN ++//****************************************** ++typedef struct { ++ grub_efi_event_t event; ++ grub_efi_status_t status; ++ grub_efi_http_message_t *message; ++} grub_efi_http_token_t; ++ ++struct grub_efi_http { ++ grub_efi_status_t ++ (*get_mode_data) (struct grub_efi_http *this, ++ grub_efi_http_config_data_t *http_config_data); ++ ++ grub_efi_status_t ++ (*configure) (struct grub_efi_http *this, ++ grub_efi_http_config_data_t *http_config_data); ++ ++ grub_efi_status_t ++ (*request) (struct grub_efi_http *this, ++ grub_efi_http_token_t *token); ++ ++ grub_efi_status_t ++ (*cancel) (struct grub_efi_http *this, ++ grub_efi_http_token_t *token); ++ ++ grub_efi_status_t ++ (*response) (struct grub_efi_http *this, ++ grub_efi_http_token_t *token); ++ ++ grub_efi_status_t ++ (*poll) (struct grub_efi_http *this); ++}; ++typedef struct grub_efi_http grub_efi_http_t; ++ ++#endif /* !GRUB_EFI_HTTP_HEADER */ +diff --git a/include/grub/net/efi.h b/include/grub/net/efi.h +new file mode 100644 +index 0000000000..de90d223e8 +--- /dev/null ++++ b/include/grub/net/efi.h +@@ -0,0 +1,144 @@ ++#ifndef GRUB_NET_EFI_HEADER ++#define GRUB_NET_EFI_HEADER 1 ++ ++#include ++#include ++#include ++#include ++ ++typedef struct grub_efi_net_interface grub_efi_net_interface_t; ++typedef struct grub_efi_net_ip_config grub_efi_net_ip_config_t; ++typedef union grub_efi_net_ip_address grub_efi_net_ip_address_t; ++typedef struct grub_efi_net_ip_manual_address grub_efi_net_ip_manual_address_t; ++ ++struct grub_efi_net_interface ++{ ++ char *name; ++ int prefer_ip6; ++ struct grub_efi_net_device *dev; ++ struct grub_efi_net_io *io; ++ grub_efi_net_ip_config_t *ip_config; ++ int io_type; ++ struct grub_efi_net_interface *next; ++}; ++ ++#define efi_net_interface_get_hw_address(inf) inf->ip_config->get_hw_address (inf->dev) ++#define efi_net_interface_get_address(inf) inf->ip_config->get_address (inf->dev) ++#define efi_net_interface_get_route_table(inf) inf->ip_config->get_route_table (inf->dev) ++#define efi_net_interface_set_address(inf, addr, with_subnet) inf->ip_config->set_address (inf->dev, addr, with_subnet) ++#define efi_net_interface_set_gateway(inf, addr) inf->ip_config->set_gateway (inf->dev, addr) ++#define efi_net_interface_set_dns(inf, addr) inf->ip_config->set_dns (inf->dev, addr) ++ ++struct grub_efi_net_ip_config ++{ ++ char * (*get_hw_address) (struct grub_efi_net_device *dev); ++ char * (*get_address) (struct grub_efi_net_device *dev); ++ char ** (*get_route_table) (struct grub_efi_net_device *dev); ++ grub_efi_net_interface_t * (*best_interface) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); ++ int (*set_address) (struct grub_efi_net_device *dev, grub_efi_net_ip_manual_address_t *net_ip, int with_subnet); ++ int (*set_gateway) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); ++ int (*set_dns) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *dns); ++}; ++ ++union grub_efi_net_ip_address ++{ ++ grub_efi_ipv4_address_t ip4; ++ grub_efi_ipv6_address_t ip6; ++}; ++ ++struct grub_efi_net_ip_manual_address ++{ ++ int is_ip6; ++ union ++ { ++ grub_efi_ip4_config2_manual_address_t ip4; ++ grub_efi_ip6_config_manual_address_t ip6; ++ }; ++}; ++ ++struct grub_efi_net_device ++{ ++ grub_efi_handle_t handle; ++ grub_efi_ip4_config2_protocol_t *ip4_config; ++ grub_efi_ip6_config_protocol_t *ip6_config; ++ grub_efi_handle_t http_handle; ++ grub_efi_http_t *http; ++ grub_efi_handle_t ip4_pxe_handle; ++ grub_efi_pxe_t *ip4_pxe; ++ grub_efi_handle_t ip6_pxe_handle; ++ grub_efi_pxe_t *ip6_pxe; ++ grub_efi_handle_t dhcp4_handle; ++ grub_efi_dhcp4_protocol_t *dhcp4; ++ grub_efi_handle_t dhcp6_handle; ++ grub_efi_dhcp6_protocol_t *dhcp6; ++ char *card_name; ++ grub_efi_net_interface_t *net_interfaces; ++ struct grub_efi_net_device *next; ++}; ++ ++struct grub_efi_net_io ++{ ++ void (*configure) (struct grub_efi_net_device *dev, int prefer_ip6); ++ grub_err_t (*open) (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ const char *filename, ++ int type); ++ grub_ssize_t (*read) (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ char *buf, ++ grub_size_t len); ++ grub_err_t (*close) (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file); ++}; ++ ++extern struct grub_efi_net_device *net_devices; ++ ++extern struct grub_efi_net_io io_http; ++extern struct grub_efi_net_io io_pxe; ++ ++extern grub_efi_net_ip_config_t *efi_net_ip4_config; ++extern grub_efi_net_ip_config_t *efi_net_ip6_config; ++ ++char * ++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address); ++ ++char * ++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address); ++ ++char * ++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address); ++ ++int ++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest); ++ ++int ++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest); ++ ++char * ++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev); ++ ++char * ++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev); ++ ++grub_efi_net_interface_t * ++grub_efi_net_create_interface (struct grub_efi_net_device *dev, ++ const char *interface_name, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int has_subnet); ++ ++int grub_efi_net_fs_init (void); ++void grub_efi_net_fs_fini (void); ++int grub_efi_net_boot_from_https (void); ++int grub_efi_net_boot_from_opa (void); ++ ++extern grub_command_func_t grub_efi_net_list_routes; ++extern grub_command_func_t grub_efi_net_list_cards; ++extern grub_command_func_t grub_efi_net_list_addrs; ++extern grub_command_func_t grub_efi_net_add_addr; ++extern grub_command_func_t grub_efi_net_bootp; ++extern grub_command_func_t grub_efi_net_bootp6; ++ ++#endif /* ! GRUB_NET_EFI_HEADER */ diff --git a/SOURCES/0078-make-better-backtraces.patch b/SOURCES/0078-make-better-backtraces.patch deleted file mode 100644 index a65af3d..0000000 --- a/SOURCES/0078-make-better-backtraces.patch +++ /dev/null @@ -1,910 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 9 Jul 2019 17:05:03 +0200 -Subject: [PATCH] make better backtraces - -Signed-off-by: Peter Jones ---- - Makefile.util.def | 6 ++ - grub-core/Makefile.core.def | 16 ++-- - grub-core/{lib => commands}/backtrace.c | 2 +- - grub-core/gdb/cstub.c | 1 - - grub-core/kern/arm64/backtrace.c | 94 ++++++++++++++++++++++++ - grub-core/kern/backtrace.c | 97 +++++++++++++++++++++++++ - grub-core/kern/dl.c | 45 ++++++++++++ - grub-core/kern/i386/backtrace.c | 125 ++++++++++++++++++++++++++++++++ - grub-core/kern/i386/pc/init.c | 4 +- - grub-core/kern/ieee1275/init.c | 1 - - grub-core/kern/misc.c | 13 ++-- - grub-core/kern/mm.c | 6 +- - grub-core/lib/arm64/backtrace.c | 62 ---------------- - grub-core/lib/i386/backtrace.c | 78 -------------------- - include/grub/backtrace.h | 10 ++- - include/grub/dl.h | 2 + - include/grub/kernel.h | 3 + - grub-core/kern/arm/efi/startup.S | 2 + - grub-core/kern/arm/startup.S | 2 + - grub-core/kern/arm64/efi/startup.S | 2 + - grub-core/kern/i386/qemu/startup.S | 3 +- - grub-core/kern/ia64/efi/startup.S | 3 +- - grub-core/kern/sparc64/ieee1275/crt0.S | 3 +- - grub-core/Makefile.am | 1 + - 24 files changed, 414 insertions(+), 167 deletions(-) - rename grub-core/{lib => commands}/backtrace.c (98%) - create mode 100644 grub-core/kern/arm64/backtrace.c - create mode 100644 grub-core/kern/backtrace.c - create mode 100644 grub-core/kern/i386/backtrace.c - delete mode 100644 grub-core/lib/arm64/backtrace.c - delete mode 100644 grub-core/lib/i386/backtrace.c - -diff --git a/Makefile.util.def b/Makefile.util.def -index afc4d7b0c3e..41906486a71 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -51,6 +51,12 @@ library = { - common = grub-core/partmap/msdos.c; - common = grub-core/fs/proc.c; - common = grub-core/fs/archelp.c; -+ common = grub-core/kern/backtrace.c; -+ -+ x86 = grub-core/kern/i386/backtrace.c; -+ i386_xen = grub-core/kern/i386/backtrace.c; -+ x86_64_xen = grub-core/kern/i386/backtrace.c; -+ arm64 = grub-core/kern/arm64/backtrace.c; - }; - - library = { -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 5354f9613d3..4b7c45a7b06 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -142,6 +142,12 @@ kernel = { - common = kern/rescue_reader.c; - common = kern/term.c; - common = kern/verifiers.c; -+ common = kern/backtrace.c; -+ -+ x86 = kern/i386/backtrace.c; -+ i386_xen = kern/i386/backtrace.c; -+ x86_64_xen = kern/i386/backtrace.c; -+ arm64 = kern/arm64/backtrace.c; - - noemu = kern/compiler-rt.c; - noemu = kern/mm.c; -@@ -188,9 +194,6 @@ kernel = { - - softdiv = lib/division.c; - -- x86 = lib/i386/backtrace.c; -- x86 = lib/backtrace.c; -- - i386 = kern/i386/dl.c; - i386_xen = kern/i386/dl.c; - i386_xen_pvh = kern/i386/dl.c; -@@ -2398,15 +2401,12 @@ module = { - - module = { - name = backtrace; -- x86 = lib/i386/backtrace.c; -- i386_xen_pvh = lib/i386/backtrace.c; -- i386_xen = lib/i386/backtrace.c; -- x86_64_xen = lib/i386/backtrace.c; -- common = lib/backtrace.c; -+ common = commands/backtrace.c; - enable = x86; - enable = i386_xen_pvh; - enable = i386_xen; - enable = x86_64_xen; -+ enable = arm64; - }; - - module = { -diff --git a/grub-core/lib/backtrace.c b/grub-core/commands/backtrace.c -similarity index 98% -rename from grub-core/lib/backtrace.c -rename to grub-core/commands/backtrace.c -index c0ad6ab8be1..8b5ec3913b5 100644 ---- a/grub-core/lib/backtrace.c -+++ b/grub-core/commands/backtrace.c -@@ -54,7 +54,7 @@ grub_cmd_backtrace (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) - { -- grub_backtrace (); -+ grub_backtrace (1); - return 0; - } - -diff --git a/grub-core/gdb/cstub.c b/grub-core/gdb/cstub.c -index b64acd70fee..99281472d36 100644 ---- a/grub-core/gdb/cstub.c -+++ b/grub-core/gdb/cstub.c -@@ -215,7 +215,6 @@ grub_gdb_trap (int trap_no) - grub_printf ("Unhandled exception 0x%x at ", trap_no); - grub_backtrace_print_address ((void *) grub_gdb_regs[PC]); - grub_printf ("\n"); -- grub_backtrace_pointer ((void *) grub_gdb_regs[EBP]); - grub_fatal ("Unhandled exception"); - } - -diff --git a/grub-core/kern/arm64/backtrace.c b/grub-core/kern/arm64/backtrace.c -new file mode 100644 -index 00000000000..019c6fdfef2 ---- /dev/null -+++ b/grub-core/kern/arm64/backtrace.c -@@ -0,0 +1,94 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2009 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_STACK_FRAME 102400 -+ -+struct fplr -+{ -+ void *lr; -+ struct fplr *fp; -+}; -+ -+void -+grub_backtrace_pointer (void *frame, unsigned int skip) -+{ -+ unsigned int x = 0; -+ struct fplr *fplr = (struct fplr *)frame; -+ -+ while (fplr) -+ { -+ const char *name = NULL; -+ char *addr = NULL; -+ -+ grub_dprintf("backtrace", "fp is %p next_fp is %p\n", -+ fplr, fplr->fp); -+ -+ if (x >= skip) -+ { -+ name = grub_get_symbol_by_addr (fplr->lr, 1); -+ if (name) -+ addr = grub_resolve_symbol (name); -+ grub_backtrace_print_address (fplr->lr); -+ -+ if (addr && addr != fplr->lr) -+ grub_printf (" %s() %p+%p \n", name ? name : "unknown", addr, -+ (void *)((grub_uint64_t)fplr->lr - (grub_uint64_t)addr)); -+ else -+ grub_printf(" %s() %p \n", name ? name : "unknown", addr); -+ -+ } -+ -+ x += 1; -+ -+ if (fplr->fp < fplr || -+ (grub_uint64_t)fplr->fp - (grub_uint64_t)fplr > MAX_STACK_FRAME || -+ fplr->fp == fplr) -+ { -+ break; -+ } -+ fplr = fplr->fp; -+ } -+} -+ -+asm ("\t.global \"_text\"\n" -+ "_text:\n" -+ "\t.quad .text\n" -+ "\t.global \"_data\"\n" -+ "_data:\n" -+ "\t.quad .data\n" -+ ); -+ -+extern grub_uint64_t _text; -+extern grub_uint64_t _data; -+ -+void -+grub_backtrace_arch (unsigned int skip) -+{ -+ grub_printf ("Backtrace (.text %p .data %p):\n", -+ (void *)_text, (void *)_data); -+ skip += 1; -+ grub_backtrace_pointer(__builtin_frame_address(0), skip); -+} -diff --git a/grub-core/kern/backtrace.c b/grub-core/kern/backtrace.c -new file mode 100644 -index 00000000000..4a82e865cc6 ---- /dev/null -+++ b/grub-core/kern/backtrace.c -@@ -0,0 +1,97 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2009 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static void -+grub_backtrace_print_address_default (void *addr) -+{ -+#ifndef GRUB_UTIL -+ grub_dl_t mod; -+ void *start_addr; -+ -+ FOR_DL_MODULES (mod) -+ { -+ grub_dl_segment_t segment; -+ for (segment = mod->segment; segment; segment = segment->next) -+ if (segment->addr <= addr && (grub_uint8_t *) segment->addr -+ + segment->size > (grub_uint8_t *) addr) -+ { -+ grub_printf ("%s.%x+%" PRIxGRUB_SIZE, mod->name, -+ segment->section, -+ (grub_size_t) -+ ((grub_uint8_t *)addr - (grub_uint8_t *)segment->addr)); -+ return; -+ } -+ } -+ -+ start_addr = grub_resolve_symbol ("_start"); -+ if (start_addr && start_addr < addr) -+ grub_printf ("kernel+%" PRIxGRUB_SIZE, -+ (grub_size_t) -+ ((grub_uint8_t *)addr - (grub_uint8_t *)start_addr)); -+ else -+#endif -+ grub_printf ("%p", addr); -+} -+ -+static void -+grub_backtrace_pointer_default (void *frame __attribute__((__unused__)), -+ unsigned int skip __attribute__((__unused__))) -+{ -+ return; -+} -+ -+void -+grub_backtrace_pointer (void *frame, unsigned int skip) -+ __attribute__((__weak__, -+ __alias__(("grub_backtrace_pointer_default")))); -+ -+void -+grub_backtrace_print_address (void *addr) -+ __attribute__((__weak__, -+ __alias__(("grub_backtrace_print_address_default")))); -+ -+static void -+grub_backtrace_arch_default(unsigned int skip) -+{ -+ grub_backtrace_pointer(__builtin_frame_address(0), skip + 1); -+} -+ -+void grub_backtrace_arch (unsigned int skip) -+ __attribute__((__weak__, __alias__(("grub_backtrace_arch_default")))); -+ -+void grub_backtrace (unsigned int skip) -+{ -+ grub_backtrace_arch(skip + 1); -+} -+ -+void grub_debug_backtrace (const char * const debug, -+ unsigned int skip) -+{ -+ if (grub_debug_enabled (debug)) -+ grub_backtrace (skip + 1); -+} -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 7afb9e6f724..88d2077709e 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -124,6 +124,50 @@ grub_dl_resolve_symbol (const char *name) - return 0; - } - -+void * -+grub_resolve_symbol (const char *name) -+{ -+ grub_symbol_t sym; -+ -+ sym = grub_dl_resolve_symbol (name); -+ if (sym) -+ return sym->addr; -+ return NULL; -+} -+ -+const char * -+grub_get_symbol_by_addr(const void *addr, int isfunc) -+{ -+ unsigned int i; -+ grub_symbol_t before = NULL, after = NULL; -+ for (i = 0; i < GRUB_SYMTAB_SIZE; i++) -+ { -+ grub_symbol_t sym; -+ for (sym = grub_symtab[i]; sym; sym = sym->next) -+ { -+ //grub_printf ("addr 0x%08llx symbol %s\n", (unsigned long long)sym->addr, sym->name); -+ if (sym->addr > addr) -+ { -+ if (!after || sym->addr > after->addr) -+ after = sym; -+ } -+ -+ if (isfunc != sym->isfunc) -+ continue; -+ if (sym->addr > addr) -+ continue; -+ -+ if ((!before && sym->addr <= addr) || (before && before->addr <= sym->addr)) -+ before = sym; -+ } -+ } -+ -+ if (before && addr < after->addr) -+ return before->name; -+ -+ return NULL; -+} -+ - /* Register a symbol with the name NAME and the address ADDR. */ - grub_err_t - grub_dl_register_symbol (const char *name, void *addr, int isfunc, -@@ -336,6 +380,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) - const char *str; - Elf_Word size, entsize; - -+ grub_dprintf ("modules", "Resolving symbols for \"%s\"\n", mod->name); - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -diff --git a/grub-core/kern/i386/backtrace.c b/grub-core/kern/i386/backtrace.c -new file mode 100644 -index 00000000000..2413f9a57db ---- /dev/null -+++ b/grub-core/kern/i386/backtrace.c -@@ -0,0 +1,125 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2009 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_STACK_FRAME 102400 -+ -+void -+grub_backtrace_pointer (void *frame, unsigned int skip) -+{ -+ void **ebp = (void **)frame; -+ unsigned long x = 0; -+ -+ while (ebp) -+ { -+ void **next_ebp = (void **)ebp[0]; -+ const char *name = NULL; -+ char *addr = NULL; -+ -+ grub_dprintf("backtrace", "ebp is %p next_ebp is %p\n", ebp, next_ebp); -+ -+ if (x >= skip) -+ { -+ name = grub_get_symbol_by_addr (ebp[1], 1); -+ if (name) -+ addr = grub_resolve_symbol (name); -+ grub_backtrace_print_address (ebp[1]); -+ -+ if (addr && addr != ebp[1]) -+ grub_printf (" %s() %p+%p \n", name ? name : "unknown", addr, -+ (char *)((char *)ebp[1] - addr)); -+ else -+ grub_printf(" %s() %p \n", name ? name : "unknown", addr); -+ -+#if 0 -+ grub_printf ("("); -+ for (i = 0, arg = ebp[2]; arg != next_ebp && i < 12; arg++, i++) -+ grub_printf ("%p,", arg); -+ grub_printf (")\n"); -+#endif -+ } -+ -+ x += 1; -+ -+ if (next_ebp < ebp || next_ebp - ebp > MAX_STACK_FRAME || next_ebp == ebp) -+ { -+ //grub_printf ("Invalid stack frame at %p (%p)\n", ebp, next_ebp); -+ break; -+ } -+ ebp = next_ebp; -+ } -+} -+ -+#if defined (__x86_64__) -+asm ("\t.global \"_text\"\n" -+ "_text:\n" -+ "\t.quad .text\n" -+ "\t.global \"_data\"\n" -+ "_data:\n" -+ "\t.quad .data\n" -+ ); -+#elif defined(__i386__) -+asm ("\t.global \"_text\"\n" -+ "_text:\n" -+ "\t.long .text\n" -+ "\t.global \"_data\"\n" -+ "_data:\n" -+ "\t.long .data\n" -+ ); -+#else -+#warning I dunno... -+#endif -+ -+extern unsigned long _text; -+extern unsigned long _data; -+ -+#ifdef GRUB_UTIL -+#define EXT_C(x) x -+#endif -+ -+void -+grub_backtrace_arch (unsigned int skip) -+{ -+ grub_printf ("Backtrace (.text %p .data %p):\n", -+ (void *)_text, (void *)_data); -+ skip += 1; -+#if defined (__x86_64__) -+ asm volatile ("movq %%rbp, %%rdi\n" -+ "movq 0, %%rsi\n" -+ "movl %0, %%esi\n" -+ "call " EXT_C("grub_backtrace_pointer") -+ : -+ : "r" (skip)); -+#elif defined(__i386__) -+ asm volatile ("addl $8, %%esp\n" -+ "pushl %0\n" -+ "pushl %%ebp\n" -+ "call " EXT_C("grub_backtrace_pointer") -+ : -+ : "r" (skip)); -+#else -+ grub_backtrace_pointer(__builtin_frame_address(0), skip); -+#endif -+} -diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c -index 27bc68b8a53..b51d0abfa6e 100644 ---- a/grub-core/kern/i386/pc/init.c -+++ b/grub-core/kern/i386/pc/init.c -@@ -153,7 +153,7 @@ compact_mem_regions (void) - } - - grub_addr_t grub_modbase; --extern grub_uint8_t _start[], _edata[]; -+extern grub_uint8_t _edata[]; - - /* Helper for grub_machine_init. */ - static int -@@ -217,7 +217,7 @@ grub_machine_init (void) - /* This has to happen before any BIOS calls. */ - grub_via_workaround_init (); - -- grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start); -+ grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - (grub_uint8_t *)_start); - - /* Initialize the console as early as possible. */ - grub_console_init (); -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index 0cd2a627231..937c1bc44cb 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -63,7 +63,6 @@ - #define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024) - #endif - --extern char _start[]; - extern char _end[]; - - #ifdef __sparc__ -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index c60601b699d..a432a6be54a 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -1197,15 +1197,15 @@ grub_printf_fmt_check (const char *fmt, const char *fmt_expected) - - - /* Abort GRUB. This function does not return. */ --static void __attribute__ ((noreturn)) -+static inline void __attribute__ ((noreturn)) - grub_abort (void) - { --#ifndef GRUB_UTIL --#if (defined(__i386__) || defined(__x86_64__)) && !defined(GRUB_MACHINE_EMU) -- grub_backtrace(); -+#if !defined(GRUB_MACHINE_EMU) && !defined(GRUB_UTIL) -+ grub_backtrace (1); -+#else -+ grub_printf ("\n"); - #endif --#endif -- grub_printf ("\nAborted."); -+ grub_printf ("Aborted."); - - #ifndef GRUB_UTIL - if (grub_term_inputs) -@@ -1232,6 +1232,7 @@ grub_fatal (const char *fmt, ...) - { - va_list ap; - -+ grub_printf ("\n"); - va_start (ap, fmt); - grub_vprintf (_(fmt), ap); - va_end (ap); -diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c -index c070afc621f..d8c8377578b 100644 ---- a/grub-core/kern/mm.c -+++ b/grub-core/kern/mm.c -@@ -97,13 +97,13 @@ get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r) - break; - - if (! *r) -- grub_fatal ("out of range pointer %p", ptr); -+ grub_fatal ("out of range pointer %p\n", ptr); - - *p = (grub_mm_header_t) ptr - 1; - if ((*p)->magic == GRUB_MM_FREE_MAGIC) -- grub_fatal ("double free at %p", *p); -+ grub_fatal ("double free at %p\n", *p); - if ((*p)->magic != GRUB_MM_ALLOC_MAGIC) -- grub_fatal ("alloc magic is broken at %p: %lx", *p, -+ grub_fatal ("alloc magic is broken at %p: %lx\n", *p, - (unsigned long) (*p)->magic); - } - -diff --git a/grub-core/lib/arm64/backtrace.c b/grub-core/lib/arm64/backtrace.c -deleted file mode 100644 -index 1079b5380e1..00000000000 ---- a/grub-core/lib/arm64/backtrace.c -+++ /dev/null -@@ -1,62 +0,0 @@ --/* -- * GRUB -- GRand Unified Bootloader -- * Copyright (C) 2009 Free Software Foundation, Inc. -- * -- * GRUB is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation, either version 3 of the License, or -- * (at your option) any later version. -- * -- * GRUB is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with GRUB. If not, see . -- */ -- --#include --#include --#include --#include --#include --#include --#include -- --#define MAX_STACK_FRAME 102400 -- --void --grub_backtrace_pointer (int frame) --{ -- while (1) -- { -- void *lp = __builtin_return_address (frame); -- if (!lp) -- break; -- -- lp = __builtin_extract_return_addr (lp); -- -- grub_printf ("%p: ", lp); -- grub_backtrace_print_address (lp); -- grub_printf (" ("); -- for (i = 0; i < 2; i++) -- grub_printf ("%p,", ((void **)ptr) [i + 2]); -- grub_printf ("%p)\n", ((void **)ptr) [i + 2]); -- nptr = *(void **)ptr; -- if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME -- || nptr == ptr) -- { -- grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr); -- break; -- } -- ptr = nptr; -- } --} -- --void --grub_backtrace (void) --{ -- grub_backtrace_pointer (1); --} -- -diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c -deleted file mode 100644 -index c67273db3ae..00000000000 ---- a/grub-core/lib/i386/backtrace.c -+++ /dev/null -@@ -1,78 +0,0 @@ --/* -- * GRUB -- GRand Unified Bootloader -- * Copyright (C) 2009 Free Software Foundation, Inc. -- * -- * GRUB is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation, either version 3 of the License, or -- * (at your option) any later version. -- * -- * GRUB is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with GRUB. If not, see . -- */ --#include --#ifdef GRUB_UTIL --#define REALLY_GRUB_UTIL GRUB_UTIL --#undef GRUB_UTIL --#endif -- --#include --#include -- --#ifdef REALLY_GRUB_UTIL --#define GRUB_UTIL REALLY_GRUB_UTIL --#undef REALLY_GRUB_UTIL --#endif -- --#include --#include --#include --#include --#include --#include -- --#define MAX_STACK_FRAME 102400 -- --void --grub_backtrace_pointer (void *ebp) --{ -- void *ptr, *nptr; -- unsigned i; -- -- ptr = ebp; -- while (1) -- { -- grub_printf ("%p: ", ptr); -- grub_backtrace_print_address (((void **) ptr)[1]); -- grub_printf (" ("); -- for (i = 0; i < 2; i++) -- grub_printf ("%p,", ((void **)ptr) [i + 2]); -- grub_printf ("%p)\n", ((void **)ptr) [i + 2]); -- nptr = *(void **)ptr; -- if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME -- || nptr == ptr) -- { -- grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr); -- break; -- } -- ptr = nptr; -- } --} -- --void --grub_backtrace (void) --{ --#ifdef __x86_64__ -- asm volatile ("movq %%rbp, %%rdi\n" -- "callq *%%rax": :"a"(grub_backtrace_pointer)); --#else -- asm volatile ("movl %%ebp, %%eax\n" -- "calll *%%ecx": :"c"(grub_backtrace_pointer)); --#endif --} -- -diff --git a/include/grub/backtrace.h b/include/grub/backtrace.h -index 395519762f0..275cf85e2d3 100644 ---- a/include/grub/backtrace.h -+++ b/include/grub/backtrace.h -@@ -19,8 +19,14 @@ - #ifndef GRUB_BACKTRACE_HEADER - #define GRUB_BACKTRACE_HEADER 1 - --void grub_backtrace (void); --void grub_backtrace_pointer (void *ptr); -+#include -+#include -+ -+void EXPORT_FUNC(grub_debug_backtrace) (const char * const debug, -+ unsigned int skip); -+void EXPORT_FUNC(grub_backtrace) (unsigned int skip); -+void grub_backtrace_arch (unsigned int skip); -+void grub_backtrace_pointer (void *ptr, unsigned int skip); - void grub_backtrace_print_address (void *addr); - - #endif -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 91933b85f2c..2f76e6b0437 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -259,6 +259,8 @@ grub_dl_is_persistent (grub_dl_t mod) - - #endif - -+void * EXPORT_FUNC(grub_resolve_symbol) (const char *name); -+const char * EXPORT_FUNC(grub_get_symbol_by_addr) (const void *addr, int isfunc); - grub_err_t grub_dl_register_symbol (const char *name, void *addr, - int isfunc, grub_dl_t mod); - -diff --git a/include/grub/kernel.h b/include/grub/kernel.h -index abbca5ea335..300a9766cda 100644 ---- a/include/grub/kernel.h -+++ b/include/grub/kernel.h -@@ -111,6 +111,9 @@ grub_addr_t grub_modules_get_end (void); - - #endif - -+void EXPORT_FUNC(start) (void); -+void EXPORT_FUNC(_start) (void); -+ - /* The start point of the C code. */ - void grub_main (void) __attribute__ ((noreturn)); - -diff --git a/grub-core/kern/arm/efi/startup.S b/grub-core/kern/arm/efi/startup.S -index 9f8265315a9..f3bc41f9d0f 100644 ---- a/grub-core/kern/arm/efi/startup.S -+++ b/grub-core/kern/arm/efi/startup.S -@@ -23,6 +23,8 @@ - .file "startup.S" - .text - .arm -+ .globl start, _start -+FUNCTION(start) - FUNCTION(_start) - /* - * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in r1/r0. -diff --git a/grub-core/kern/arm/startup.S b/grub-core/kern/arm/startup.S -index 3946fe8e183..5679a1d00ad 100644 ---- a/grub-core/kern/arm/startup.S -+++ b/grub-core/kern/arm/startup.S -@@ -48,6 +48,8 @@ - - .text - .arm -+ .globl start, _start -+FUNCTION(start) - FUNCTION(_start) - b codestart - -diff --git a/grub-core/kern/arm64/efi/startup.S b/grub-core/kern/arm64/efi/startup.S -index 666a7ee3c92..41676bdb2b8 100644 ---- a/grub-core/kern/arm64/efi/startup.S -+++ b/grub-core/kern/arm64/efi/startup.S -@@ -19,7 +19,9 @@ - #include - - .file "startup.S" -+ .globl start, _start - .text -+FUNCTION(start) - FUNCTION(_start) - /* - * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0. -diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S -index 0d89858d9b3..939f182fc74 100644 ---- a/grub-core/kern/i386/qemu/startup.S -+++ b/grub-core/kern/i386/qemu/startup.S -@@ -24,7 +24,8 @@ - - .text - .code32 -- .globl _start -+ .globl start, _start -+start: - _start: - jmp codestart - -diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S -index d75c6d7cc74..8f2a593e529 100644 ---- a/grub-core/kern/ia64/efi/startup.S -+++ b/grub-core/kern/ia64/efi/startup.S -@@ -24,8 +24,9 @@ - .psr lsb - .lsb - -- .global _start -+ .global start, _start - .proc _start -+start: - _start: - alloc loc0=ar.pfs,2,4,0,0 - mov loc1=rp -diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S -index 03b916f0534..701bf63abcf 100644 ---- a/grub-core/kern/sparc64/ieee1275/crt0.S -+++ b/grub-core/kern/sparc64/ieee1275/crt0.S -@@ -22,7 +22,8 @@ - - .text - .align 4 -- .globl _start -+ .globl start, _start -+start: - _start: - ba codestart - mov %o4, %o0 -diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index 80e7a83edf9..f512573c0da 100644 ---- a/grub-core/Makefile.am -+++ b/grub-core/Makefile.am -@@ -66,6 +66,7 @@ CLEANFILES += grub_script.yy.c grub_script.yy.h - - include $(srcdir)/Makefile.core.am - -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/backtrace.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h diff --git a/SOURCES/0079-AUDIT-0-http-boot-tracker-bug.patch b/SOURCES/0079-AUDIT-0-http-boot-tracker-bug.patch new file mode 100644 index 0000000..b487271 --- /dev/null +++ b/SOURCES/0079-AUDIT-0-http-boot-tracker-bug.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Krahmer +Date: Tue, 28 Nov 2017 17:24:38 +0800 +Subject: [PATCH] AUDIT-0: http boot tracker bug + +Fixing a memory leak in case of error, and a integer overflow, leading to a +heap overflow due to overly large chunk sizes. + +We need to check against some maximum value, otherwise values like 0xffffffff +will eventually lead in the allocation functions to small sized buffers, since +the len is rounded up to the next reasonable alignment. The following memcpy +will then smash the heap, leading to RCE. + +This is no big issue for pure http boot, since its going to execute an +untrusted kernel anyway, but it will break trusted boot scenarios, where only +signed code is allowed to be executed. + +Signed-off-by: Michael Chang +--- + grub-core/net/efi/net.c | 4 +++- + grub-core/net/http.c | 5 ++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +index 86bce6535d..4bb308026c 100644 +--- a/grub-core/net/efi/net.c ++++ b/grub-core/net/efi/net.c +@@ -645,8 +645,10 @@ grub_efihttp_chunk_read (grub_file_t file, char *buf, + + rd = efi_net_interface (read, file, chunk, sz); + +- if (rd <= 0) ++ if (rd <= 0) { ++ grub_free (chunk); + return rd; ++ } + + if (buf) + { +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 12a2632ea5..b52b558d63 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -31,7 +31,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + enum + { +- HTTP_PORT = 80 ++ HTTP_PORT = 80, ++ HTTP_MAX_CHUNK_SIZE = 0x80000000 + }; + + +@@ -78,6 +79,8 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) + if (data->in_chunk_len == 2) + { + data->chunk_rem = grub_strtoul (ptr, 0, 16); ++ if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE) ++ return GRUB_ERR_NET_PACKET_TOO_BIG; + grub_errno = GRUB_ERR_NONE; + if (data->chunk_rem == 0) + { diff --git a/SOURCES/0079-normal-don-t-draw-our-startup-message-if-debug-is-se.patch b/SOURCES/0079-normal-don-t-draw-our-startup-message-if-debug-is-se.patch deleted file mode 100644 index 9922f2b..0000000 --- a/SOURCES/0079-normal-don-t-draw-our-startup-message-if-debug-is-se.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 9 Nov 2017 15:58:52 -0500 -Subject: [PATCH] normal: don't draw our startup message if debug is set - ---- - grub-core/normal/main.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index d5968797f4f..e349303c29b 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -432,6 +432,9 @@ grub_normal_reader_init (int nested) - const char *msg_esc = _("ESC at any time exits."); - char *msg_formatted; - -+ if (grub_env_get ("debug") != NULL) -+ return 0; -+ - msg_formatted = grub_xasprintf (_("Minimal BASH-like line editing is supported. For " - "the first word, TAB lists possible command completions. Anywhere " - "else TAB lists possible device or file completions. %s"), diff --git a/SOURCES/0080-Work-around-some-minor-include-path-weirdnesses.patch b/SOURCES/0080-Work-around-some-minor-include-path-weirdnesses.patch deleted file mode 100644 index 460d792..0000000 --- a/SOURCES/0080-Work-around-some-minor-include-path-weirdnesses.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 16 Mar 2018 13:28:57 -0400 -Subject: [PATCH] Work around some minor include path weirdnesses - -Signed-off-by: Peter Jones ---- - include/grub/arm/efi/console.h | 24 ++++++++++++++++++++++++ - include/grub/arm64/efi/console.h | 24 ++++++++++++++++++++++++ - include/grub/i386/efi/console.h | 24 ++++++++++++++++++++++++ - include/grub/x86_64/efi/console.h | 24 ++++++++++++++++++++++++ - 4 files changed, 96 insertions(+) - create mode 100644 include/grub/arm/efi/console.h - create mode 100644 include/grub/arm64/efi/console.h - create mode 100644 include/grub/i386/efi/console.h - create mode 100644 include/grub/x86_64/efi/console.h - -diff --git a/include/grub/arm/efi/console.h b/include/grub/arm/efi/console.h -new file mode 100644 -index 00000000000..1592f6f76b5 ---- /dev/null -+++ b/include/grub/arm/efi/console.h -@@ -0,0 +1,24 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_ARM_EFI_CONSOLE_H -+#define GRUB_ARM_EFI_CONSOLE_H -+ -+#include -+ -+#endif /* ! GRUB_ARM_EFI_CONSOLE_H */ -diff --git a/include/grub/arm64/efi/console.h b/include/grub/arm64/efi/console.h -new file mode 100644 -index 00000000000..95689339384 ---- /dev/null -+++ b/include/grub/arm64/efi/console.h -@@ -0,0 +1,24 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_ARM64_EFI_CONSOLE_H -+#define GRUB_ARM64_EFI_CONSOLE_H -+ -+#include -+ -+#endif /* ! GRUB_ARM64_EFI_CONSOLE_H */ -diff --git a/include/grub/i386/efi/console.h b/include/grub/i386/efi/console.h -new file mode 100644 -index 00000000000..9231375cb07 ---- /dev/null -+++ b/include/grub/i386/efi/console.h -@@ -0,0 +1,24 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_I386_EFI_CONSOLE_H -+#define GRUB_I386_EFI_CONSOLE_H -+ -+#include -+ -+#endif /* ! GRUB_I386_EFI_CONSOLE_H */ -diff --git a/include/grub/x86_64/efi/console.h b/include/grub/x86_64/efi/console.h -new file mode 100644 -index 00000000000..dba9d8678d0 ---- /dev/null -+++ b/include/grub/x86_64/efi/console.h -@@ -0,0 +1,24 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_X86_64_EFI_CONSOLE_H -+#define GRUB_X86_64_EFI_CONSOLE_H -+ -+#include -+ -+#endif /* ! GRUB_X86_64_EFI_CONSOLE_H */ diff --git a/SOURCES/0080-grub-editenv-Add-incr-command-to-increment-integer-v.patch b/SOURCES/0080-grub-editenv-Add-incr-command-to-increment-integer-v.patch new file mode 100644 index 0000000..6e2e4e2 --- /dev/null +++ b/SOURCES/0080-grub-editenv-Add-incr-command-to-increment-integer-v.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 4 Jun 2018 19:49:47 +0200 +Subject: [PATCH] grub-editenv: Add "incr" command to increment integer value + env. variables + +To be able to automatically detect if the last boot was successful, +We want to keep count of succesful / failed boots in some integer +environment variable. + +This commit adds a grub-editenvt "incr" command to increment such +integer value env. variables by 1 for use from various boot scripts. + +Signed-off-by: Hans de Goede +--- + util/grub-editenv.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/util/grub-editenv.c b/util/grub-editenv.c +index db6f187cc6..948eec8a11 100644 +--- a/util/grub-editenv.c ++++ b/util/grub-editenv.c +@@ -53,6 +53,9 @@ static struct argp_option options[] = { + /* TRANSLATORS: "unset" is a keyword. It's a summary of "unset" subcommand. */ + {N_("unset [NAME ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("Delete variables."), 0}, ++ /* TRANSLATORS: "incr" is a keyword. It's a summary of "incr" subcommand. */ ++ {N_("incr [NAME ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE, ++ N_("Increase value of integer variables."), 0}, + + {0, 0, 0, OPTION_DOC, N_("Options:"), -1}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, +@@ -253,6 +256,51 @@ unset_variables (const char *name, int argc, char *argv[]) + grub_envblk_close (envblk); + } + ++struct get_int_value_params { ++ char *varname; ++ int value; ++}; ++ ++static int ++get_int_value (const char *varname, const char *value, void *hook_data) ++{ ++ struct get_int_value_params *params = hook_data; ++ ++ if (strcmp (varname, params->varname) == 0) { ++ params->value = strtol (value, NULL, 10); ++ return 1; ++ } ++ return 0; ++} ++ ++static void ++incr_variables (const char *name, int argc, char *argv[]) ++{ ++ grub_envblk_t envblk; ++ char buf[16]; ++ ++ envblk = open_envblk_file (name); ++ while (argc) ++ { ++ struct get_int_value_params params = { ++ .varname = argv[0], ++ .value = 0, /* Consider unset variables 0 */ ++ }; ++ ++ grub_envblk_iterate (envblk, ¶ms, get_int_value); ++ snprintf(buf, sizeof(buf), "%d", params.value + 1); ++ ++ if (! grub_envblk_set (envblk, argv[0], buf)) ++ grub_util_error ("%s", _("environment block too small")); ++ ++ argc--; ++ argv++; ++ } ++ ++ write_envblk (name, envblk); ++ grub_envblk_close (envblk); ++} ++ + int + main (int argc, char *argv[]) + { +@@ -292,6 +340,8 @@ main (int argc, char *argv[]) + set_variables (filename, argc - curindex, argv + curindex); + else if (strcmp (command, "unset") == 0) + unset_variables (filename, argc - curindex, argv + curindex); ++ else if (strcmp (command, "incr") == 0) ++ incr_variables (filename, argc - curindex, argv + curindex); + else + { + char *program = xstrdup(program_name); diff --git a/SOURCES/0081-Add-auto-hide-menu-support.patch b/SOURCES/0081-Add-auto-hide-menu-support.patch new file mode 100644 index 0000000..a4fbe4a --- /dev/null +++ b/SOURCES/0081-Add-auto-hide-menu-support.patch @@ -0,0 +1,183 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 6 Jun 2018 08:44:11 +0200 +Subject: [PATCH] Add auto-hide menu support + +On single-os systems we do not want to show the menu, unless something +went wrong with the previous boot, in which case the user may need the +menu to debug/fix the problem. + +This commit adds a new grub.d/00_menu_auto_hide file which emits a +config snippet implementing this. I've chosen to do this in a separate +grub.d file because chances of this going upstream are small and this way +it will be easier to rebase. + +Since auto-hiding the menu requires detecting the previous boot was ok, +we get fastboot support (where we don't check for a key at all) for free +so this commit also adds support for this. + +The new config-file code uses the following variables: + +menu_auto_hide Set this to "1" to activate the new auto-hide feature + Set this to "2" to auto-hide the menu even when multiple + operating systems are installed. Note the menu will still + auto show after booting an other os as that won't set + boot_success. +menu_show_once Set this to "1" to force showing the menu once. +boot_success The OS sets this to "1" to indicate a successful boot. +boot_indeterminate The OS increments this integer when rebooting after e.g. + installing updates or a selinux relabel. +fastboot If set to "1" and the conditions for auto-hiding the menu + are met, the menu is not shown and all checks for keypresses + are skipped, booting the default immediately. + +30_os-prober.in changes somewhat inspired by: +https://git.launchpad.net/~ubuntu-core-dev/grub/+git/ubuntu/tree/debian/patches/quick_boot.patch + +Signed-off-by: Hans de Goede +--- + Makefile.util.def | 6 +++++ + util/grub.d/01_menu_auto_hide.in | 48 ++++++++++++++++++++++++++++++++++++++++ + util/grub.d/30_os-prober.in | 18 +++++++++++++++ + 3 files changed, 72 insertions(+) + create mode 100644 util/grub.d/01_menu_auto_hide.in + +diff --git a/Makefile.util.def b/Makefile.util.def +index bda9fd1211..cb8e3c3270 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -458,6 +458,12 @@ script = { + installdir = grubconf; + }; + ++script = { ++ name = '01_menu_auto_hide'; ++ common = util/grub.d/01_menu_auto_hide.in; ++ installdir = grubconf; ++}; ++ + script = { + name = '01_users'; + common = util/grub.d/01_users.in; +diff --git a/util/grub.d/01_menu_auto_hide.in b/util/grub.d/01_menu_auto_hide.in +new file mode 100644 +index 0000000000..ad175870a5 +--- /dev/null ++++ b/util/grub.d/01_menu_auto_hide.in +@@ -0,0 +1,48 @@ ++#! /bin/sh ++ ++# Disable / skip generating menu-auto-hide config parts on serial terminals ++for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do ++ case "$x" in ++ serial*) ++ exit 0 ++ ;; ++ esac ++done ++ ++cat << EOF ++if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then ++ set last_boot_ok=1 ++else ++ set last_boot_ok=0 ++fi ++ ++# Reset boot_indeterminate after a successful boot ++if [ "\${boot_success}" = "1" ] ; then ++ set boot_indeterminate=0 ++# Avoid boot_indeterminate causing the menu to be hidden more then once ++elif [ "\${boot_indeterminate}" = "1" ]; then ++ set boot_indeterminate=2 ++fi ++set boot_success=0 ++save_env boot_success boot_indeterminate ++ ++if [ x\$feature_timeout_style = xy ] ; then ++ if [ "\${menu_show_once}" ]; then ++ unset menu_show_once ++ save_env menu_show_once ++ set timeout_style=menu ++ set timeout=60 ++ elif [ "\${menu_auto_hide}" -a "\${last_boot_ok}" = "1" ]; then ++ set orig_timeout_style=\${timeout_style} ++ set orig_timeout=\${timeout} ++ if [ "\${fastboot}" = "1" ]; then ++ # timeout_style=menu + timeout=0 avoids the countdown code keypress check ++ set timeout_style=menu ++ set timeout=0 ++ else ++ set timeout_style=hidden ++ set timeout=1 ++ fi ++ fi ++fi ++EOF +diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in +index 4b27bd2015..3c9431cfcf 100644 +--- a/util/grub.d/30_os-prober.in ++++ b/util/grub.d/30_os-prober.in +@@ -42,6 +42,7 @@ if [ -z "${OSPROBED}" ] ; then + fi + + osx_entry() { ++ found_other_os=1 + # TRANSLATORS: it refers on the OS residing on device %s + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + hints="" +@@ -102,6 +103,7 @@ for OS in ${OSPROBED} ; do + + case ${BOOT} in + chain) ++ found_other_os=1 + + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + cat << EOF +@@ -132,6 +134,7 @@ EOF + EOF + ;; + efi) ++ found_other_os=1 + + EFIPATH=${DEVICE#*@} + DEVICE=${DEVICE%@*} +@@ -176,6 +179,7 @@ EOF + LINITRD="${LINITRD#/boot}" + fi + ++ found_other_os=1 + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + recovery_params="$(echo "${LPARAMS}" | grep single)" || true + counter=1 +@@ -257,6 +261,7 @@ EOF + done + ;; + hurd) ++ found_other_os=1 + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + cat << EOF + menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' { +@@ -283,6 +288,7 @@ EOF + EOF + ;; + minix) ++ found_other_os=1 + cat << EOF + menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" { + EOF +@@ -299,3 +305,15 @@ EOF + ;; + esac + done ++ ++# We override the results of the menu_auto_hide code here, this is a bit ugly, ++# but grub-mkconfig writes out the file linearly, so this is the only way ++if [ "${found_other_os}" = "1" ]; then ++ cat << EOF ++# Other OS found, undo autohiding of menu unless menu_auto_hide=2 ++if [ "\${orig_timeout_style}" -a "\${menu_auto_hide}" != "2" ]; then ++ set timeout_style=\${orig_timeout_style} ++ set timeout=\${orig_timeout} ++fi ++EOF ++fi diff --git a/SOURCES/0081-Make-it-possible-to-enabled-build-id-sha1.patch b/SOURCES/0081-Make-it-possible-to-enabled-build-id-sha1.patch deleted file mode 100644 index 356a4d8..0000000 --- a/SOURCES/0081-Make-it-possible-to-enabled-build-id-sha1.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 25 Jun 2015 15:41:06 -0400 -Subject: [PATCH] Make it possible to enabled --build-id=sha1 - -Signed-off-by: Peter Jones ---- - configure.ac | 8 ++++++++ - acinclude.m4 | 19 +++++++++++++++++++ - 2 files changed, 27 insertions(+) - -diff --git a/configure.ac b/configure.ac -index 537ed411469..b4455e4732d 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1470,7 +1470,15 @@ grub_PROG_TARGET_CC - if test "x$TARGET_APPLE_LINKER" != x1 ; then - grub_PROG_OBJCOPY_ABSOLUTE - fi -+ -+AC_ARG_ENABLE([build-id], -+ [AS_HELP_STRING([--enable-build-id], -+ [ask the linker to supply build-id notes (default=no)])]) -+if test x$enable_build_id = xyes; then -+grub_PROG_LD_BUILD_ID_SHA1 -+else - grub_PROG_LD_BUILD_ID_NONE -+fi - if test "x$target_cpu" = xi386; then - if test "$platform" != emu && test "x$TARGET_APPLE_LINKER" != x1 ; then - if test ! -z "$TARGET_IMG_LDSCRIPT"; then -diff --git a/acinclude.m4 b/acinclude.m4 -index 6e14bb553c6..21238fcfd03 100644 ---- a/acinclude.m4 -+++ b/acinclude.m4 -@@ -136,6 +136,25 @@ if test "x$grub_cv_prog_ld_build_id_none" = xyes; then - fi - ]) - -+dnl Supply --build-id=sha1 to ld if building modules. -+dnl This suppresses warnings from ld on some systems -+AC_DEFUN([grub_PROG_LD_BUILD_ID_SHA1], -+[AC_MSG_CHECKING([whether linker accepts --build-id=sha1]) -+AC_CACHE_VAL(grub_cv_prog_ld_build_id_sha1, -+[save_LDFLAGS="$LDFLAGS" -+LDFLAGS="$LDFLAGS -Wl,--build-id=sha1" -+AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], -+ [grub_cv_prog_ld_build_id_sha1=yes], -+ [grub_cv_prog_ld_build_id_sha1=no]) -+LDFLAGS="$save_LDFLAGS" -+]) -+AC_MSG_RESULT([$grub_cv_prog_ld_build_id_sha1]) -+ -+if test "x$grub_cv_prog_ld_build_id_sha1" = xyes; then -+ TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,--build-id=sha1" -+fi -+]) -+ - dnl Check nm - AC_DEFUN([grub_PROG_NM_WORKS], - [AC_MSG_CHECKING([whether nm works]) diff --git a/SOURCES/0082-Add-grub-set-bootflag-utility.patch b/SOURCES/0082-Add-grub-set-bootflag-utility.patch new file mode 100644 index 0000000..495bb13 --- /dev/null +++ b/SOURCES/0082-Add-grub-set-bootflag-utility.patch @@ -0,0 +1,290 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 12 Jun 2018 13:25:16 +0200 +Subject: [PATCH] Add grub-set-bootflag utility + +This commit adds a new grub-set-bootflag utility, which can be used +to set known bootflags in the grubenv: boot_success or menu_show_once. + +grub-set-bootflag is different from grub-editenv in 2 ways: + +1) It is intended to be executed by regular users so must be installed +as suid root. As such it is written to not use any existing grubenv +related code for easy auditing. + +It can't be executed through pkexec because we want to call it under gdm +and pkexec does not work under gdm due the gdm user having /sbin/nologin +as shell. + +2) Since it can be executed by regular users it only allows setting +(assigning a value of 1 to) bootflags which it knows about. Currently +those are just boot_success and menu_show_once. + +This commit also adds a couple of example systemd and files which show +how this can be used to set boot_success from a user-session: + +docs/grub-boot-success.service +docs/grub-boot-success.timer + +The 2 grub-boot-success.systemd files should be placed in /lib/systemd/user +and a symlink to grub-boot-success.timer should be added to +/lib/systemd/user/timers.target.wants. + +Signed-off-by: Hans de Goede +[makhomed: grub-boot-success.timer: Only run if not in a container] +Signed-off-by: Gena Makhomed +[rharwood: migrate to h2m] +Signed-off-by: Robbie Harwood +--- + Makefile.util.def | 7 ++ + util/grub-set-bootflag.c | 172 +++++++++++++++++++++++++++++++++++++++++ + conf/Makefile.extra-dist | 3 + + docs/grub-boot-success.service | 6 ++ + docs/grub-boot-success.timer | 7 ++ + docs/man/grub-set-bootflag.h2m | 2 + + 6 files changed, 197 insertions(+) + create mode 100644 util/grub-set-bootflag.c + create mode 100644 docs/grub-boot-success.service + create mode 100644 docs/grub-boot-success.timer + create mode 100644 docs/man/grub-set-bootflag.h2m + +diff --git a/Makefile.util.def b/Makefile.util.def +index cb8e3c3270..d066652e9b 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -1429,3 +1429,10 @@ program = { + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + }; ++ ++program = { ++ name = grub-set-bootflag; ++ installdir = sbin; ++ mansection = 1; ++ common = util/grub-set-bootflag.c; ++}; +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +new file mode 100644 +index 0000000000..d506f7e75b +--- /dev/null ++++ b/util/grub-set-bootflag.c +@@ -0,0 +1,172 @@ ++/* grub-set-bootflag.c - tool to set boot-flags in the grubenv. */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++/* ++ * NOTE this gets run by users as root (through pkexec), so this does not ++ * use any grub library / util functions to allow for easy auditing. ++ * The grub headers are only included to get certain defines. ++ */ ++ ++#include /* For *_DIR_NAME defines */ ++#include ++#include /* For GRUB_ENVBLK_DEFCFG define */ ++#include ++#include ++#include ++#include ++ ++#include "progname.h" ++ ++#define GRUBENV "/" GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME "/" GRUB_ENVBLK_DEFCFG ++#define GRUBENV_SIZE 1024 ++ ++const char *bootflags[] = { ++ "boot_success", ++ "menu_show_once", ++ NULL ++}; ++ ++static void usage(FILE *out) ++{ ++ int i; ++ ++ fprintf (out, "Usage: 'grub-set-bootflag ', where is one of:\n"); ++ for (i = 0; bootflags[i]; i++) ++ fprintf (out, " %s\n", bootflags[i]); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ /* NOTE buf must be at least the longest bootflag length + 4 bytes */ ++ char env[GRUBENV_SIZE + 1], buf[64], *s; ++ const char *bootflag; ++ int i, len, ret; ++ FILE *f; ++ ++ if (argc != 2) ++ { ++ usage (stderr); ++ return 1; ++ } ++ else if (!strcmp (argv[1], "--help")) ++ { ++ usage (stdout); ++ return 0; ++ } ++ else if (!strcmp (argv[1], "--version")) ++ { ++ printf ("grub-set-bootflag (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); ++ return 0; ++ } ++ ++ for (i = 0; bootflags[i]; i++) ++ if (!strcmp (argv[1], bootflags[i])) ++ break; ++ if (!bootflags[i]) ++ { ++ fprintf (stderr, "Invalid bootflag: '%s'\n", argv[1]); ++ usage (stderr); ++ return 1; ++ } ++ ++ bootflag = bootflags[i]; ++ len = strlen (bootflag); ++ ++ f = fopen (GRUBENV, "r"); ++ if (!f) ++ { ++ perror ("Error opening " GRUBENV " for reading"); ++ return 1; ++ } ++ ++ ret = fread (env, 1, GRUBENV_SIZE, f); ++ fclose (f); ++ if (ret != GRUBENV_SIZE) ++ { ++ errno = EINVAL; ++ perror ("Error reading from " GRUBENV); ++ return 1; ++ } ++ ++ /* 0 terminate env */ ++ env[GRUBENV_SIZE] = 0; ++ ++ if (strncmp (env, GRUB_ENVBLK_SIGNATURE, strlen (GRUB_ENVBLK_SIGNATURE))) ++ { ++ fprintf (stderr, "Error invalid environment block\n"); ++ return 1; ++ } ++ ++ /* Find a pre-existing definition of the bootflag */ ++ s = strstr (env, bootflag); ++ while (s && s[len] != '=') ++ s = strstr (s + len, bootflag); ++ ++ if (s && ((s[len + 1] != '0' && s[len + 1] != '1') || s[len + 2] != '\n')) ++ { ++ fprintf (stderr, "Pre-existing bootflag '%s' has unexpected value\n", bootflag); ++ return 1; ++ } ++ ++ /* No pre-existing bootflag? -> find free space */ ++ if (!s) ++ { ++ for (i = 0; i < (len + 3); i++) ++ buf[i] = '#'; ++ buf[i] = 0; ++ s = strstr (env, buf); ++ } ++ ++ if (!s) ++ { ++ fprintf (stderr, "No space in grubenv to store bootflag '%s'\n", bootflag); ++ return 1; ++ } ++ ++ /* The grubenv is not 0 terminated, so memcpy the name + '=' , '1', '\n' */ ++ snprintf(buf, sizeof(buf), "%s=1\n", bootflag); ++ memcpy(s, buf, len + 3); ++ ++ /* "r+", don't truncate so that the diskspace stays reserved */ ++ f = fopen (GRUBENV, "r+"); ++ if (!f) ++ { ++ perror ("Error opening " GRUBENV " for writing"); ++ return 1; ++ } ++ ++ ret = fwrite (env, 1, GRUBENV_SIZE, f); ++ if (ret != GRUBENV_SIZE) ++ { ++ perror ("Error writing to " GRUBENV); ++ return 1; ++ } ++ ++ ret = fflush (f); ++ if (ret) ++ { ++ perror ("Error flushing " GRUBENV); ++ return 1; ++ } ++ ++ fsync (fileno (f)); ++ fclose (f); ++ ++ return 0; ++} +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index 8f1485d52a..ad235de7fc 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -15,6 +15,9 @@ EXTRA_DIST += docs/man + EXTRA_DIST += docs/autoiso.cfg + EXTRA_DIST += docs/grub.cfg + EXTRA_DIST += docs/osdetect.cfg ++EXTRA_DIST += docs/org.gnu.grub.policy ++EXTRA_DIST += docs/grub-boot-success.service ++EXTRA_DIST += docs/grub-boot-success.timer + + EXTRA_DIST += conf/i386-cygwin-img-ld.sc + +diff --git a/docs/grub-boot-success.service b/docs/grub-boot-success.service +new file mode 100644 +index 0000000000..80e79584c9 +--- /dev/null ++++ b/docs/grub-boot-success.service +@@ -0,0 +1,6 @@ ++[Unit] ++Description=Mark boot as successful ++ ++[Service] ++Type=oneshot ++ExecStart=/usr/sbin/grub2-set-bootflag boot_success +diff --git a/docs/grub-boot-success.timer b/docs/grub-boot-success.timer +new file mode 100644 +index 0000000000..406f172005 +--- /dev/null ++++ b/docs/grub-boot-success.timer +@@ -0,0 +1,7 @@ ++[Unit] ++Description=Mark boot as successful after the user session has run 2 minutes ++ConditionUser=!@system ++ConditionVirtualization=!container ++ ++[Timer] ++OnActiveSec=2min +diff --git a/docs/man/grub-set-bootflag.h2m b/docs/man/grub-set-bootflag.h2m +new file mode 100644 +index 0000000000..94ec0b92ed +--- /dev/null ++++ b/docs/man/grub-set-bootflag.h2m +@@ -0,0 +1,2 @@ ++[NAME] ++grub-set-bootflag \- set a bootflag in the GRUB environment block diff --git a/SOURCES/0082-Add-grub_qdprintf-grub_dprintf-without-the-file-line.patch b/SOURCES/0082-Add-grub_qdprintf-grub_dprintf-without-the-file-line.patch deleted file mode 100644 index a8a757e..0000000 --- a/SOURCES/0082-Add-grub_qdprintf-grub_dprintf-without-the-file-line.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Sun, 28 Jun 2015 13:09:58 -0400 -Subject: [PATCH] Add grub_qdprintf() - grub_dprintf() without the file+line - number. - -This just makes copy+paste of our debug loading info easier. - -Signed-off-by: Peter Jones ---- - grub-core/kern/misc.c | 18 ++++++++++++++++++ - include/grub/misc.h | 2 ++ - 2 files changed, 20 insertions(+) - -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index a432a6be54a..9a2fae6398e 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -191,6 +191,24 @@ grub_real_dprintf (const char *file, const int line, const char *condition, - } - } - -+void -+grub_qdprintf (const char *condition, const char *fmt, ...) -+{ -+ va_list args; -+ const char *debug = grub_env_get ("debug"); -+ -+ if (! debug) -+ return; -+ -+ if (grub_strword (debug, "all") || grub_strword (debug, condition)) -+ { -+ va_start (args, fmt); -+ grub_vprintf (fmt, args); -+ va_end (args); -+ grub_refresh (); -+ } -+} -+ - #define PREALLOC_SIZE 255 - - int -diff --git a/include/grub/misc.h b/include/grub/misc.h -index fd18e6320b8..3adc4036e3b 100644 ---- a/include/grub/misc.h -+++ b/include/grub/misc.h -@@ -345,6 +345,8 @@ void EXPORT_FUNC(grub_real_dprintf) (const char *file, - const int line, - const char *condition, - const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 4, 5))); -+void EXPORT_FUNC(grub_qdprintf) (const char *condition, -+ const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 2, 3))); - int EXPORT_FUNC(grub_vprintf) (const char *fmt, va_list args); - int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...) - __attribute__ ((format (GNU_PRINTF, 3, 4))); diff --git a/SOURCES/0083-Make-a-gdb-dprintf-that-tells-us-load-addresses.patch b/SOURCES/0083-Make-a-gdb-dprintf-that-tells-us-load-addresses.patch deleted file mode 100644 index 75de764..0000000 --- a/SOURCES/0083-Make-a-gdb-dprintf-that-tells-us-load-addresses.patch +++ /dev/null @@ -1,178 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 25 Jun 2015 15:11:36 -0400 -Subject: [PATCH] Make a "gdb" dprintf that tells us load addresses. - -This makes a grub_dprintf() call during platform init and during module -loading that tells us the virtual addresses of the .text and .data -sections of grub-core/kernel.exec and any modules it loads. - -Specifically, it displays them in the gdb "add-symbol-file" syntax, with -the presumption that there's a variable $grubdir that reflects the path -to any such binaries. - -Signed-off-by: Peter Jones ---- - grub-core/kern/dl.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ - grub-core/kern/efi/efi.c | 4 ++-- - grub-core/kern/efi/init.c | 26 +++++++++++++++++++++++- - include/grub/efi/efi.h | 2 +- - 4 files changed, 78 insertions(+), 4 deletions(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 88d2077709e..9557254035e 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -501,6 +501,23 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name) - return s; - return NULL; - } -+static long -+grub_dl_find_section_index (Elf_Ehdr *e, const char *name) -+{ -+ Elf_Shdr *s; -+ const char *str; -+ unsigned i; -+ -+ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); -+ str = (char *) e + s->sh_offset; -+ -+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); -+ i < e->e_shnum; -+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -+ if (grub_strcmp (str + s->sh_name, name) == 0) -+ return (long)i; -+ return -1; -+} - - /* Me, Vladimir Serbinenko, hereby I add this module check as per new - GNU module policy. Note that this license check is informative only. -@@ -653,6 +670,37 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) - - return GRUB_ERR_NONE; - } -+static void -+grub_dl_print_gdb_info (grub_dl_t mod, Elf_Ehdr *e) -+{ -+ void *text, *data = NULL; -+ long idx; -+ -+ idx = grub_dl_find_section_index (e, ".text"); -+ if (idx < 0) -+ return; -+ -+ text = grub_dl_get_section_addr (mod, idx); -+ if (!text) -+ return; -+ -+ idx = grub_dl_find_section_index (e, ".data"); -+ if (idx >= 0) -+ data = grub_dl_get_section_addr (mod, idx); -+ -+ if (data) -+ grub_qdprintf ("gdb", "add-symbol-file \\\n" -+ "/usr/lib/debug/usr/lib/grub/%s-%s/%s.debug " -+ "\\\n %p -s .data %p\n", -+ GRUB_TARGET_CPU, GRUB_PLATFORM, -+ mod->name, text, data); -+ else -+ grub_qdprintf ("gdb", "add-symbol-file \\\n" -+ "/usr/lib/debug/usr/lib/grub/%s-%s/%s.debug " -+ "\\\n%p\n", -+ GRUB_TARGET_CPU, GRUB_PLATFORM, -+ mod->name, text); -+} - - /* Load a module from core memory. */ - grub_dl_t -@@ -712,6 +760,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) - grub_dprintf ("modules", "module name: %s\n", mod->name); - grub_dprintf ("modules", "init function: %p\n", mod->init); - -+ grub_dl_print_gdb_info (mod, e); -+ - if (grub_dl_add (mod)) - { - grub_dl_unload (mod); -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index ae9885edb84..d6a2fb57789 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -296,7 +296,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, - /* Search the mods section from the PE32/PE32+ image. This code uses - a PE32 header, but should work with PE32+ as well. */ - grub_addr_t --grub_efi_modules_addr (void) -+grub_efi_section_addr (const char *section_name) - { - grub_efi_loaded_image_t *image; - struct grub_pe32_header *header; -@@ -321,7 +321,7 @@ grub_efi_modules_addr (void) - i < coff_header->num_sections; - i++, section++) - { -- if (grub_strcmp (section->name, "mods") == 0) -+ if (grub_strcmp (section->name, section_name) == 0) - break; - } - -diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c -index 6d39bd3ad29..2d12e6188fd 100644 ---- a/grub-core/kern/efi/init.c -+++ b/grub-core/kern/efi/init.c -@@ -115,10 +115,33 @@ grub_efi_env_init (void) - grub_free (envblk_s.buf); - } - -+static void -+grub_efi_print_gdb_info (void) -+{ -+ grub_addr_t text; -+ grub_addr_t data; -+ -+ text = grub_efi_section_addr (".text"); -+ if (!text) -+ return; -+ -+ data = grub_efi_section_addr (".data"); -+ if (data) -+ grub_qdprintf ("gdb", -+ "add-symbol-file /usr/lib/debug/usr/lib/grub/%s-%s/" -+ "kernel.exec %p -s .data %p\n", -+ GRUB_TARGET_CPU, GRUB_PLATFORM, (void *)text, (void *)data); -+ else -+ grub_qdprintf ("gdb", -+ "add-symbol-file /usr/lib/debug/usr/lib/grub/%s-%s/" -+ "kernel.exec %p\n", -+ GRUB_TARGET_CPU, GRUB_PLATFORM, (void *)text); -+} -+ - void - grub_efi_init (void) - { -- grub_modbase = grub_efi_modules_addr (); -+ grub_modbase = grub_efi_section_addr ("mods"); - /* First of all, initialize the console so that GRUB can display - messages. */ - grub_console_init (); -@@ -142,6 +165,7 @@ grub_efi_init (void) - 0, 0, 0, NULL); - - grub_efi_env_init (); -+ grub_efi_print_gdb_info (); - grub_efidisk_init (); - } - -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 03f9a9d0118..2e0691454b1 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -138,7 +138,7 @@ grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); - grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args); - #endif - --grub_addr_t grub_efi_modules_addr (void); -+grub_addr_t grub_efi_section_addr (const char *section); - - void grub_efi_mm_init (void); - void grub_efi_mm_fini (void); diff --git a/SOURCES/0083-docs-Add-grub-boot-indeterminate.service-example.patch b/SOURCES/0083-docs-Add-grub-boot-indeterminate.service-example.patch new file mode 100644 index 0000000..96eff36 --- /dev/null +++ b/SOURCES/0083-docs-Add-grub-boot-indeterminate.service-example.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 19 Jun 2018 15:20:54 +0200 +Subject: [PATCH] docs: Add grub-boot-indeterminate.service example + +This is an example service file, for use from +/lib/systemd/system/system-update.target.wants +to increment the boot_indeterminate variable when +doing offline updates. + +Signed-off-by: Hans de Goede +--- + docs/grub-boot-indeterminate.service | 11 +++++++++++ + 1 file changed, 11 insertions(+) + create mode 100644 docs/grub-boot-indeterminate.service + +diff --git a/docs/grub-boot-indeterminate.service b/docs/grub-boot-indeterminate.service +new file mode 100644 +index 0000000000..6c8dcb186b +--- /dev/null ++++ b/docs/grub-boot-indeterminate.service +@@ -0,0 +1,11 @@ ++[Unit] ++Description=Mark boot as indeterminate ++DefaultDependencies=false ++Requires=sysinit.target ++After=sysinit.target ++Wants=system-update-pre.target ++Before=system-update-pre.target ++ ++[Service] ++Type=oneshot ++ExecStart=/usr/bin/grub2-editenv - incr boot_indeterminate diff --git a/SOURCES/0084-Fixup-for-newer-compiler.patch b/SOURCES/0084-Fixup-for-newer-compiler.patch deleted file mode 100644 index 12dd193..0000000 --- a/SOURCES/0084-Fixup-for-newer-compiler.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 10 May 2018 13:40:19 -0400 -Subject: [PATCH] Fixup for newer compiler - ---- - grub-core/fs/btrfs.c | 2 +- - include/grub/gpt_partition.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 2b21cbaa67e..4cc86e9b79e 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -218,7 +218,7 @@ struct grub_btrfs_inode - grub_uint64_t size; - grub_uint8_t dummy2[0x70]; - struct grub_btrfs_time mtime; --} GRUB_PACKED; -+} GRUB_PACKED __attribute__ ((aligned(8))); - - struct grub_btrfs_extent_data - { -diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h -index 7a93f43291c..8212697bf6b 100644 ---- a/include/grub/gpt_partition.h -+++ b/include/grub/gpt_partition.h -@@ -76,7 +76,7 @@ struct grub_gpt_partentry - grub_uint64_t end; - grub_uint64_t attrib; - char name[72]; --} GRUB_PACKED; -+} GRUB_PACKED __attribute__ ((aligned(8))); - - grub_err_t - grub_gpt_partition_map_iterate (grub_disk_t disk, diff --git a/SOURCES/0084-gentpl-add-disable-support.patch b/SOURCES/0084-gentpl-add-disable-support.patch new file mode 100644 index 0000000..3b305e6 --- /dev/null +++ b/SOURCES/0084-gentpl-add-disable-support.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 11 Jul 2018 13:43:15 -0400 +Subject: [PATCH] gentpl: add 'disable = ' support + +Signed-off-by: Peter Jones +--- + gentpl.py | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/gentpl.py b/gentpl.py +index c86550d4f9..f3c5f84f85 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -592,11 +592,21 @@ def platform_conditional(platform, closure): + # }; + # + def foreach_enabled_platform(defn, closure): ++ enabled = False ++ disabled = False + if 'enable' in defn: ++ enabled = True + for platform in GRUB_PLATFORMS: + if platform_tagged(defn, platform, "enable"): + platform_conditional(platform, closure) +- else: ++ ++ if 'disable' in defn: ++ disabled = True ++ for platform in GRUB_PLATFORMS: ++ if not platform_tagged(defn, platform, "disable"): ++ platform_conditional(platform, closure) ++ ++ if not enabled and not disabled: + for platform in GRUB_PLATFORMS: + platform_conditional(platform, closure) + +@@ -655,6 +665,8 @@ def first_time(defn, snippet): + def is_platform_independent(defn): + if 'enable' in defn: + return False ++ if 'disable' in defn: ++ return False + for suffix in [ "", "_nodist" ]: + template = platform_values(defn, GRUB_PLATFORMS[0], suffix) + for platform in GRUB_PLATFORMS[1:]: diff --git a/SOURCES/0085-Don-t-attempt-to-export-the-start-and-_start-symbols.patch b/SOURCES/0085-Don-t-attempt-to-export-the-start-and-_start-symbols.patch deleted file mode 100644 index 0e925ee..0000000 --- a/SOURCES/0085-Don-t-attempt-to-export-the-start-and-_start-symbols.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Sat, 12 May 2018 11:29:07 +0200 -Subject: [PATCH] Don't attempt to export the start and _start symbols for - grub-emu - -Commit 318ee04aadc ("make better backtraces") reworked the backtrace logic -but the changes lead to the following build error on the grub-emu platform: - -grub_emu_lite-symlist.o:(.data+0xf08): undefined reference to `start' -collect2: error: ld returned 1 exit status -make[3]: *** [Makefile:25959: grub-emu-lite] Error 1 -make[3]: *** Waiting for unfinished jobs.... -cat kernel_syms.input | grep -v '^#' | sed -n \ - -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/defined kernel '""'\1/;p;}' \ - -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined kernel '""'\1/;p;}' \ - | sort -u >kernel_syms.lst - -The problem is that start and _start symbols are exported unconditionally, -but these aren't defined for grub-emu since is an emultaed platform so it -doesn't have a startup logic. Don't attempt to export those for grub-emu. - -Signed-off-by: Javier Martinez Canillas ---- - include/grub/kernel.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/include/grub/kernel.h b/include/grub/kernel.h -index 300a9766cda..55849777eaa 100644 ---- a/include/grub/kernel.h -+++ b/include/grub/kernel.h -@@ -111,8 +111,10 @@ grub_addr_t grub_modules_get_end (void); - - #endif - -+#if !defined(GRUB_MACHINE_EMU) - void EXPORT_FUNC(start) (void); - void EXPORT_FUNC(_start) (void); -+#endif - - /* The start point of the C code. */ - void grub_main (void) __attribute__ ((noreturn)); diff --git a/SOURCES/0085-gentpl-add-pc-firmware-type.patch b/SOURCES/0085-gentpl-add-pc-firmware-type.patch new file mode 100644 index 0000000..0bfd2ea --- /dev/null +++ b/SOURCES/0085-gentpl-add-pc-firmware-type.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 11 Jul 2019 11:04:24 +0200 +Subject: [PATCH] gentpl: add 'pc' firmware type + +Signed-off-by: Peter Jones +--- + gentpl.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/gentpl.py b/gentpl.py +index f3c5f84f85..f09b336869 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -51,6 +51,7 @@ GROUPS["riscv32"] = [ "riscv32_efi" ] + GROUPS["riscv64"] = [ "riscv64_efi" ] + + # Groups based on firmware ++GROUPS["pc"] = [ "i386_pc" ] + GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", + "riscv32_efi", "riscv64_efi" ] + GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] diff --git a/SOURCES/0086-Fixup-for-newer-compiler.patch b/SOURCES/0086-Fixup-for-newer-compiler.patch deleted file mode 100644 index 11ed6e5..0000000 --- a/SOURCES/0086-Fixup-for-newer-compiler.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 10 May 2018 13:40:19 -0400 -Subject: [PATCH] Fixup for newer compiler - ---- - conf/Makefile.common | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/conf/Makefile.common b/conf/Makefile.common -index 191b1a70c6b..5f0ef969857 100644 ---- a/conf/Makefile.common -+++ b/conf/Makefile.common -@@ -38,7 +38,7 @@ CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding - LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) - CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 - CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) --STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -+STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -R .note.gnu.property -R .gnu.build.attributes - - CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding - LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d diff --git a/SOURCES/0086-efinet-also-use-the-firmware-acceleration-for-http.patch b/SOURCES/0086-efinet-also-use-the-firmware-acceleration-for-http.patch new file mode 100644 index 0000000..a3a9400 --- /dev/null +++ b/SOURCES/0086-efinet-also-use-the-firmware-acceleration-for-http.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 30 Jul 2018 14:06:42 -0400 +Subject: [PATCH] efinet: also use the firmware acceleration for http + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/net.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +index 4bb308026c..6603cd83ed 100644 +--- a/grub-core/net/efi/net.c ++++ b/grub-core/net/efi/net.c +@@ -1324,7 +1324,9 @@ grub_efi_net_boot_from_https (void) + && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) + { + grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp; +- return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0; ++ grub_dprintf ("efinet", "url:%s\n", (const char *)uri_dp->uri); ++ return (grub_strncmp ((const char *)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0 || ++ grub_strncmp ((const char *)uri_dp->uri, "http://", sizeof ("http://") - 1) == 0); + } + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) diff --git a/SOURCES/0087-Add-support-for-non-Ethernet-network-cards.patch b/SOURCES/0087-Add-support-for-non-Ethernet-network-cards.patch deleted file mode 100644 index 02fb951..0000000 --- a/SOURCES/0087-Add-support-for-non-Ethernet-network-cards.patch +++ /dev/null @@ -1,766 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrzej Kacprowski -Date: Wed, 10 Jul 2019 15:22:29 +0200 -Subject: [PATCH] Add support for non-Ethernet network cards - -This patch replaces fixed 6-byte link layer address with -up to 32-byte variable sized address. -This allows supporting Infiniband and Omni-Path fabric -which use 20-byte address, but other network card types -can also take advantage of this change. -The network card driver is responsible for replacing L2 -header provided by grub2 if needed. -This approach is compatible with UEFI network stack which -also allows up to 32-byte variable size link address. - -The BOOTP/DHCP packet format is limited to 16 byte client -hardware address, if link address is more that 16-bytes -then chaddr field in BOOTP it will be set to 0 as per rfc4390. - -Resolves: rhbz#1370642 - -Signed-off-by: Andrzej Kacprowski -[msalter: Fix max string calculation in grub_net_hwaddr_to_str] -Signed-off-by: Mark Salter ---- - grub-core/net/arp.c | 155 ++++++++++++++++++++++----------- - grub-core/net/bootp.c | 15 ++-- - grub-core/net/drivers/efi/efinet.c | 8 +- - grub-core/net/drivers/emu/emunet.c | 1 + - grub-core/net/drivers/i386/pc/pxe.c | 13 +-- - grub-core/net/drivers/ieee1275/ofnet.c | 2 + - grub-core/net/drivers/uboot/ubootnet.c | 1 + - grub-core/net/ethernet.c | 88 +++++++++---------- - grub-core/net/icmp6.c | 15 ++-- - grub-core/net/ip.c | 4 +- - grub-core/net/net.c | 50 ++++++----- - include/grub/net.h | 19 ++-- - 12 files changed, 219 insertions(+), 152 deletions(-) - -diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c -index 54306e3b16d..67b409a8acc 100644 ---- a/grub-core/net/arp.c -+++ b/grub-core/net/arp.c -@@ -31,22 +31,12 @@ enum - ARP_REPLY = 2 - }; - --enum -- { -- /* IANA ARP constant to define hardware type as ethernet. */ -- GRUB_NET_ARPHRD_ETHERNET = 1 -- }; -- --struct arppkt { -+struct arphdr { - grub_uint16_t hrd; - grub_uint16_t pro; - grub_uint8_t hln; - grub_uint8_t pln; - grub_uint16_t op; -- grub_uint8_t sender_mac[6]; -- grub_uint32_t sender_ip; -- grub_uint8_t recv_mac[6]; -- grub_uint32_t recv_ip; - } GRUB_PACKED; - - static int have_pending; -@@ -57,12 +47,16 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *proto_addr) - { - struct grub_net_buff nb; -- struct arppkt *arp_packet; -+ struct arphdr *arp_header; - grub_net_link_level_address_t target_mac_addr; - grub_err_t err; - int i; - grub_uint8_t *nbd; - grub_uint8_t arp_data[128]; -+ grub_uint8_t hln; -+ grub_uint8_t pln; -+ grub_uint8_t arp_packet_len; -+ grub_uint8_t *tmp_ptr; - - if (proto_addr->type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) - return grub_error (GRUB_ERR_BUG, "unsupported address family"); -@@ -73,23 +67,39 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, - grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb, 128); - -- err = grub_netbuff_push (&nb, sizeof (*arp_packet)); -+ hln = inf->card->default_address.len; -+ pln = sizeof (proto_addr->ipv4); -+ arp_packet_len = sizeof (*arp_header) + 2 * (hln + pln); -+ -+ err = grub_netbuff_push (&nb, arp_packet_len); - if (err) - return err; - -- arp_packet = (struct arppkt *) nb.data; -- arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); -- arp_packet->hln = 6; -- arp_packet->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); -- arp_packet->pln = 4; -- arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); -- /* Sender hardware address. */ -- grub_memcpy (arp_packet->sender_mac, &inf->hwaddress.mac, 6); -- arp_packet->sender_ip = inf->address.ipv4; -- grub_memset (arp_packet->recv_mac, 0, 6); -- arp_packet->recv_ip = proto_addr->ipv4; -- /* Target protocol address */ -- grub_memset (&target_mac_addr.mac, 0xff, 6); -+ arp_header = (struct arphdr *) nb.data; -+ arp_header->hrd = grub_cpu_to_be16 (inf->card->default_address.type); -+ arp_header->hln = hln; -+ arp_header->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); -+ arp_header->pln = pln; -+ arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); -+ tmp_ptr = nb.data + sizeof (*arp_header); -+ -+ /* The source hardware address. */ -+ grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln); -+ tmp_ptr += hln; -+ -+ /* The source protocol address. */ -+ grub_memcpy (tmp_ptr, &inf->address.ipv4, pln); -+ tmp_ptr += pln; -+ -+ /* The target hardware address. */ -+ grub_memset (tmp_ptr, 0, hln); -+ tmp_ptr += hln; -+ -+ /* The target protocol address */ -+ grub_memcpy (tmp_ptr, &proto_addr->ipv4, pln); -+ tmp_ptr += pln; -+ -+ grub_memset (&target_mac_addr.mac, 0xff, hln); - - nbd = nb.data; - send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP); -@@ -114,28 +124,53 @@ grub_err_t - grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card, - grub_uint16_t *vlantag) - { -- struct arppkt *arp_packet = (struct arppkt *) nb->data; -+ struct arphdr *arp_header = (struct arphdr *) nb->data; - grub_net_network_level_address_t sender_addr, target_addr; - grub_net_link_level_address_t sender_mac_addr; - struct grub_net_network_level_interface *inf; -+ grub_uint16_t hw_type; -+ grub_uint8_t hln; -+ grub_uint8_t pln; -+ grub_uint8_t arp_packet_len; -+ grub_uint8_t *tmp_ptr; - -- if (arp_packet->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) -- || arp_packet->pln != 4 || arp_packet->hln != 6 -- || nb->tail - nb->data < (int) sizeof (*arp_packet)) -+ hw_type = card->default_address.type; -+ hln = card->default_address.len; -+ pln = sizeof(sender_addr.ipv4); -+ arp_packet_len = sizeof (*arp_header) + 2 * (pln + hln); -+ -+ if (arp_header->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) -+ || arp_header->hrd != grub_cpu_to_be16 (hw_type) -+ || arp_header->hln != hln || arp_header->pln != pln -+ || nb->tail - nb->data < (int) arp_packet_len) { - return GRUB_ERR_NONE; -+ } - -+ tmp_ptr = nb->data + sizeof (*arp_header); -+ -+ /* The source hardware address. */ -+ sender_mac_addr.type = hw_type; -+ sender_mac_addr.len = hln; -+ grub_memcpy (sender_mac_addr.mac, tmp_ptr, hln); -+ tmp_ptr += hln; -+ -+ /* The source protocol address. */ - sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; -+ grub_memcpy(&sender_addr.ipv4, tmp_ptr, pln); -+ tmp_ptr += pln; -+ -+ grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); -+ -+ /* The target hardware address. */ -+ tmp_ptr += hln; -+ -+ /* The target protocol address. */ - target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; -- sender_addr.ipv4 = arp_packet->sender_ip; -- target_addr.ipv4 = arp_packet->recv_ip; -- if (arp_packet->sender_ip == pending_req) -+ grub_memcpy(&target_addr.ipv4, tmp_ptr, pln); -+ -+ if (sender_addr.ipv4 == pending_req) - have_pending = 1; - -- sender_mac_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (sender_mac_addr.mac, arp_packet->sender_mac, -- sizeof (sender_mac_addr.mac)); -- grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); -- - FOR_NET_NETWORK_LEVEL_INTERFACES (inf) - { - /* Verify vlantag id */ -@@ -148,11 +183,11 @@ grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card, - - /* Am I the protocol address target? */ - if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 -- && arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) -+ && arp_header->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) - { - grub_net_link_level_address_t target; - struct grub_net_buff nb_reply; -- struct arppkt *arp_reply; -+ struct arphdr *arp_reply; - grub_uint8_t arp_data[128]; - grub_err_t err; - -@@ -161,25 +196,39 @@ grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card, - grub_netbuff_clear (&nb_reply); - grub_netbuff_reserve (&nb_reply, 128); - -- err = grub_netbuff_push (&nb_reply, sizeof (*arp_packet)); -+ err = grub_netbuff_push (&nb_reply, arp_packet_len); - if (err) - return err; - -- arp_reply = (struct arppkt *) nb_reply.data; -+ arp_reply = (struct arphdr *) nb_reply.data; - -- arp_reply->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); -+ arp_reply->hrd = grub_cpu_to_be16 (hw_type); - arp_reply->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); -- arp_reply->pln = 4; -- arp_reply->hln = 6; -+ arp_reply->pln = pln; -+ arp_reply->hln = hln; - arp_reply->op = grub_cpu_to_be16_compile_time (ARP_REPLY); -- arp_reply->sender_ip = arp_packet->recv_ip; -- arp_reply->recv_ip = arp_packet->sender_ip; -- arp_reply->hln = 6; -- -- target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (target.mac, arp_packet->sender_mac, 6); -- grub_memcpy (arp_reply->sender_mac, inf->hwaddress.mac, 6); -- grub_memcpy (arp_reply->recv_mac, arp_packet->sender_mac, 6); -+ -+ tmp_ptr = nb_reply.data + sizeof (*arp_reply); -+ -+ /* The source hardware address. */ -+ grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln); -+ tmp_ptr += hln; -+ -+ /* The source protocol address. */ -+ grub_memcpy (tmp_ptr, &target_addr.ipv4, pln); -+ tmp_ptr += pln; -+ -+ /* The target hardware address. */ -+ grub_memcpy (tmp_ptr, sender_mac_addr.mac, hln); -+ tmp_ptr += hln; -+ -+ /* The target protocol address */ -+ grub_memcpy (tmp_ptr, &sender_addr.ipv4, pln); -+ tmp_ptr += pln; -+ -+ target.type = hw_type; -+ target.len = hln; -+ grub_memcpy (target.mac, sender_mac_addr.mac, hln); - - /* Change operation to REPLY and send packet */ - send_ethernet_packet (inf, &nb_reply, target, GRUB_NET_ETHERTYPE_ARP); -diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c -index e28fb6a09f9..08b6b2b5d6c 100644 ---- a/grub-core/net/bootp.c -+++ b/grub-core/net/bootp.c -@@ -233,7 +233,6 @@ grub_net_configure_by_dhcp_ack (const char *name, - int is_def, char **device, char **path) - { - grub_net_network_level_address_t addr; -- grub_net_link_level_address_t hwaddr; - struct grub_net_network_level_interface *inter; - int mask = -1; - char server_ip[sizeof ("xxx.xxx.xxx.xxx")]; -@@ -250,12 +249,8 @@ grub_net_configure_by_dhcp_ack (const char *name, - if (path) - *path = 0; - -- grub_memcpy (hwaddr.mac, bp->mac_addr, -- bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len -- : sizeof (hwaddr.mac)); -- hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- -- inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); -+ grub_dprintf("dhcp", "configuring dhcp for %s\n", name); -+ inter = grub_net_add_addr (name, card, &addr, &card->default_address, flags); - if (!inter) - return 0; - -@@ -567,7 +562,9 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) - grub_memset (pack, 0, sizeof (*pack)); - pack->opcode = 1; - pack->hw_type = 1; -- pack->hw_len = 6; -+ pack->hw_len = iface->hwaddress.len > 16 ? 0 -+ : iface->hwaddress.len; -+ - err = grub_get_datetime (&date); - if (err || !grub_datetime2unixtime (&date, &t)) - { -@@ -580,7 +577,7 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) - else - pack->ident = iface->xid; - -- grub_memcpy (&pack->mac_addr, &iface->hwaddress.mac, 6); -+ grub_memcpy (&pack->mac_addr, &iface->hwaddress.mac, pack->hw_len); - - grub_netbuff_push (nb, sizeof (*udph)); - -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index 173fb63153c..a673bea807a 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -279,6 +279,9 @@ grub_efinet_findcards (void) - /* This should not happen... Why? */ - continue; - -+ if (net->mode->hwaddr_size > GRUB_NET_MAX_LINK_ADDRESS_SIZE) -+ continue; -+ - if (net->mode->state == GRUB_EFI_NETWORK_STOPPED - && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) - continue; -@@ -315,10 +318,11 @@ grub_efinet_findcards (void) - card->name = grub_xasprintf ("efinet%d", i++); - card->driver = &efidriver; - card->flags = 0; -- card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -+ card->default_address.type = net->mode->if_type; -+ card->default_address.len = net->mode->hwaddr_size; - grub_memcpy (card->default_address.mac, - net->mode->current_address, -- sizeof (card->default_address.mac)); -+ net->mode->hwaddr_size); - card->efi_net = net; - card->efi_handle = *handle; - -diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c -index b194920861f..5b6c5e16a6d 100644 ---- a/grub-core/net/drivers/emu/emunet.c -+++ b/grub-core/net/drivers/emu/emunet.c -@@ -46,6 +46,7 @@ static struct grub_net_card emucard = - .mtu = 1500, - .default_address = { - .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, -+ . len = 6, - {.mac = {0, 1, 2, 3, 4, 5}} - }, - .flags = 0 -diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c -index 3f4152d036c..9f8fb4b6d2b 100644 ---- a/grub-core/net/drivers/i386/pc/pxe.c -+++ b/grub-core/net/drivers/i386/pc/pxe.c -@@ -386,20 +386,21 @@ GRUB_MOD_INIT(pxe) - grub_memset (ui, 0, sizeof (*ui)); - grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry); - -+ grub_pxe_card.default_address.len = 6; - grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr, -- sizeof (grub_pxe_card.default_address.mac)); -- for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) -+ grub_pxe_card.default_address.len); -+ for (i = 0; i < grub_pxe_card.default_address.len; i++) - if (grub_pxe_card.default_address.mac[i] != 0) - break; -- if (i != sizeof (grub_pxe_card.default_address.mac)) -+ if (i != grub_pxe_card.default_address.len) - { -- for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) -+ for (i = 0; i < grub_pxe_card.default_address.len; i++) - if (grub_pxe_card.default_address.mac[i] != 0xff) - break; - } -- if (i == sizeof (grub_pxe_card.default_address.mac)) -+ if (i == grub_pxe_card.default_address.len) - grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr, -- sizeof (grub_pxe_card.default_address.mac)); -+ grub_pxe_card.default_address.len); - grub_pxe_card.mtu = ui->mtu; - - grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c -index 3860b6f78d8..bcb3f9ea02d 100644 ---- a/grub-core/net/drivers/ieee1275/ofnet.c -+++ b/grub-core/net/drivers/ieee1275/ofnet.c -@@ -160,6 +160,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath, - grub_uint16_t vlantag = 0; - - hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -+ hw_addr.len = 6; - - args = bootpath + grub_strlen (devpath) + 1; - do -@@ -503,6 +504,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias) - grub_memcpy (&lla.mac, pprop, 6); - - lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -+ lla.len = 6; - card->default_address = lla; - - card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; -diff --git a/grub-core/net/drivers/uboot/ubootnet.c b/grub-core/net/drivers/uboot/ubootnet.c -index 056052e40d5..22ebcbf211e 100644 ---- a/grub-core/net/drivers/uboot/ubootnet.c -+++ b/grub-core/net/drivers/uboot/ubootnet.c -@@ -131,6 +131,7 @@ GRUB_MOD_INIT (ubootnet) - - grub_memcpy (&(card->default_address.mac), &devinfo->di_net.hwaddr, 6); - card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -+ card->default_address.len = 6; - - card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; - card->txbuf = grub_zalloc (card->txbufsize); -diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c -index 4d7ceed6f93..9aae83a5eb4 100644 ---- a/grub-core/net/ethernet.c -+++ b/grub-core/net/ethernet.c -@@ -29,13 +29,6 @@ - - #define LLCADDRMASK 0x7f - --struct etherhdr --{ -- grub_uint8_t dst[6]; -- grub_uint8_t src[6]; -- grub_uint16_t type; --} GRUB_PACKED; -- - struct llchdr - { - grub_uint8_t dsap; -@@ -55,13 +48,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, - grub_net_link_level_address_t target_addr, - grub_net_ethertype_t ethertype) - { -- struct etherhdr *eth; -+ grub_uint8_t *eth; - grub_err_t err; -- grub_uint8_t etherhdr_size; -- grub_uint16_t vlantag_id = VLANTAG_IDENTIFIER; -+ grub_uint32_t vlantag = 0; -+ grub_uint8_t hw_addr_len = inf->card->default_address.len; -+ grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2; - -- etherhdr_size = sizeof (*eth); -- COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE); -+ /* Source and destination link addresses + ethertype + vlan tag */ -+ COMPILE_TIME_ASSERT ((GRUB_NET_MAX_LINK_ADDRESS_SIZE * 2 + 2 + 4) < -+ GRUB_NET_MAX_LINK_HEADER_SIZE); - - /* Increase ethernet header in case of vlantag */ - if (inf->vlantag != 0) -@@ -70,11 +65,22 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, - err = grub_netbuff_push (nb, etherhdr_size); - if (err) - return err; -- eth = (struct etherhdr *) nb->data; -- grub_memcpy (eth->dst, target_addr.mac, 6); -- grub_memcpy (eth->src, inf->hwaddress.mac, 6); -+ eth = nb->data; -+ grub_memcpy (eth, target_addr.mac, hw_addr_len); -+ eth += hw_addr_len; -+ grub_memcpy (eth, inf->hwaddress.mac, hw_addr_len); -+ eth += hw_addr_len; -+ -+ /* Check if a vlan-tag is present. */ -+ if (vlantag != 0) -+ { -+ *((grub_uint32_t *)eth) = grub_cpu_to_be32 (vlantag); -+ eth += sizeof (vlantag); -+ } -+ -+ /* Write ethertype */ -+ *((grub_uint16_t*) eth) = grub_cpu_to_be16 (ethertype); - -- eth->type = grub_cpu_to_be16 (ethertype); - if (!inf->card->opened) - { - err = GRUB_ERR_NONE; -@@ -85,18 +91,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, - inf->card->opened = 1; - } - -- /* Check and add a vlan-tag if needed. */ -- if (inf->vlantag != 0) -- { -- /* Move eth type to the right */ -- grub_memcpy ((char *) nb->data + etherhdr_size - 2, -- (char *) nb->data + etherhdr_size - 6, 2); -- -- /* Add the tag in the middle */ -- grub_memcpy ((char *) nb->data + etherhdr_size - 6, &vlantag_id, 2); -- grub_memcpy ((char *) nb->data + etherhdr_size - 4, (char *) &(inf->vlantag), 2); -- } -- - return inf->card->driver->send (inf->card, nb); - } - -@@ -104,31 +98,40 @@ grub_err_t - grub_net_recv_ethernet_packet (struct grub_net_buff *nb, - struct grub_net_card *card) - { -- struct etherhdr *eth; -+ grub_uint8_t *eth; - struct llchdr *llch; - struct snaphdr *snaph; - grub_net_ethertype_t type; - grub_net_link_level_address_t hwaddress; - grub_net_link_level_address_t src_hwaddress; - grub_err_t err; -- grub_uint8_t etherhdr_size = sizeof (*eth); -+ grub_uint8_t hw_addr_len = card->default_address.len; -+ grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2; - grub_uint16_t vlantag = 0; - -+ eth = nb->data; - -- /* Check if a vlan-tag is present. If so, the ethernet header is 4 bytes */ -- /* longer than the original one. The vlantag id is extracted and the header */ -- /* is reseted to the original size. */ -- if (grub_get_unaligned16 (nb->data + etherhdr_size - 2) == VLANTAG_IDENTIFIER) -+ hwaddress.type = card->default_address.type; -+ hwaddress.len = hw_addr_len; -+ grub_memcpy (hwaddress.mac, eth, hw_addr_len); -+ eth += hw_addr_len; -+ -+ src_hwaddress.type = card->default_address.type; -+ src_hwaddress.len = hw_addr_len; -+ grub_memcpy (src_hwaddress.mac, eth, hw_addr_len); -+ eth += hw_addr_len; -+ -+ type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); -+ if (type == VLANTAG_IDENTIFIER) - { -- vlantag = grub_get_unaligned16 (nb->data + etherhdr_size); -+ /* Skip vlan tag */ -+ eth += 2; -+ vlantag = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); - etherhdr_size += 4; -- /* Move eth type to the original position */ -- grub_memcpy((char *) nb->data + etherhdr_size - 6, -- (char *) nb->data + etherhdr_size - 2, 2); -+ eth += 2; -+ type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); - } - -- eth = (struct etherhdr *) nb->data; -- type = grub_be_to_cpu16 (eth->type); - err = grub_netbuff_pull (nb, etherhdr_size); - if (err) - return err; -@@ -148,11 +151,6 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb, - } - } - -- hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); -- src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac)); -- - switch (type) - { - /* ARP packet. */ -diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c -index 2cbd95dce25..56a3ec5c8e8 100644 ---- a/grub-core/net/icmp6.c -+++ b/grub-core/net/icmp6.c -@@ -231,8 +231,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, - && ohdr->len == 1) - { - grub_net_link_level_address_t ll_address; -- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); -+ ll_address.type = card->default_address.type; -+ ll_address.len = card->default_address.len; -+ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); - grub_net_link_layer_add_address (card, source, &ll_address, 0); - } - } -@@ -335,8 +336,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, - && ohdr->len == 1) - { - grub_net_link_level_address_t ll_address; -- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); -+ ll_address.type = card->default_address.type; -+ ll_address.len = card->default_address.len; -+ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); - grub_net_link_layer_add_address (card, source, &ll_address, 0); - } - } -@@ -384,8 +386,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, - && ohdr->len == 1) - { - grub_net_link_level_address_t ll_address; -- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); -+ ll_address.type = card->default_address.type; -+ ll_address.len = card->default_address.len; -+ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); - grub_net_link_layer_add_address (card, source, &ll_address, 0); - } - if (ohdr->type == OPTION_PREFIX && ohdr->len == 4) -diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c -index ea5edf8f1f6..a5896f6dc26 100644 ---- a/grub-core/net/ip.c -+++ b/grub-core/net/ip.c -@@ -276,8 +276,8 @@ handle_dgram (struct grub_net_buff *nb, - if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV - && inf->hwaddress.type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET -- && grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr, -- sizeof (inf->hwaddress.mac)) == 0) -+ && (grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr, -+ bootp->hw_len) == 0 || bootp->hw_len == 0)) - { - grub_net_process_dhcp (nb, inf); - grub_netbuff_free (nb); -diff --git a/grub-core/net/net.c b/grub-core/net/net.c -index 22f2689aaeb..a46f82362ed 100644 ---- a/grub-core/net/net.c -+++ b/grub-core/net/net.c -@@ -133,8 +133,9 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, - << 48) - && proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1)))) - { -- hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memset (hw_addr->mac, -1, 6); -+ hw_addr->type = inf->card->default_address.type; -+ hw_addr->len = inf->card->default_address.len; -+ grub_memset (hw_addr->mac, -1, hw_addr->len); - return GRUB_ERR_NONE; - } - -@@ -142,6 +143,7 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, - && ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff)) - { - hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -+ hw_addr->len = inf->card->default_address.len; - hw_addr->mac[0] = 0x33; - hw_addr->mac[1] = 0x33; - hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff); -@@ -762,23 +764,23 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) - void - grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) - { -- str[0] = 0; -- switch (addr->type) -+ char *ptr; -+ unsigned i; -+ int maxstr; -+ -+ if (addr->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE) - { -- case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: -- { -- char *ptr; -- unsigned i; -- for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++) -- { -- grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str), -- "%02x:", addr->mac[i] & 0xff); -- ptr += (sizeof ("XX:") - 1); -- } -- return; -- } -+ str[0] = 0; -+ grub_printf (_("Unsupported hw address type %d len %d\n"), -+ addr->type, addr->len); -+ return; -+ } -+ maxstr = addr->len * grub_strlen ("XX:"); -+ for (ptr = str, i = 0; i < addr->len; i++) -+ { -+ ptr += grub_snprintf (ptr, maxstr - (ptr - str), -+ "%02x:", addr->mac[i] & 0xff); - } -- grub_printf (_("Unsupported hw address type %d\n"), addr->type); - } - - int -@@ -789,13 +791,17 @@ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, - return -1; - if (a->type > b->type) - return +1; -- switch (a->type) -+ if (a->len < b->len) -+ return -1; -+ if (a->len > b->len) -+ return +1; -+ if (a->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE) - { -- case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: -- return grub_memcmp (a->mac, b->mac, sizeof (a->mac)); -+ grub_printf (_("Unsupported hw address type %d len %d\n"), -+ a->type, a->len); -+ return + 1; - } -- grub_printf (_("Unsupported hw address type %d\n"), a->type); -- return 1; -+ return grub_memcmp (a->mac, b->mac, a->len); - } - - int -diff --git a/include/grub/net.h b/include/grub/net.h -index 8a05ec4fe7a..af0404db7e3 100644 ---- a/include/grub/net.h -+++ b/include/grub/net.h -@@ -29,7 +29,8 @@ - - enum - { -- GRUB_NET_MAX_LINK_HEADER_SIZE = 64, -+ GRUB_NET_MAX_LINK_HEADER_SIZE = 96, -+ GRUB_NET_MAX_LINK_ADDRESS_SIZE = 32, - GRUB_NET_UDP_HEADER_SIZE = 8, - GRUB_NET_TCP_HEADER_SIZE = 20, - GRUB_NET_OUR_IPV4_HEADER_SIZE = 20, -@@ -42,15 +43,17 @@ enum - - typedef enum grub_link_level_protocol_id - { -- GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET -+ /* IANA ARP constant to define hardware type. */ -+ GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET = 1, - } grub_link_level_protocol_id_t; - - typedef struct grub_net_link_level_address - { - grub_link_level_protocol_id_t type; -+ grub_uint8_t len; - union - { -- grub_uint8_t mac[6]; -+ grub_uint8_t mac[GRUB_NET_MAX_LINK_ADDRESS_SIZE]; - }; - } grub_net_link_level_address_t; - -@@ -566,11 +569,13 @@ grub_net_addr_cmp (const grub_net_network_level_address_t *a, - #define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX") - - /* -- Currently suppoerted adresses: -- ethernet: XX:XX:XX:XX:XX:XX -+ Up to 32 byte hardware address supported, see GRUB_NET_MAX_LINK_ADDRESS_SIZE - */ -- --#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) -+#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof (\ -+ "XX:XX:XX:XX:XX:XX:XX:XX:"\ -+ "XX:XX:XX:XX:XX:XX:XX:XX:"\ -+ "XX:XX:XX:XX:XX:XX:XX:XX:"\ -+ "XX:XX:XX:XX:XX:XX:XX:XX")) - - void - grub_net_addr_to_str (const grub_net_network_level_address_t *target, diff --git a/SOURCES/0087-efi-http-Make-root_url-reflect-the-protocol-hostname.patch b/SOURCES/0087-efi-http-Make-root_url-reflect-the-protocol-hostname.patch new file mode 100644 index 0000000..90d9777 --- /dev/null +++ b/SOURCES/0087-efi-http-Make-root_url-reflect-the-protocol-hostname.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 30 Jul 2018 16:39:57 -0400 +Subject: [PATCH] efi/http: Make root_url reflect the protocol+hostname of our + boot url. + +This lets you write config files that don't know urls. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/http.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +index 3f61fd2fa5..243acbaa35 100644 +--- a/grub-core/net/efi/http.c ++++ b/grub-core/net/efi/http.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + static void + http_configure (struct grub_efi_net_device *dev, int prefer_ip6) +@@ -351,6 +352,24 @@ grub_efihttp_open (struct grub_efi_net_device *dev, + grub_err_t err; + grub_off_t size; + char *buf; ++ char *root_url; ++ grub_efi_ipv6_address_t address; ++ const char *rest; ++ ++ if (grub_efi_string_to_ip6_address (file->device->net->server, &address, &rest) && *rest == 0) ++ root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", file->device->net->server); ++ else ++ root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", file->device->net->server); ++ if (root_url) ++ { ++ grub_env_unset ("root_url"); ++ grub_env_set ("root_url", root_url); ++ grub_free (root_url); ++ } ++ else ++ { ++ return grub_errno; ++ } + + err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); + if (err != GRUB_ERR_NONE) diff --git a/SOURCES/0088-Make-it-so-we-can-tell-configure-which-cflags-utils-.patch b/SOURCES/0088-Make-it-so-we-can-tell-configure-which-cflags-utils-.patch new file mode 100644 index 0000000..6d2974f --- /dev/null +++ b/SOURCES/0088-Make-it-so-we-can-tell-configure-which-cflags-utils-.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 26 Jun 2018 17:16:06 -0400 +Subject: [PATCH] Make it so we can tell configure which cflags utils are built + with + +This lets us have kernel.img be built with TARGET_CFLAGS but grub-mkimage and +friends built with HOST_CFLAGS. That in turn lets us build with an ARM compiler +that only has hard-float ABI versions of crt*.o and libgcc*, but still use soft +float for grub.efi. + +Signed-off-by: Peter Jones +--- + configure.ac | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- + conf/Makefile.common | 23 ++++++++++++----------- + gentpl.py | 8 ++++---- + 3 files changed, 64 insertions(+), 16 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 302300711f..008f6c273b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -849,11 +849,23 @@ if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ) && test "x$p + TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow" + fi + ++# Should grub utils get the host CFLAGS, or the target CFLAGS? ++AC_ARG_WITH([utils], ++ AS_HELP_STRING([--with-utils=host|target|build], ++ [choose which flags to build utilities with. (default=target)]), ++ [have_with_utils=y], ++ [have_with_utils=n]) ++if test x"$have_with_utils" = xy ; then ++ with_utils="$withval" ++else ++ with_utils=target ++fi ++ + # GRUB doesn't use float or doubles at all. Yet some toolchains may decide + # that floats are a good fit to run instead of what's written in the code. + # Given that floating point unit is disabled (if present to begin with) + # when GRUB is running which may result in various hard crashes. +-if test x"$platform" != xemu ; then ++if test x"$platform" != xemu -a x"$with_utils" == xtarget ; then + AC_CACHE_CHECK([for options to get soft-float], grub_cv_target_cc_soft_float, [ + grub_cv_target_cc_soft_float=no + if test "x$target_cpu" = xarm64; then +@@ -1954,6 +1966,41 @@ HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_builddir)/include" + ++case "$with_utils" in ++ host) ++ UTILS_CFLAGS=$HOST_CFLAGS ++ UTILS_CPPFLAGS=$HOST_CPPFLAGS ++ UTILS_CCASFLAGS=$HOST_CCASFLAGS ++ UTILS_LDFLAGS=$HOST_LDFLAGS ++ ;; ++ target) ++ UTILS_CFLAGS=$TARGET_CFLAGS ++ UTILS_CPPFLAGS=$TARGET_CPPFLAGS ++ UTILS_CCASFLAGS=$TARGET_CCASFLAGS ++ UTILS_LDFLAGS=$TARGET_LDFLAGS ++ ;; ++ build) ++ UTILS_CFLAGS=$BUILD_CFLAGS ++ UTILS_CPPFLAGS=$BUILD_CPPFLAGS ++ UTILS_CCASFLAGS=$BUILD_CCASFLAGS ++ UTILS_LDFLAGS=$BUILD_LDFLAGS ++ ;; ++ *) ++ AC_MSG_ERROR([--with-utils must be either host, target, or build]) ++ ;; ++esac ++AC_MSG_NOTICE([Using $with_utils flags for utilities.]) ++ ++unset CFLAGS ++unset CPPFLAGS ++unset CCASFLAGS ++unset LDFLAGS ++ ++AC_SUBST(UTILS_CFLAGS) ++AC_SUBST(UTILS_CPPFLAGS) ++AC_SUBST(UTILS_CCASFLAGS) ++AC_SUBST(UTILS_LDFLAGS) ++ + GRUB_TARGET_CPU="${target_cpu}" + GRUB_PLATFORM="${platform}" + +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 5f0ef96985..2ff9b39357 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -40,24 +40,25 @@ CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 + CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) + STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -R .note.gnu.property -R .gnu.build.attributes + +-CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding +-LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d +-CPPFLAGS_MODULE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) +-CCASFLAGS_MODULE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) ++CFLAGS_MODULE = $(TARGET_CFLAGS) $(CFLAGS_PLATFORM) -ffreestanding ++LDFLAGS_MODULE = $(TARGET_LDFLAGS) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d ++CPPFLAGS_MODULE = $(TARGET_CPPFLAGS) $(CPPFLAGS_DEFAULT) $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) ++CCASFLAGS_MODULE = $(TARGET_CCASFLAGS) $(CCASFLAGS_DEFAULT) $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) + + CFLAGS_IMAGE = $(CFLAGS_PLATFORM) -fno-builtin + LDFLAGS_IMAGE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S + CPPFLAGS_IMAGE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) + CCASFLAGS_IMAGE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) + +-CFLAGS_PROGRAM = +-LDFLAGS_PROGRAM = +-CPPFLAGS_PROGRAM = +-CCASFLAGS_PROGRAM = ++CFLAGS_PROGRAM = $(UTILS_CFLAGS) ++LDFLAGS_PROGRAM = $(UTILS_LDFLAGS) ++CPPFLAGS_PROGRAM = $(UTILS_CPPFLAGS) ++CCASFLAGS_PROGRAM = $(UTILS_CCASFLAGS) + +-CFLAGS_LIBRARY = +-CPPFLAGS_LIBRARY = +-CCASFLAGS_LIBRARY = ++CFLAGS_LIBRARY = $(UTILS_CFLAGS) ++LDFLAGS_LIBRARY = $(UTILS_LDFLAGS) ++CPPFLAGS_LIBRARY = $(UTILS_CPPFLAGS) ++CCASFLAGS_LIBRARY = $(UTILS_CCASFLAGS) + + # Other variables + +diff --git a/gentpl.py b/gentpl.py +index f09b336869..0e62e14666 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -697,10 +697,10 @@ def module(defn, platform): + var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform) + " ## platform sources") + var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources") + var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform)) +- var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_MODULE) " + platform_cflags(defn, platform)) +- var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_MODULE) " + platform_ldflags(defn, platform)) +- var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform)) +- var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform)) ++ var_set(cname(defn) + "_CFLAGS", "$(CFLAGS_MODULE) " + platform_cflags(defn, platform)) ++ var_set(cname(defn) + "_LDFLAGS", "$(LDFLAGS_MODULE) " + platform_ldflags(defn, platform)) ++ var_set(cname(defn) + "_CPPFLAGS", "$(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform)) ++ var_set(cname(defn) + "_CCASFLAGS", "$(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform)) + var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF) " + platform_dependencies(defn, platform)) + + gvar_add("dist_noinst_DATA", extra_dist(defn)) diff --git a/SOURCES/0088-net-read-bracketed-ipv6-addrs-and-port-numbers.patch b/SOURCES/0088-net-read-bracketed-ipv6-addrs-and-port-numbers.patch deleted file mode 100644 index 834b96e..0000000 --- a/SOURCES/0088-net-read-bracketed-ipv6-addrs-and-port-numbers.patch +++ /dev/null @@ -1,270 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aaron Miller -Date: Fri, 29 Jul 2016 17:41:38 +0800 -Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers - -Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses -to be recognized with brackets around them, which is required to specify a port -number - -Signed-off-by: Aaron Miller -[pjones: various bug fixes] -Signed-off-by: Peter Jones ---- - grub-core/net/http.c | 25 ++++++++++++--- - grub-core/net/net.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++--- - grub-core/net/tftp.c | 8 +++-- - include/grub/net.h | 1 + - 4 files changed, 109 insertions(+), 12 deletions(-) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index b616cf40b1e..12a2632ea55 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -289,7 +289,9 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), - nb2 = grub_netbuff_alloc (data->chunk_rem); - if (!nb2) - return grub_errno; -- grub_netbuff_put (nb2, data->chunk_rem); -+ err = grub_netbuff_put (nb2, data->chunk_rem); -+ if (err) -+ return grub_errno; - grub_memcpy (nb2->data, nb->data, data->chunk_rem); - if (file->device->net->packs.count >= 20) - { -@@ -312,12 +314,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - int i; - struct grub_net_buff *nb; - grub_err_t err; -+ char* server = file->device->net->server; -+ int port = file->device->net->port; - - nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE - + sizeof ("GET ") - 1 - + grub_strlen (data->filename) - + sizeof (" HTTP/1.1\r\nHost: ") - 1 -- + grub_strlen (file->device->net->server) -+ + grub_strlen (server) + sizeof (":XXXXXXXXXX") - + sizeof ("\r\nUser-Agent: " PACKAGE_STRING - "\r\n") - 1 - + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX" -@@ -356,7 +360,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - sizeof (" HTTP/1.1\r\nHost: ") - 1); - - ptr = nb->tail; -- err = grub_netbuff_put (nb, grub_strlen (file->device->net->server)); -+ err = grub_netbuff_put (nb, grub_strlen (server)); - if (err) - { - grub_netbuff_free (nb); -@@ -365,6 +369,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - grub_memcpy (ptr, file->device->net->server, - grub_strlen (file->device->net->server)); - -+ if (port) -+ { -+ ptr = nb->tail; -+ grub_snprintf ((char *) ptr, -+ sizeof (":XXXXXXXXXX"), -+ ":%d", -+ port); -+ } -+ - ptr = nb->tail; - err = grub_netbuff_put (nb, - sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") -@@ -390,8 +403,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - grub_netbuff_put (nb, 2); - grub_memcpy (ptr, "\r\n", 2); - -- data->sock = grub_net_tcp_open (file->device->net->server, -- HTTP_PORT, http_receive, -+ grub_dprintf ("http", "opening path %s on host %s TCP port %d\n", -+ data->filename, server, port ? port : HTTP_PORT); -+ data->sock = grub_net_tcp_open (server, -+ port ? port : HTTP_PORT, http_receive, - http_err, NULL, - file); - if (!data->sock) -diff --git a/grub-core/net/net.c b/grub-core/net/net.c -index a46f82362ed..0ce5e675ed7 100644 ---- a/grub-core/net/net.c -+++ b/grub-core/net/net.c -@@ -444,6 +444,13 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) - grub_uint16_t newip[8]; - const char *ptr = val; - int word, quaddot = -1; -+ int bracketed = 0; -+ -+ if (ptr[0] == '[') -+ { -+ bracketed = 1; -+ ptr++; -+ } - - if (ptr[0] == ':' && ptr[1] != ':') - return 0; -@@ -482,6 +489,8 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) - grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); - } - grub_memcpy (ip, newip, 16); -+ if (bracketed && *ptr == ']') -+ ptr++; - if (rest) - *rest = ptr; - return 1; -@@ -1343,8 +1352,10 @@ grub_net_open_real (const char *name) - { - grub_net_app_level_t proto; - const char *protname, *server; -+ char *host; - grub_size_t protnamelen; - int try; -+ int port = 0; - - if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) - { -@@ -1382,6 +1393,72 @@ grub_net_open_real (const char *name) - return NULL; - } - -+ char* port_start; -+ /* ipv6 or port specified? */ -+ if ((port_start = grub_strchr (server, ':'))) -+ { -+ char* ipv6_begin; -+ if((ipv6_begin = grub_strchr (server, '['))) -+ { -+ char* ipv6_end = grub_strchr (server, ']'); -+ if(!ipv6_end) -+ { -+ grub_error (GRUB_ERR_NET_BAD_ADDRESS, -+ N_("mismatched [ in address")); -+ return NULL; -+ } -+ /* port number after bracketed ipv6 addr */ -+ if(ipv6_end[1] == ':') -+ { -+ port = grub_strtoul (ipv6_end + 2, NULL, 10); -+ if(port > 65535) -+ { -+ grub_error (GRUB_ERR_NET_BAD_ADDRESS, -+ N_("bad port number")); -+ return NULL; -+ } -+ } -+ host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1); -+ } -+ else -+ { -+ if (grub_strchr (port_start + 1, ':')) -+ { -+ int iplen = grub_strlen (server); -+ /* bracket bare ipv6 addrs */ -+ host = grub_malloc (iplen + 3); -+ if(!host) -+ { -+ return NULL; -+ } -+ host[0] = '['; -+ grub_memcpy (host + 1, server, iplen); -+ host[iplen + 1] = ']'; -+ host[iplen + 2] = '\0'; -+ } -+ else -+ { -+ /* hostname:port or ipv4:port */ -+ port = grub_strtol (port_start + 1, NULL, 10); -+ if(port > 65535) -+ { -+ grub_error (GRUB_ERR_NET_BAD_ADDRESS, -+ N_("bad port number")); -+ return NULL; -+ } -+ host = grub_strndup (server, port_start - server); -+ } -+ } -+ } -+ else -+ { -+ host = grub_strdup (server); -+ } -+ if (!host) -+ { -+ return NULL; -+ } -+ - for (try = 0; try < 2; try++) - { - FOR_NET_APP_LEVEL (proto) -@@ -1391,14 +1468,13 @@ grub_net_open_real (const char *name) - { - grub_net_t ret = grub_zalloc (sizeof (*ret)); - if (!ret) -- return NULL; -- ret->protocol = proto; -- ret->server = grub_strdup (server); -- if (!ret->server) - { -- grub_free (ret); -+ grub_free (host); - return NULL; - } -+ ret->protocol = proto; -+ ret->port = port; -+ ret->server = host; - ret->fs = &grub_net_fs; - return ret; - } -@@ -1473,6 +1549,7 @@ grub_net_open_real (const char *name) - grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), - name); - -+ grub_free (host); - return NULL; - } - -diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c -index 4ab2f5c7357..d54b13f09ff 100644 ---- a/grub-core/net/tftp.c -+++ b/grub-core/net/tftp.c -@@ -295,6 +295,7 @@ tftp_open (struct grub_file *file, const char *filename) - grub_err_t err; - grub_uint8_t *nbd; - grub_net_network_level_address_t addr; -+ int port = file->device->net->port; - - data = grub_zalloc (sizeof (*data)); - if (!data) -@@ -362,14 +363,17 @@ tftp_open (struct grub_file *file, const char *filename) - err = grub_net_resolve_address (file->device->net->server, &addr); - if (err) - { -- grub_dprintf("tftp", "Address resolution failed: %d\n", err); -+ grub_dprintf ("tftp", "Address resolution failed: %d\n", err); -+ grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n", -+ (unsigned long long)data->file_size, -+ (unsigned long long)data->block_size); - grub_free (data); - return err; - } - - grub_dprintf("tftp", "opening connection\n"); - data->sock = grub_net_udp_open (addr, -- TFTP_SERVER_PORT, tftp_receive, -+ port ? port : TFTP_SERVER_PORT, tftp_receive, - file); - if (!data->sock) - { -diff --git a/include/grub/net.h b/include/grub/net.h -index af0404db7e3..d55d505a03a 100644 ---- a/include/grub/net.h -+++ b/include/grub/net.h -@@ -273,6 +273,7 @@ typedef struct grub_net - { - char *server; - char *name; -+ int port; - grub_net_app_level_t protocol; - grub_net_packets_t packs; - grub_off_t offset; diff --git a/SOURCES/0089-bootp-New-net_bootp6-command.patch b/SOURCES/0089-bootp-New-net_bootp6-command.patch deleted file mode 100644 index 21b3871..0000000 --- a/SOURCES/0089-bootp-New-net_bootp6-command.patch +++ /dev/null @@ -1,1368 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Wed, 10 Jul 2019 15:42:36 +0200 -Subject: [PATCH] bootp: New net_bootp6 command - -Implement new net_bootp6 command for IPv6 network auto configuration via the -DHCPv6 protocol (RFC3315). - -Signed-off-by: Michael Chang -Signed-off-by: Ken Lin -[pjones: Put back our code to add a local route] -Signed-off-by: Peter Jones ---- - grub-core/net/bootp.c | 1059 ++++++++++++++++++++++++++++++------ - grub-core/net/drivers/efi/efinet.c | 20 +- - grub-core/net/ip.c | 39 ++ - include/grub/efi/api.h | 2 +- - include/grub/net.h | 91 ++-- - 5 files changed, 1002 insertions(+), 209 deletions(-) - -diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c -index 08b6b2b5d6c..fe93b80f1cf 100644 ---- a/grub-core/net/bootp.c -+++ b/grub-core/net/bootp.c -@@ -24,6 +24,98 @@ - #include - #include - #include -+#include -+#include -+ -+static int -+dissect_url (const char *url, char **proto, char **host, char **path) -+{ -+ const char *p, *ps; -+ grub_size_t l; -+ -+ *proto = *host = *path = NULL; -+ ps = p = url; -+ -+ while ((p = grub_strchr (p, ':'))) -+ { -+ if (grub_strlen (p) < sizeof ("://") - 1) -+ break; -+ if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0) -+ { -+ l = p - ps; -+ *proto = grub_malloc (l + 1); -+ if (!*proto) -+ { -+ grub_print_error (); -+ return 0; -+ } -+ -+ grub_memcpy (*proto, ps, l); -+ (*proto)[l] = '\0'; -+ p += sizeof ("://") - 1; -+ break; -+ } -+ ++p; -+ } -+ -+ if (!*proto) -+ { -+ grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url); -+ return 0; -+ } -+ -+ ps = p; -+ p = grub_strchr (p, '/'); -+ -+ if (!p) -+ { -+ grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url); -+ grub_free (*proto); -+ *proto = NULL; -+ return 0; -+ } -+ -+ l = p - ps; -+ -+ if (l > 2 && ps[0] == '[' && ps[l - 1] == ']') -+ { -+ *host = grub_malloc (l - 1); -+ if (!*host) -+ { -+ grub_print_error (); -+ grub_free (*proto); -+ *proto = NULL; -+ return 0; -+ } -+ grub_memcpy (*host, ps + 1, l - 2); -+ (*host)[l - 2] = 0; -+ } -+ else -+ { -+ *host = grub_malloc (l + 1); -+ if (!*host) -+ { -+ grub_print_error (); -+ grub_free (*proto); -+ *proto = NULL; -+ return 0; -+ } -+ grub_memcpy (*host, ps, l); -+ (*host)[l] = 0; -+ } -+ -+ *path = grub_strdup (p); -+ if (!*path) -+ { -+ grub_print_error (); -+ grub_free (*host); -+ grub_free (*proto); -+ *host = NULL; -+ *proto = NULL; -+ return 0; -+ } -+ return 1; -+} - - struct grub_dhcp_discover_options - { -@@ -604,6 +696,584 @@ out: - return err; - } - -+/* The default netbuff size for sending DHCPv6 packets which should be -+ large enough to hold the information */ -+#define GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE 512 -+ -+struct grub_dhcp6_options -+{ -+ grub_uint8_t *client_duid; -+ grub_uint16_t client_duid_len; -+ grub_uint8_t *server_duid; -+ grub_uint16_t server_duid_len; -+ grub_uint32_t iaid; -+ grub_uint32_t t1; -+ grub_uint32_t t2; -+ grub_net_network_level_address_t *ia_addr; -+ grub_uint32_t preferred_lifetime; -+ grub_uint32_t valid_lifetime; -+ grub_net_network_level_address_t *dns_server_addrs; -+ grub_uint16_t num_dns_server; -+ char *boot_file_proto; -+ char *boot_file_server_ip; -+ char *boot_file_path; -+}; -+ -+typedef struct grub_dhcp6_options *grub_dhcp6_options_t; -+ -+struct grub_dhcp6_session -+{ -+ struct grub_dhcp6_session *next; -+ struct grub_dhcp6_session **prev; -+ grub_uint32_t iaid; -+ grub_uint32_t transaction_id:24; -+ grub_uint64_t start_time; -+ struct grub_net_dhcp6_option_duid_ll duid; -+ struct grub_net_network_level_interface *iface; -+ -+ /* The associated dhcpv6 options */ -+ grub_dhcp6_options_t adv; -+ grub_dhcp6_options_t reply; -+}; -+ -+typedef struct grub_dhcp6_session *grub_dhcp6_session_t; -+ -+typedef void (*dhcp6_option_hook_fn) (const struct grub_net_dhcp6_option *opt, void *data); -+ -+static void -+foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, -+ dhcp6_option_hook_fn hook, void *hook_data); -+ -+static void -+parse_dhcp6_iaaddr (const struct grub_net_dhcp6_option *opt, void *data) -+{ -+ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t )data; -+ -+ grub_uint16_t code = grub_be_to_cpu16 (opt->code); -+ grub_uint16_t len = grub_be_to_cpu16 (opt->len); -+ -+ if (code == GRUB_NET_DHCP6_OPTION_IAADDR) -+ { -+ const struct grub_net_dhcp6_option_iaaddr *iaaddr; -+ iaaddr = (const struct grub_net_dhcp6_option_iaaddr *)opt->data; -+ -+ if (len < sizeof (*iaaddr)) -+ { -+ grub_dprintf ("bootp", "DHCPv6: code %u with insufficient length %u\n", code, len); -+ return; -+ } -+ if (!dhcp6->ia_addr) -+ { -+ dhcp6->ia_addr = grub_malloc (sizeof(*dhcp6->ia_addr)); -+ dhcp6->ia_addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -+ dhcp6->ia_addr->ipv6[0] = grub_get_unaligned64 (iaaddr->addr); -+ dhcp6->ia_addr->ipv6[1] = grub_get_unaligned64 (iaaddr->addr + 8); -+ dhcp6->preferred_lifetime = grub_be_to_cpu32 (iaaddr->preferred_lifetime); -+ dhcp6->valid_lifetime = grub_be_to_cpu32 (iaaddr->valid_lifetime); -+ } -+ } -+} -+ -+static void -+parse_dhcp6_option (const struct grub_net_dhcp6_option *opt, void *data) -+{ -+ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t)data; -+ grub_uint16_t code = grub_be_to_cpu16 (opt->code); -+ grub_uint16_t len = grub_be_to_cpu16 (opt->len); -+ -+ switch (code) -+ { -+ case GRUB_NET_DHCP6_OPTION_CLIENTID: -+ -+ if (dhcp6->client_duid || !len) -+ { -+ grub_dprintf ("bootp", "Skipped DHCPv6 CLIENTID with length %u\n", len); -+ break; -+ } -+ dhcp6->client_duid = grub_malloc (len); -+ grub_memcpy (dhcp6->client_duid, opt->data, len); -+ dhcp6->client_duid_len = len; -+ break; -+ -+ case GRUB_NET_DHCP6_OPTION_SERVERID: -+ -+ if (dhcp6->server_duid || !len) -+ { -+ grub_dprintf ("bootp", "Skipped DHCPv6 SERVERID with length %u\n", len); -+ break; -+ } -+ dhcp6->server_duid = grub_malloc (len); -+ grub_memcpy (dhcp6->server_duid, opt->data, len); -+ dhcp6->server_duid_len = len; -+ break; -+ -+ case GRUB_NET_DHCP6_OPTION_IA_NA: -+ { -+ const struct grub_net_dhcp6_option_iana *ia_na; -+ grub_uint16_t data_len; -+ -+ if (dhcp6->iaid || len < sizeof (*ia_na)) -+ { -+ grub_dprintf ("bootp", "Skipped DHCPv6 IA_NA with length %u\n", len); -+ break; -+ } -+ ia_na = (const struct grub_net_dhcp6_option_iana *)opt->data; -+ dhcp6->iaid = grub_be_to_cpu32 (ia_na->iaid); -+ dhcp6->t1 = grub_be_to_cpu32 (ia_na->t1); -+ dhcp6->t2 = grub_be_to_cpu32 (ia_na->t2); -+ -+ data_len = len - sizeof (*ia_na); -+ if (data_len) -+ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)ia_na->data, data_len, parse_dhcp6_iaaddr, dhcp6); -+ } -+ break; -+ -+ case GRUB_NET_DHCP6_OPTION_DNS_SERVERS: -+ { -+ const grub_uint8_t *po; -+ grub_uint16_t ln; -+ grub_net_network_level_address_t *la; -+ -+ if (!len || len & 0xf) -+ { -+ grub_dprintf ("bootp", "Skip invalid length DHCPv6 DNS_SERVERS \n"); -+ break; -+ } -+ dhcp6->num_dns_server = ln = len >> 4; -+ dhcp6->dns_server_addrs = la = grub_zalloc (ln * sizeof (*la)); -+ -+ for (po = opt->data; ln > 0; po += 0x10, la++, ln--) -+ { -+ la->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -+ la->ipv6[0] = grub_get_unaligned64 (po); -+ la->ipv6[1] = grub_get_unaligned64 (po + 8); -+ la->option = DNS_OPTION_PREFER_IPV6; -+ } -+ } -+ break; -+ -+ case GRUB_NET_DHCP6_OPTION_BOOTFILE_URL: -+ dissect_url ((const char *)opt->data, -+ &dhcp6->boot_file_proto, -+ &dhcp6->boot_file_server_ip, -+ &dhcp6->boot_file_path); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+static void -+foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, dhcp6_option_hook_fn hook, void *hook_data) -+{ -+ while (size) -+ { -+ grub_uint16_t code, len; -+ -+ if (size < sizeof (*opt)) -+ { -+ grub_dprintf ("bootp", "DHCPv6: Options stopped with remaining size %" PRIxGRUB_SIZE "\n", size); -+ break; -+ } -+ size -= sizeof (*opt); -+ len = grub_be_to_cpu16 (opt->len); -+ code = grub_be_to_cpu16 (opt->code); -+ if (size < len) -+ { -+ grub_dprintf ("bootp", "DHCPv6: Options stopped at out of bound length %u for option %u\n", len, code); -+ break; -+ } -+ if (!len) -+ { -+ grub_dprintf ("bootp", "DHCPv6: Options stopped at zero length option %u\n", code); -+ break; -+ } -+ else -+ { -+ if (hook) -+ hook (opt, hook_data); -+ size -= len; -+ opt = (const struct grub_net_dhcp6_option *)((grub_uint8_t *)opt + len + sizeof (*opt)); -+ } -+ } -+} -+ -+static grub_dhcp6_options_t -+grub_dhcp6_options_get (const struct grub_net_dhcp6_packet *v6h, -+ grub_size_t size) -+{ -+ grub_dhcp6_options_t options; -+ -+ if (size < sizeof (*v6h)) -+ { -+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small")); -+ return NULL; -+ } -+ -+ options = grub_zalloc (sizeof(*options)); -+ if (!options) -+ return NULL; -+ -+ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)v6h->dhcp_options, -+ size - sizeof (*v6h), parse_dhcp6_option, options); -+ -+ return options; -+} -+ -+static void -+grub_dhcp6_options_free (grub_dhcp6_options_t options) -+{ -+ if (options->client_duid) -+ grub_free (options->client_duid); -+ if (options->server_duid) -+ grub_free (options->server_duid); -+ if (options->ia_addr) -+ grub_free (options->ia_addr); -+ if (options->dns_server_addrs) -+ grub_free (options->dns_server_addrs); -+ if (options->boot_file_proto) -+ grub_free (options->boot_file_proto); -+ if (options->boot_file_server_ip) -+ grub_free (options->boot_file_server_ip); -+ if (options->boot_file_path) -+ grub_free (options->boot_file_path); -+ -+ grub_free (options); -+} -+ -+static grub_dhcp6_session_t grub_dhcp6_sessions; -+#define FOR_DHCP6_SESSIONS_SAFE(var, next) FOR_LIST_ELEMENTS_SAFE (var, next, grub_dhcp6_sessions) -+#define FOR_DHCP6_SESSIONS(var) FOR_LIST_ELEMENTS (var, grub_dhcp6_sessions) -+ -+static void -+grub_net_configure_by_dhcp6_info (const char *name, -+ struct grub_net_card *card, -+ grub_dhcp6_options_t dhcp6, -+ int is_def, -+ int flags, -+ struct grub_net_network_level_interface **ret_inf) -+{ -+ grub_net_network_level_netaddress_t netaddr; -+ struct grub_net_network_level_interface *inf; -+ -+ if (dhcp6->ia_addr) -+ { -+ inf = grub_net_add_addr (name, card, dhcp6->ia_addr, &card->default_address, flags); -+ -+ netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -+ netaddr.ipv6.base[0] = dhcp6->ia_addr->ipv6[0]; -+ netaddr.ipv6.base[1] = 0; -+ netaddr.ipv6.masksize = 64; -+ grub_net_add_route (name, netaddr, inf); -+ -+ if (ret_inf) -+ *ret_inf = inf; -+ } -+ -+ if (dhcp6->dns_server_addrs) -+ { -+ grub_uint16_t i; -+ -+ for (i = 0; i < dhcp6->num_dns_server; ++i) -+ grub_net_add_dns_server (dhcp6->dns_server_addrs + i); -+ } -+ -+ if (dhcp6->boot_file_path) -+ grub_env_set_net_property (name, "boot_file", dhcp6->boot_file_path, -+ grub_strlen (dhcp6->boot_file_path)); -+ -+ if (is_def && dhcp6->boot_file_server_ip) -+ { -+ grub_net_default_server = grub_strdup (dhcp6->boot_file_server_ip); -+ grub_env_set ("net_default_interface", name); -+ grub_env_export ("net_default_interface"); -+ } -+} -+ -+static void -+grub_dhcp6_session_add (struct grub_net_network_level_interface *iface, -+ grub_uint32_t iaid) -+{ -+ grub_dhcp6_session_t se; -+ struct grub_datetime date; -+ grub_err_t err; -+ grub_int32_t t = 0; -+ -+ se = grub_malloc (sizeof (*se)); -+ -+ err = grub_get_datetime (&date); -+ if (err || !grub_datetime2unixtime (&date, &t)) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ t = 0; -+ } -+ -+ se->iface = iface; -+ se->iaid = iaid; -+ se->transaction_id = t; -+ se->start_time = grub_get_time_ms (); -+ se->duid.type = grub_cpu_to_be16_compile_time (3) ; -+ se->duid.hw_type = grub_cpu_to_be16_compile_time (1); -+ grub_memcpy (&se->duid.hwaddr, &iface->hwaddress.mac, sizeof (se->duid.hwaddr)); -+ se->adv = NULL; -+ se->reply = NULL; -+ grub_list_push (GRUB_AS_LIST_P (&grub_dhcp6_sessions), GRUB_AS_LIST (se)); -+} -+ -+static void -+grub_dhcp6_session_remove (grub_dhcp6_session_t se) -+{ -+ grub_list_remove (GRUB_AS_LIST (se)); -+ if (se->adv) -+ grub_dhcp6_options_free (se->adv); -+ if (se->reply) -+ grub_dhcp6_options_free (se->reply); -+ grub_free (se); -+} -+ -+static void -+grub_dhcp6_session_remove_all (void) -+{ -+ grub_dhcp6_session_t se, next; -+ -+ FOR_DHCP6_SESSIONS_SAFE (se, next) -+ { -+ grub_dhcp6_session_remove (se); -+ } -+ grub_dhcp6_sessions = NULL; -+} -+ -+static grub_err_t -+grub_dhcp6_session_configure_network (grub_dhcp6_session_t se) -+{ -+ char *name; -+ -+ name = grub_xasprintf ("%s:dhcp6", se->iface->card->name); -+ if (!name) -+ return grub_errno; -+ -+ grub_net_configure_by_dhcp6_info (name, se->iface->card, se->reply, 1, 0, 0); -+ grub_free (name); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_dhcp6_session_send_request (grub_dhcp6_session_t se) -+{ -+ struct grub_net_buff *nb; -+ struct grub_net_dhcp6_option *opt; -+ struct grub_net_dhcp6_packet *v6h; -+ struct grub_net_dhcp6_option_iana *ia_na; -+ struct grub_net_dhcp6_option_iaaddr *iaaddr; -+ struct udphdr *udph; -+ grub_net_network_level_address_t multicast; -+ grub_net_link_level_address_t ll_multicast; -+ grub_uint64_t elapsed; -+ struct grub_net_network_level_interface *inf = se->iface; -+ grub_dhcp6_options_t dhcp6 = se->adv; -+ grub_err_t err = GRUB_ERR_NONE; -+ -+ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -+ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48); -+ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL); -+ -+ err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); -+ if (err) -+ return err; -+ -+ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); -+ -+ if (!nb) -+ return grub_errno; -+ -+ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ err = grub_netbuff_push (nb, dhcp6->client_duid_len + sizeof (*opt)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ opt = (struct grub_net_dhcp6_option *)nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID); -+ opt->len = grub_cpu_to_be16 (dhcp6->client_duid_len); -+ grub_memcpy (opt->data, dhcp6->client_duid , dhcp6->client_duid_len); -+ -+ err = grub_netbuff_push (nb, dhcp6->server_duid_len + sizeof (*opt)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ opt = (struct grub_net_dhcp6_option *)nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_SERVERID); -+ opt->len = grub_cpu_to_be16 (dhcp6->server_duid_len); -+ grub_memcpy (opt->data, dhcp6->server_duid , dhcp6->server_duid_len); -+ -+ err = grub_netbuff_push (nb, sizeof (*ia_na) + sizeof (*opt)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ if (dhcp6->ia_addr) -+ { -+ err = grub_netbuff_push (nb, sizeof(*iaaddr) + sizeof (*opt)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ } -+ opt = (struct grub_net_dhcp6_option *)nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); -+ opt->len = grub_cpu_to_be16 (sizeof (*ia_na)); -+ if (dhcp6->ia_addr) -+ opt->len += grub_cpu_to_be16 (sizeof(*iaaddr) + sizeof (*opt)); -+ -+ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data; -+ ia_na->iaid = grub_cpu_to_be32 (dhcp6->iaid); -+ -+ ia_na->t1 = grub_cpu_to_be32 (dhcp6->t1); -+ ia_na->t2 = grub_cpu_to_be32 (dhcp6->t2); -+ -+ if (dhcp6->ia_addr) -+ { -+ opt = (struct grub_net_dhcp6_option *)ia_na->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR); -+ opt->len = grub_cpu_to_be16 (sizeof (*iaaddr)); -+ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)opt->data; -+ grub_set_unaligned64 (iaaddr->addr, dhcp6->ia_addr->ipv6[0]); -+ grub_set_unaligned64 (iaaddr->addr + 8, dhcp6->ia_addr->ipv6[1]); -+ -+ iaaddr->preferred_lifetime = grub_cpu_to_be32 (dhcp6->preferred_lifetime); -+ iaaddr->valid_lifetime = grub_cpu_to_be32 (dhcp6->valid_lifetime); -+ } -+ -+ err = grub_netbuff_push (nb, sizeof (*opt) + 2 * sizeof (grub_uint16_t)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ opt = (struct grub_net_dhcp6_option*) nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ORO); -+ opt->len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_uint16_t)); -+ grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL)); -+ grub_set_unaligned16 (opt->data + 2, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS)); -+ -+ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ opt = (struct grub_net_dhcp6_option*) nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME); -+ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t)); -+ -+ /* the time is expressed in hundredths of a second */ -+ elapsed = grub_divmod64 (grub_get_time_ms () - se->start_time, 10, 0); -+ -+ if (elapsed > 0xffff) -+ elapsed = 0xffff; -+ -+ grub_set_unaligned16 (opt->data, grub_cpu_to_be16 ((grub_uint16_t)elapsed)); -+ -+ err = grub_netbuff_push (nb, sizeof (*v6h)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ v6h = (struct grub_net_dhcp6_packet *) nb->data; -+ v6h->message_type = GRUB_NET_DHCP6_REQUEST; -+ v6h->transaction_id = se->transaction_id; -+ -+ err = grub_netbuff_push (nb, sizeof (*udph)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ udph = (struct udphdr *) nb->data; -+ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT); -+ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT); -+ udph->chksum = 0; -+ udph->len = grub_cpu_to_be16 (nb->tail - nb->data); -+ -+ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, -+ &inf->address, -+ &multicast); -+ err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, -+ GRUB_NET_IP_UDP); -+ -+ grub_netbuff_free (nb); -+ -+ return err; -+} -+ -+struct grub_net_network_level_interface * -+grub_net_configure_by_dhcpv6_reply (const char *name, -+ struct grub_net_card *card, -+ grub_net_interface_flags_t flags, -+ const struct grub_net_dhcp6_packet *v6h, -+ grub_size_t size, -+ int is_def, -+ char **device, char **path) -+{ -+ struct grub_net_network_level_interface *inf; -+ grub_dhcp6_options_t dhcp6; -+ int mask = -1; -+ -+ dhcp6 = grub_dhcp6_options_get (v6h, size); -+ if (!dhcp6) -+ { -+ grub_print_error (); -+ return NULL; -+ } -+ -+ grub_net_configure_by_dhcp6_info (name, card, dhcp6, is_def, flags, &inf); -+ -+ if (device && dhcp6->boot_file_proto && dhcp6->boot_file_server_ip) -+ { -+ *device = grub_xasprintf ("%s,%s", dhcp6->boot_file_proto, dhcp6->boot_file_server_ip); -+ grub_print_error (); -+ } -+ if (path && dhcp6->boot_file_path) -+ { -+ *path = grub_strdup (dhcp6->boot_file_path); -+ grub_print_error (); -+ if (*path) -+ { -+ char *slash; -+ slash = grub_strrchr (*path, '/'); -+ if (slash) -+ *slash = 0; -+ else -+ **path = 0; -+ } -+ } -+ -+ grub_dhcp6_options_free (dhcp6); -+ -+ if (inf) -+ grub_net_add_ipv6_local (inf, mask); -+ -+ return inf; -+} -+ - /* - * This is called directly from net/ip.c:handle_dgram(), because those - * BOOTP/DHCP packets are a bit special due to their improper -@@ -672,6 +1342,77 @@ grub_net_process_dhcp (struct grub_net_buff *nb, - } - } - -+grub_err_t -+grub_net_process_dhcp6 (struct grub_net_buff *nb, -+ struct grub_net_card *card __attribute__ ((unused))) -+{ -+ const struct grub_net_dhcp6_packet *v6h; -+ grub_dhcp6_session_t se; -+ grub_size_t size; -+ grub_dhcp6_options_t options; -+ -+ v6h = (const struct grub_net_dhcp6_packet *) nb->data; -+ size = nb->tail - nb->data; -+ -+ options = grub_dhcp6_options_get (v6h, size); -+ if (!options) -+ return grub_errno; -+ -+ if (!options->client_duid || !options->server_duid || !options->ia_addr) -+ { -+ grub_dhcp6_options_free (options); -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Bad DHCPv6 Packet"); -+ } -+ -+ FOR_DHCP6_SESSIONS (se) -+ { -+ if (se->transaction_id == v6h->transaction_id && -+ grub_memcmp (options->client_duid, &se->duid, sizeof (se->duid)) == 0 && -+ se->iaid == options->iaid) -+ break; -+ } -+ -+ if (!se) -+ { -+ grub_dprintf ("bootp", "DHCPv6 session not found\n"); -+ grub_dhcp6_options_free (options); -+ return GRUB_ERR_NONE; -+ } -+ -+ if (v6h->message_type == GRUB_NET_DHCP6_ADVERTISE) -+ { -+ if (se->adv) -+ { -+ grub_dprintf ("bootp", "Skipped DHCPv6 Advertised .. \n"); -+ grub_dhcp6_options_free (options); -+ return GRUB_ERR_NONE; -+ } -+ -+ se->adv = options; -+ return grub_dhcp6_session_send_request (se); -+ } -+ else if (v6h->message_type == GRUB_NET_DHCP6_REPLY) -+ { -+ if (!se->adv) -+ { -+ grub_dprintf ("bootp", "Skipped DHCPv6 Reply .. \n"); -+ grub_dhcp6_options_free (options); -+ return GRUB_ERR_NONE; -+ } -+ -+ se->reply = options; -+ grub_dhcp6_session_configure_network (se); -+ grub_dhcp6_session_remove (se); -+ return GRUB_ERR_NONE; -+ } -+ else -+ { -+ grub_dhcp6_options_free (options); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ - static grub_err_t - grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -@@ -897,180 +1638,174 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), - return err; - } - --static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp; -- --struct grub_net_network_level_interface * --grub_net_configure_by_dhcpv6_ack (const char *name, -- struct grub_net_card *card, -- grub_net_interface_flags_t flags -- __attribute__((__unused__)), -- const grub_net_link_level_address_t *hwaddr, -- const struct grub_net_dhcpv6_packet *packet, -- int is_def, char **device, char **path) -+static grub_err_t -+grub_cmd_bootp6 (struct grub_command *cmd __attribute__ ((unused)), -+ int argc, char **args) - { -- struct grub_net_network_level_interface *inter = NULL; -- struct grub_net_network_level_address addr; -- int mask = -1; -+ struct grub_net_card *card; -+ grub_uint32_t iaid = 0; -+ int interval; -+ grub_err_t err; -+ grub_dhcp6_session_t se; - -- if (!device || !path) -- return NULL; -+ err = GRUB_ERR_NONE; - -- *device = 0; -- *path = 0; -+ FOR_NET_CARDS (card) -+ { -+ struct grub_net_network_level_interface *iface; - -- grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n", -- hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2], -- hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]); -+ if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) -+ continue; - -- if (is_def) -- grub_net_default_server = 0; -+ iface = grub_net_ipv6_get_link_local (card, &card->default_address); -+ if (!iface) -+ { -+ grub_dhcp6_session_remove_all (); -+ return grub_errno; -+ } - -- if (is_def && !grub_net_default_server && packet) -+ grub_dhcp6_session_add (iface, iaid++); -+ } -+ -+ for (interval = 200; interval < 10000; interval *= 2) - { -- const grub_uint8_t *options = packet->dhcp_options; -- unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet); -- unsigned int i; -- -- for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); ) -- { -- grub_uint16_t num, len; -- grub_net_dhcpv6_option_t *opt = -- (grub_net_dhcpv6_option_t *)(options + i); -- -- num = grub_be_to_cpu16(opt->option_num); -- len = grub_be_to_cpu16(opt->option_len); -- -- grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len); -- -- if (len == 0) -- break; -- -- if (len + i > 1024) -- break; -- -- if (num == GRUB_NET_DHCP6_BOOTFILE_URL) -- { -- char *scheme, *userinfo, *host, *file; -- char *tmp; -- int hostlen; -- int port; -- int rc = extract_url_info ((const char *)opt->option_data, -- (grub_size_t)len, -- &scheme, &userinfo, &host, &port, -- &file); -- if (rc < 0) -- continue; -- -- /* right now this only handles tftp. */ -- if (grub_strcmp("tftp", scheme)) -- { -- grub_free (scheme); -- grub_free (userinfo); -- grub_free (host); -- grub_free (file); -- continue; -- } -- grub_free (userinfo); -- -- hostlen = grub_strlen (host); -- if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']') -- { -- tmp = host+1; -- host[hostlen-1] = '\0'; -- } -- else -- tmp = host; -- -- *device = grub_xasprintf ("%s,%s", scheme, tmp); -- grub_free (scheme); -- grub_free (host); -- -- if (file && *file) -- { -- tmp = grub_strrchr (file, '/'); -- if (tmp) -- *(tmp+1) = '\0'; -- else -- file[0] = '\0'; -- } -- else if (!file) -- file = grub_strdup (""); -- -- if (file[0] == '/') -- { -- *path = grub_strdup (file+1); -- grub_free (file); -- } -- else -- *path = file; -- } -- else if (num == GRUB_NET_DHCP6_IA_NA) -- { -- const grub_net_dhcpv6_option_t *ia_na_opt; -- const grub_net_dhcpv6_opt_ia_na_t *ia_na = -- (const grub_net_dhcpv6_opt_ia_na_t *)opt; -- unsigned int left = len - OFFSET_OF (options, ia_na); -- unsigned int j; -- -- if ((grub_uint8_t *)ia_na + left > -- (grub_uint8_t *)options + option_max) -- left -= ((grub_uint8_t *)ia_na + left) -- - ((grub_uint8_t *)options + option_max); -- -- if (len < OFFSET_OF (option_data, opt) -- + sizeof (grub_net_dhcpv6_option_t)) -- { -- grub_dprintf ("net", -- "found dhcpv6 ia_na option with no address\n"); -- continue; -- } -- -- for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); ) -- { -- ia_na_opt = (const grub_net_dhcpv6_option_t *) -- (ia_na->options + j); -- grub_uint16_t ia_na_opt_num, ia_na_opt_len; -- -- ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num); -- ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len); -- if (ia_na_opt_len == 0) -- break; -- if (j + ia_na_opt_len > left) -- break; -- if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS) -- { -- const grub_net_dhcpv6_opt_ia_address_t *ia_addr; -- -- ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *) -- ia_na_opt; -- addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -- grub_memcpy(addr.ipv6, ia_addr->ipv6_address, -- sizeof (ia_addr->ipv6_address)); -- inter = grub_net_add_addr (name, card, &addr, hwaddr, 0); -- } -- -- j += ia_na_opt_len; -- left -= ia_na_opt_len; -- } -- } -- -- i += len + 4; -- } -- -- grub_print_error (); -+ int done = 1; -+ -+ FOR_DHCP6_SESSIONS (se) -+ { -+ struct grub_net_buff *nb; -+ struct grub_net_dhcp6_option *opt; -+ struct grub_net_dhcp6_packet *v6h; -+ struct grub_net_dhcp6_option_duid_ll *duid; -+ struct grub_net_dhcp6_option_iana *ia_na; -+ grub_net_network_level_address_t multicast; -+ grub_net_link_level_address_t ll_multicast; -+ struct udphdr *udph; -+ -+ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; -+ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48); -+ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL); -+ -+ err = grub_net_link_layer_resolve (se->iface, -+ &multicast, &ll_multicast); -+ if (err) -+ { -+ grub_dhcp6_session_remove_all (); -+ return err; -+ } -+ -+ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); -+ -+ if (!nb) -+ { -+ grub_dhcp6_session_remove_all (); -+ return grub_errno; -+ } -+ -+ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); -+ if (err) -+ { -+ grub_dhcp6_session_remove_all (); -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t)); -+ if (err) -+ { -+ grub_dhcp6_session_remove_all (); -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ opt = (struct grub_net_dhcp6_option *)nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME); -+ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t)); -+ grub_set_unaligned16 (opt->data, 0); -+ -+ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*duid)); -+ if (err) -+ { -+ grub_dhcp6_session_remove_all (); -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ opt = (struct grub_net_dhcp6_option *)nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID); -+ opt->len = grub_cpu_to_be16 (sizeof (*duid)); -+ -+ duid = (struct grub_net_dhcp6_option_duid_ll *) opt->data; -+ grub_memcpy (duid, &se->duid, sizeof (*duid)); -+ -+ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*ia_na)); -+ if (err) -+ { -+ grub_dhcp6_session_remove_all (); -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ opt = (struct grub_net_dhcp6_option *)nb->data; -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); -+ opt->len = grub_cpu_to_be16 (sizeof (*ia_na)); -+ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data; -+ ia_na->iaid = grub_cpu_to_be32 (se->iaid); -+ ia_na->t1 = 0; -+ ia_na->t2 = 0; -+ -+ err = grub_netbuff_push (nb, sizeof (*v6h)); -+ if (err) -+ { -+ grub_dhcp6_session_remove_all (); -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ v6h = (struct grub_net_dhcp6_packet *)nb->data; -+ v6h->message_type = GRUB_NET_DHCP6_SOLICIT; -+ v6h->transaction_id = se->transaction_id; -+ -+ grub_netbuff_push (nb, sizeof (*udph)); -+ -+ udph = (struct udphdr *) nb->data; -+ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT); -+ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT); -+ udph->chksum = 0; -+ udph->len = grub_cpu_to_be16 (nb->tail - nb->data); -+ -+ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, -+ &se->iface->address, &multicast); -+ -+ err = grub_net_send_ip_packet (se->iface, &multicast, -+ &ll_multicast, nb, GRUB_NET_IP_UDP); -+ done = 0; -+ grub_netbuff_free (nb); -+ -+ if (err) -+ { -+ grub_dhcp6_session_remove_all (); -+ return err; -+ } -+ } -+ if (!done) -+ grub_net_poll_cards (interval, 0); - } - -- if (is_def) -+ FOR_DHCP6_SESSIONS (se) - { -- grub_env_set ("net_default_interface", name); -- grub_env_export ("net_default_interface"); -+ grub_error_push (); -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, -+ N_("couldn't autoconfigure %s"), -+ se->iface->card->name); - } - -- if (inter) -- grub_net_add_ipv6_local (inter, mask); -- return inter; -+ grub_dhcp6_session_remove_all (); -+ -+ return err; - } - -+static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp, cmd_bootp6; - - void - grub_bootp_init (void) -@@ -1084,11 +1819,15 @@ grub_bootp_init (void) - cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, - N_("VAR INTERFACE NUMBER DESCRIPTION"), - N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); -+ cmd_bootp6 = grub_register_command ("net_bootp6", grub_cmd_bootp6, -+ N_("[CARD]"), -+ N_("perform a DHCPv6 autoconfiguration")); - } - - void - grub_bootp_fini (void) - { -+ grub_unregister_command (cmd_bootp6); - grub_unregister_command (cmd_getdhcp); - grub_unregister_command (cmd_bootp); - grub_unregister_command (cmd_dhcp); -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index a673bea807a..8e25680db0c 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -393,9 +393,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - pxe_mode = pxe->mode; - if (pxe_mode->using_ipv6) - { -- grub_net_link_level_address_t hwaddr; -- struct grub_net_network_level_interface *intf; -- - grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); - grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", - pxe_mode->dhcp_ack_received ? "yes" : "no", -@@ -403,15 +400,14 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - if (!pxe_mode->dhcp_ack_received) - continue; - -- hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; -- grub_memcpy (hwaddr.mac, -- card->efi_net->mode->current_address, -- sizeof (hwaddr.mac)); -- -- intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr, -- (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6, -- 1, device, path); -- if (intf && device && path) -+ grub_net_configure_by_dhcpv6_reply (card->name, card, 0, -+ (struct grub_net_dhcp6_packet *) -+ &pxe_mode->dhcp_ack, -+ sizeof (pxe_mode->dhcp_ack), -+ 1, device, path); -+ if (grub_errno) -+ grub_print_error (); -+ if (device && path) - grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); - } - else -diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c -index a5896f6dc26..ce6bdc75c6d 100644 ---- a/grub-core/net/ip.c -+++ b/grub-core/net/ip.c -@@ -239,6 +239,45 @@ handle_dgram (struct grub_net_buff *nb, - { - struct udphdr *udph; - udph = (struct udphdr *) nb->data; -+ -+ if (proto == GRUB_NET_IP_UDP && udph->dst == grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT)) -+ { -+ if (udph->chksum) -+ { -+ grub_uint16_t chk, expected; -+ chk = udph->chksum; -+ udph->chksum = 0; -+ expected = grub_net_ip_transport_checksum (nb, -+ GRUB_NET_IP_UDP, -+ source, -+ dest); -+ if (expected != chk) -+ { -+ grub_dprintf ("net", "Invalid UDP checksum. " -+ "Expected %x, got %x\n", -+ grub_be_to_cpu16 (expected), -+ grub_be_to_cpu16 (chk)); -+ grub_netbuff_free (nb); -+ return GRUB_ERR_NONE; -+ } -+ udph->chksum = chk; -+ } -+ -+ err = grub_netbuff_pull (nb, sizeof (*udph)); -+ if (err) -+ { -+ grub_netbuff_free (nb); -+ return err; -+ } -+ -+ err = grub_net_process_dhcp6 (nb, card); -+ if (err) -+ grub_print_error (); -+ -+ grub_netbuff_free (nb); -+ return GRUB_ERR_NONE; -+ } -+ - if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) - { - const struct grub_net_bootp_packet *bootp; -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 99628801478..7614b58dca8 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -1532,7 +1532,7 @@ typedef struct grub_efi_pxe_ip_filter - { - grub_efi_uint8_t filters; - grub_efi_uint8_t ip_count; -- grub_efi_uint8_t reserved; -+ grub_efi_uint16_t reserved; - grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; - } grub_efi_pxe_ip_filter_t; - -diff --git a/include/grub/net.h b/include/grub/net.h -index d55d505a03a..543251f7273 100644 ---- a/include/grub/net.h -+++ b/include/grub/net.h -@@ -451,50 +451,65 @@ struct grub_net_bootp_packet - grub_uint8_t vendor[0]; - } GRUB_PACKED; - --enum -- { -- GRUB_NET_DHCP6_IA_NA = 3, -- GRUB_NET_DHCP6_IA_ADDRESS = 5, -- GRUB_NET_DHCP6_BOOTFILE_URL = 59, -- }; -- --struct grub_net_dhcpv6_option -+struct grub_net_dhcp6_packet - { -- grub_uint16_t option_num; -- grub_uint16_t option_len; -- grub_uint8_t option_data[]; -+ grub_uint32_t message_type:8; -+ grub_uint32_t transaction_id:24; -+ grub_uint8_t dhcp_options[0]; - } GRUB_PACKED; --typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t; - --struct grub_net_dhcpv6_opt_ia_na --{ -- grub_uint16_t option_num; -- grub_uint16_t option_len; -+struct grub_net_dhcp6_option { -+ grub_uint16_t code; -+ grub_uint16_t len; -+ grub_uint8_t data[0]; -+} GRUB_PACKED; -+ -+struct grub_net_dhcp6_option_iana { - grub_uint32_t iaid; - grub_uint32_t t1; - grub_uint32_t t2; -- grub_uint8_t options[]; -+ grub_uint8_t data[0]; - } GRUB_PACKED; --typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t; - --struct grub_net_dhcpv6_opt_ia_address --{ -- grub_uint16_t option_num; -- grub_uint16_t option_len; -- grub_uint64_t ipv6_address[2]; -+struct grub_net_dhcp6_option_iaaddr { -+ grub_uint8_t addr[16]; - grub_uint32_t preferred_lifetime; - grub_uint32_t valid_lifetime; -- grub_uint8_t options[]; -+ grub_uint8_t data[0]; - } GRUB_PACKED; --typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t; - --struct grub_net_dhcpv6_packet -+struct grub_net_dhcp6_option_duid_ll - { -- grub_uint32_t message_type:8; -- grub_uint32_t transaction_id:24; -- grub_uint8_t dhcp_options[1024]; -+ grub_uint16_t type; -+ grub_uint16_t hw_type; -+ grub_uint8_t hwaddr[6]; - } GRUB_PACKED; --typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t; -+ -+enum -+ { -+ GRUB_NET_DHCP6_SOLICIT = 1, -+ GRUB_NET_DHCP6_ADVERTISE = 2, -+ GRUB_NET_DHCP6_REQUEST = 3, -+ GRUB_NET_DHCP6_REPLY = 7 -+ }; -+ -+enum -+ { -+ DHCP6_CLIENT_PORT = 546, -+ DHCP6_SERVER_PORT = 547 -+ }; -+ -+enum -+ { -+ GRUB_NET_DHCP6_OPTION_CLIENTID = 1, -+ GRUB_NET_DHCP6_OPTION_SERVERID = 2, -+ GRUB_NET_DHCP6_OPTION_IA_NA = 3, -+ GRUB_NET_DHCP6_OPTION_IAADDR = 5, -+ GRUB_NET_DHCP6_OPTION_ORO = 6, -+ GRUB_NET_DHCP6_OPTION_ELAPSED_TIME = 8, -+ GRUB_NET_DHCP6_OPTION_DNS_SERVERS = 23, -+ GRUB_NET_DHCP6_OPTION_BOOTFILE_URL = 59 -+ }; - - #define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 - #define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 -@@ -532,12 +547,12 @@ grub_net_configure_by_dhcp_ack (const char *name, - int is_def, char **device, char **path); - - struct grub_net_network_level_interface * --grub_net_configure_by_dhcpv6_ack (const char *name, -- struct grub_net_card *card, -- grub_net_interface_flags_t flags, -- const grub_net_link_level_address_t *hwaddr, -- const struct grub_net_dhcpv6_packet *packet, -- int is_def, char **device, char **path); -+grub_net_configure_by_dhcpv6_reply (const char *name, -+ struct grub_net_card *card, -+ grub_net_interface_flags_t flags, -+ const struct grub_net_dhcp6_packet *v6, -+ grub_size_t size, -+ int is_def, char **device, char **path); - - int - grub_ipv6_get_masksize(grub_uint16_t *mask); -@@ -554,6 +569,10 @@ void - grub_net_process_dhcp (struct grub_net_buff *nb, - struct grub_net_network_level_interface *iface); - -+grub_err_t -+grub_net_process_dhcp6 (struct grub_net_buff *nb, -+ struct grub_net_card *card); -+ - int - grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, - const grub_net_link_level_address_t *b); diff --git a/SOURCES/0089-module-verifier-make-it-possible-to-run-checkers-on-.patch b/SOURCES/0089-module-verifier-make-it-possible-to-run-checkers-on-.patch new file mode 100644 index 0000000..78c15d6 --- /dev/null +++ b/SOURCES/0089-module-verifier-make-it-possible-to-run-checkers-on-.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 1 Aug 2018 10:24:52 -0400 +Subject: [PATCH] module-verifier: make it possible to run checkers on + grub-module-verifierxx.c + +This makes it so you can treat grub-module-verifierxx.c as a file you can +build directly, so syntax checkers like vim's "syntastic" plugin, which uses +"gcc -x c -fsyntax-only" to build it, will work. + +One still has to do whatever setup is required to make it pick the right +include dirs, which -W options we use, etc., but this makes it so you can do +the checking on the file you're editing, rather than on a different file. + +v2: fix the typo in the #else clause in util/grub-module-verifierXX.c + +Signed-off-by: Peter Jones +--- + util/grub-module-verifier32.c | 2 ++ + util/grub-module-verifier64.c | 2 ++ + util/grub-module-verifierXX.c | 9 +++++++++ + 3 files changed, 13 insertions(+) + +diff --git a/util/grub-module-verifier32.c b/util/grub-module-verifier32.c +index 257229f8f0..ba7d41aafe 100644 +--- a/util/grub-module-verifier32.c ++++ b/util/grub-module-verifier32.c +@@ -1,2 +1,4 @@ + #define MODULEVERIFIER_ELF32 1 ++#ifndef GRUB_MODULE_VERIFIERXX + #include "grub-module-verifierXX.c" ++#endif +diff --git a/util/grub-module-verifier64.c b/util/grub-module-verifier64.c +index 4db6b4bedd..fc23ef800b 100644 +--- a/util/grub-module-verifier64.c ++++ b/util/grub-module-verifier64.c +@@ -1,2 +1,4 @@ + #define MODULEVERIFIER_ELF64 1 ++#ifndef GRUB_MODULE_VERIFIERXX + #include "grub-module-verifierXX.c" ++#endif +diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c +index ceb24309ae..a98e2f9b1a 100644 +--- a/util/grub-module-verifierXX.c ++++ b/util/grub-module-verifierXX.c +@@ -1,3 +1,12 @@ ++#define GRUB_MODULE_VERIFIERXX ++#if !defined(MODULEVERIFIER_ELF32) && !defined(MODULEVERIFIER_ELF64) ++#if __SIZEOF_POINTER__ == 8 ++#include "grub-module-verifier64.c" ++#else ++#include "grub-module-verifier32.c" ++#endif ++#endif ++ + #include + + #include diff --git a/SOURCES/0090-Rework-how-the-fdt-command-builds.patch b/SOURCES/0090-Rework-how-the-fdt-command-builds.patch new file mode 100644 index 0000000..8f41272 --- /dev/null +++ b/SOURCES/0090-Rework-how-the-fdt-command-builds.patch @@ -0,0 +1,123 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 11 Jul 2019 13:01:41 +0200 +Subject: [PATCH] Rework how the fdt command builds. + +Trying to avoid all variants of: +cat syminfo.lst | sort | gawk -f ../../grub-core/genmoddep.awk > moddep.lst || (rm -f moddep.lst; exit 1) +grub_fdt_install in linux is not defined +grub_fdt_load in linux is not defined +grub_fdt_unload in linux is not defined +grub_fdt_install in xen_boot is not defined +grub_fdt_load in xen_boot is not defined +grub_fdt_unload in xen_boot is not defined + +Signed-off-by: Peter Jones +[javierm: Fix build with platform emu, aarch64, and risc-v] +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Robbie Harwood +--- + grub-core/Makefile.core.def | 5 ++--- + grub-core/lib/fdt.c | 2 -- + grub-core/loader/efi/fdt.c | 2 ++ + include/grub/fdt.h | 6 ++++++ + grub-core/Makefile.am | 1 + + 5 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 12797336c9..4e7d90da76 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -177,7 +177,6 @@ kernel = { + arm_coreboot = kern/arm/coreboot/init.c; + arm_coreboot = kern/arm/coreboot/timer.c; + arm_coreboot = kern/arm/coreboot/coreboot.S; +- arm_coreboot = lib/fdt.c; + arm_coreboot = bus/fdt.c; + arm_coreboot = term/ps2.c; + arm_coreboot = term/arm/pl050.c; +@@ -351,6 +350,8 @@ kernel = { + riscv64 = kern/riscv/cache_flush.S; + riscv64 = kern/riscv/dl.c; + ++ fdt = lib/fdt.c; ++ + emu = disk/host.c; + emu = kern/emu/cache_s.S; + emu = kern/emu/hostdisk.c; +@@ -1825,7 +1826,6 @@ module = { + riscv32 = loader/riscv/linux.c; + riscv64 = loader/riscv/linux.c; + emu = loader/emu/linux.c; +- fdt = lib/fdt.c; + + common = loader/linux.c; + common = lib/cmdline.c; +@@ -1837,7 +1837,6 @@ module = { + module = { + name = fdt; + efi = loader/efi/fdt.c; +- common = lib/fdt.c; + enable = fdt; + }; + +diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c +index 0d371c5633..37e04bd69e 100644 +--- a/grub-core/lib/fdt.c ++++ b/grub-core/lib/fdt.c +@@ -21,8 +21,6 @@ + #include + #include + +-GRUB_MOD_LICENSE ("GPLv3+"); +- + #define FDT_SUPPORTED_VERSION 17 + + #define FDT_BEGIN_NODE 0x00000001 +diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c +index c86f283d75..c572415d38 100644 +--- a/grub-core/loader/efi/fdt.c ++++ b/grub-core/loader/efi/fdt.c +@@ -27,6 +27,8 @@ + #include + #include + ++GRUB_MOD_LICENSE ("GPLv3+"); ++ + static void *loaded_fdt; + static void *fdt; + +diff --git a/include/grub/fdt.h b/include/grub/fdt.h +index e609c7e411..3514aa4a5b 100644 +--- a/include/grub/fdt.h ++++ b/include/grub/fdt.h +@@ -19,6 +19,9 @@ + #ifndef GRUB_FDT_HEADER + #define GRUB_FDT_HEADER 1 + ++#if !defined(GRUB_MACHINE_EMU) && \ ++ (defined(__arm__) || defined(__aarch64__) || defined(__riscv)) ++ + #include + #include + +@@ -144,4 +147,7 @@ int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const ch + grub_fdt_set_prop ((fdt), (nodeoffset), "reg", reg_64, 16); \ + }) + ++#endif /* !defined(GRUB_MACHINE_EMU) && \ ++ (defined(__arm__) || defined(__aarch64__) || defined(__riscv)) */ ++ + #endif /* ! GRUB_FDT_HEADER */ +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index bfd29a3bf0..c2e8a82bce 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -76,6 +76,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/file.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h diff --git a/SOURCES/0090-efinet-UEFI-IPv6-PXE-support.patch b/SOURCES/0090-efinet-UEFI-IPv6-PXE-support.patch deleted file mode 100644 index d8b22b8..0000000 --- a/SOURCES/0090-efinet-UEFI-IPv6-PXE-support.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Wed, 15 Apr 2015 14:48:30 +0800 -Subject: [PATCH] efinet: UEFI IPv6 PXE support - -When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is -cached in firmware buffer which can be obtained by PXE Base Code protocol. The -network interface can be setup through the parameters in that obtained packet. - -Signed-off-by: Michael Chang -Signed-off-by: Ken Lin ---- - grub-core/net/drivers/efi/efinet.c | 2 ++ - include/grub/efi/api.h | 71 +++++++++++++++++++++++--------------- - 2 files changed, 46 insertions(+), 27 deletions(-) - -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index 8e25680db0c..014e5bf9802 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -409,6 +409,8 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - grub_print_error (); - if (device && path) - grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); -+ if (grub_errno) -+ grub_print_error (); - } - else - { -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 7614b58dca8..91ab528e4d0 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -1524,31 +1524,6 @@ typedef union - grub_efi_pxe_dhcpv6_packet_t dhcpv6; - } grub_efi_pxe_packet_t; - --#define GRUB_EFI_PXE_MAX_IPCNT 8 --#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8 --#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8 -- --typedef struct grub_efi_pxe_ip_filter --{ -- grub_efi_uint8_t filters; -- grub_efi_uint8_t ip_count; -- grub_efi_uint16_t reserved; -- grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; --} grub_efi_pxe_ip_filter_t; -- --typedef struct grub_efi_pxe_arp_entry --{ -- grub_efi_ip_address_t ip_addr; -- grub_efi_mac_address_t mac_addr; --} grub_efi_pxe_arp_entry_t; -- --typedef struct grub_efi_pxe_route_entry --{ -- grub_efi_ip_address_t ip_addr; -- grub_efi_ip_address_t subnet_mask; -- grub_efi_ip_address_t gateway_addr; --} grub_efi_pxe_route_entry_t; -- - typedef struct grub_efi_pxe_icmp_error - { - grub_efi_uint8_t type; -@@ -1574,6 +1549,48 @@ typedef struct grub_efi_pxe_tftp_error - grub_efi_char8_t error_string[127]; - } grub_efi_pxe_tftp_error_t; - -+typedef struct { -+ grub_uint8_t addr[4]; -+} grub_efi_pxe_ipv4_address_t; -+ -+typedef struct { -+ grub_uint8_t addr[16]; -+} grub_efi_pxe_ipv6_address_t; -+ -+typedef struct { -+ grub_uint8_t addr[32]; -+} grub_efi_pxe_mac_address_t; -+ -+typedef union { -+ grub_uint32_t addr[4]; -+ grub_efi_pxe_ipv4_address_t v4; -+ grub_efi_pxe_ipv6_address_t v6; -+} grub_efi_pxe_ip_address_t; -+ -+#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 -+typedef struct grub_efi_pxe_ip_filter -+{ -+ grub_efi_uint8_t filters; -+ grub_efi_uint8_t ip_count; -+ grub_efi_uint16_t reserved; -+ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT]; -+} grub_efi_pxe_ip_filter_t; -+ -+typedef struct { -+ grub_efi_pxe_ip_address_t ip_addr; -+ grub_efi_pxe_mac_address_t mac_addr; -+} grub_efi_pxe_arp_entry_t; -+ -+typedef struct { -+ grub_efi_pxe_ip_address_t ip_addr; -+ grub_efi_pxe_ip_address_t subnet_mask; -+ grub_efi_pxe_ip_address_t gw_addr; -+} grub_efi_pxe_route_entry_t; -+ -+ -+#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 -+#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 -+ - typedef struct grub_efi_pxe_mode - { - grub_efi_boolean_t started; -@@ -1605,9 +1622,9 @@ typedef struct grub_efi_pxe_mode - grub_efi_pxe_packet_t pxe_bis_reply; - grub_efi_pxe_ip_filter_t ip_filter; - grub_efi_uint32_t arp_cache_entries; -- grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES]; -+ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; - grub_efi_uint32_t route_table_entries; -- grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES]; -+ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; - grub_efi_pxe_icmp_error_t icmp_error; - grub_efi_pxe_tftp_error_t tftp_error; - } grub_efi_pxe_mode_t; diff --git a/SOURCES/0091-Disable-non-wordsize-allocations-on-arm.patch b/SOURCES/0091-Disable-non-wordsize-allocations-on-arm.patch new file mode 100644 index 0000000..ea09b65 --- /dev/null +++ b/SOURCES/0091-Disable-non-wordsize-allocations-on-arm.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 2 Aug 2018 10:56:38 -0400 +Subject: [PATCH] Disable non-wordsize allocations on arm + +Signed-off-by: Peter Jones +--- + configure.ac | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 008f6c273b..54462e0892 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1260,6 +1260,26 @@ if test "x$target_cpu" = xarm; then + done + ]) + ++ AC_CACHE_CHECK([for options to disable movt and movw relocations], ++ grub_cv_target_cc_mword_relocations, ++ [grub_cv_target_cc_mword_relocations=no ++ for cand in "-mword-relocations" ; do ++ if test x"$grub_cv_target_cc_mword_relocations" != xno ; then ++ break ++ fi ++ CFLAGS="$TARGET_CFLAGS $cand -Werror" ++ CPPFLAGS="$TARGET_CPPFLAGS" ++ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], ++ [grub_cv_target_cc_mword_relocations="$cand"], ++ []) ++ done ++ ]) ++ if test x"$grub_cv_target_cc_mword_relocations" = xno ; then ++ AC_MSG_ERROR(["your compiler doesn't support disabling movw/movt relocations"]) ++ else ++ TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mword_relocations" ++ fi ++ + if test x"$grub_cv_target_cc_mno_movt" != xno ; then + # A trick so that clang doesn't see it on link stage + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_mno_movt" diff --git a/SOURCES/0091-grub.texi-Add-net_bootp6-doument.patch b/SOURCES/0091-grub.texi-Add-net_bootp6-doument.patch deleted file mode 100644 index 3f8ec97..0000000 --- a/SOURCES/0091-grub.texi-Add-net_bootp6-doument.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Tue, 5 May 2015 14:19:24 +0800 -Subject: [PATCH] grub.texi: Add net_bootp6 doument - -Update grub documentation for net_bootp6 command. - -Signed-off-by: Michael Chang -Signed-off-by: Ken Lin ---- - docs/grub.texi | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/docs/grub.texi b/docs/grub.texi -index 0615d0ed97e..04ed6ac1f07 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -5487,6 +5487,7 @@ This command is only available on AArch64 systems. - * net_add_dns:: Add a DNS server - * net_add_route:: Add routing entry - * net_bootp:: Perform a bootp/DHCP autoconfiguration -+* net_bootp6:: Perform a DHCPv6 autoconfiguration - * net_del_addr:: Remove IP address from interface - * net_del_dns:: Remove a DNS server - * net_del_route:: Remove a route entry -@@ -5611,6 +5612,22 @@ Sets environment variable @samp{net_}@var{}@samp{_boot_file} - - @end deffn - -+@node net_bootp6 -+@subsection net_bootp6 -+ -+@deffn Command net_bootp6 [@var{card}] -+Perform configuration of @var{card} using DHCPv6 protocol. If no card name is -+specified, try to configure all existing cards. If configuration was -+successful, interface with name @var{card}@samp{:dhcp6} and configured address -+is added to @var{card}. -+ -+@table @samp -+@item 1 (Domain Name Server) -+Adds all servers from option value to the list of servers used during name -+resolution. -+@end table -+ -+@end deffn - - @node net_get_dhcp_option - @subsection net_get_dhcp_option diff --git a/SOURCES/0092-Prepend-prefix-when-HTTP-path-is-relative.patch b/SOURCES/0092-Prepend-prefix-when-HTTP-path-is-relative.patch new file mode 100644 index 0000000..30d8075 --- /dev/null +++ b/SOURCES/0092-Prepend-prefix-when-HTTP-path-is-relative.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stephen Benjamin +Date: Thu, 16 Aug 2018 16:58:51 -0400 +Subject: [PATCH] Prepend prefix when HTTP path is relative + +This sets a couple of variables. With the url http://www.example.com/foo/bar : +http_path: /foo/bar +http_url: http://www.example.com/foo/bar + +Signed-off-by: Peter Jones +Signed-off-by: Stephen Benjamin +Signed-off-by: Robbie Harwood +--- + grub-core/kern/main.c | 10 +++++- + grub-core/net/efi/http.c | 82 ++++++++++++++++++++++++++++++++++++------------ + 2 files changed, 71 insertions(+), 21 deletions(-) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index d1de9fa687..1c540fc8c2 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -131,11 +131,19 @@ grub_set_prefix_and_root (void) + if (fwdevice && fwpath) + { + char *fw_path; ++ char separator[3] = ")"; + +- fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath); ++ grub_dprintf ("fw_path", "\n"); ++ grub_dprintf ("fw_path", "fwdevice:\"%s\" fwpath:\"%s\"\n", fwdevice, fwpath); ++ ++ if (!grub_strncmp(fwdevice, "http", 4) && fwpath[0] != '/') ++ grub_strcpy(separator, ")/"); ++ ++ fw_path = grub_xasprintf ("(%s%s%s", fwdevice, separator, fwpath); + if (fw_path) + { + grub_env_set ("fw_path", fw_path); ++ grub_dprintf ("fw_path", "fw_path:\"%s\"\n", fw_path); + grub_free (fw_path); + } + } +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +index 243acbaa35..de351b2cd0 100644 +--- a/grub-core/net/efi/http.c ++++ b/grub-core/net/efi/http.c +@@ -9,10 +9,52 @@ + static void + http_configure (struct grub_efi_net_device *dev, int prefer_ip6) + { ++ grub_efi_ipv6_address_t address; + grub_efi_http_config_data_t http_config; + grub_efi_httpv4_access_point_t httpv4_node; + grub_efi_httpv6_access_point_t httpv6_node; + grub_efi_status_t status; ++ int https; ++ char *http_url; ++ const char *rest, *http_server, *http_path = NULL; ++ ++ http_server = grub_env_get ("root"); ++ https = (grub_strncmp (http_server, "https", 5) == 0) ? 1 : 0; ++ ++ /* extract http server + port */ ++ if (http_server) ++ { ++ http_server = grub_strchr (http_server, ','); ++ if (http_server) ++ http_server++; ++ } ++ ++ /* fw_path is like (http,192.168.1.1:8000)/httpboot, extract path part */ ++ http_path = grub_env_get ("fw_path"); ++ if (http_path) ++ { ++ http_path = grub_strchr (http_path, ')'); ++ if (http_path) ++ { ++ http_path++; ++ grub_env_unset ("http_path"); ++ grub_env_set ("http_path", http_path); ++ } ++ } ++ ++ if (http_server && http_path) ++ { ++ if (grub_efi_string_to_ip6_address (http_server, &address, &rest) && *rest == 0) ++ http_url = grub_xasprintf ("%s://[%s]%s", https ? "https" : "http", http_server, http_path); ++ else ++ http_url = grub_xasprintf ("%s://%s%s", https ? "https" : "http", http_server, http_path); ++ if (http_url) ++ { ++ grub_env_unset ("http_url"); ++ grub_env_set ("http_url", http_url); ++ grub_free (http_url); ++ } ++ } + + grub_efi_http_t *http = dev->http; + +@@ -352,32 +394,32 @@ grub_efihttp_open (struct grub_efi_net_device *dev, + grub_err_t err; + grub_off_t size; + char *buf; +- char *root_url; +- grub_efi_ipv6_address_t address; +- const char *rest; ++ char *file_name = NULL; ++ const char *http_path; + +- if (grub_efi_string_to_ip6_address (file->device->net->server, &address, &rest) && *rest == 0) +- root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", file->device->net->server); +- else +- root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", file->device->net->server); +- if (root_url) +- { +- grub_env_unset ("root_url"); +- grub_env_set ("root_url", root_url); +- grub_free (root_url); +- } +- else +- { ++ /* If path is relative, prepend http_path */ ++ http_path = grub_env_get ("http_path"); ++ if (http_path && file->device->net->name[0] != '/') { ++ file_name = grub_xasprintf ("%s/%s", http_path, file->device->net->name); ++ if (!file_name) + return grub_errno; +- } ++ } + +- err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); ++ err = efihttp_request (dev->http, file->device->net->server, ++ file_name ? file_name : file->device->net->name, type, 1, 0); + if (err != GRUB_ERR_NONE) +- return err; ++ { ++ grub_free (file_name); ++ return err; ++ } + +- err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size); ++ err = efihttp_request (dev->http, file->device->net->server, ++ file_name ? file_name : file->device->net->name, type, 0, &size); ++ grub_free (file_name); + if (err != GRUB_ERR_NONE) +- return err; ++ { ++ return err; ++ } + + buf = grub_malloc (size); + efihttp_read (dev, buf, size); diff --git a/SOURCES/0092-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch b/SOURCES/0092-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch deleted file mode 100644 index e800dd2..0000000 --- a/SOURCES/0092-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Wed, 10 Jul 2019 23:58:28 +0200 -Subject: [PATCH] bootp: Add processing DHCPACK packet from HTTP Boot - -The vendor class identifier with the string "HTTPClient" is used to denote the -packet as responding to HTTP boot request. In DHCP4 config, the filename for -HTTP boot is the URL of the boot file while for PXE boot it is the path to the -boot file. As a consequence, the next-server becomes obseleted because the HTTP -URL already contains the server address for the boot file. For DHCP6 config, -there's no difference definition in existing config as dhcp6.bootfile-url can -be used to specify URL for both HTTP and PXE boot file. - -This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK -packet by treating it as HTTP format, not as the PXE format. - -Signed-off-by: Michael Chang -Signed-off-by: Ken Lin ---- - grub-core/net/bootp.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ - include/grub/net.h | 1 + - 2 files changed, 56 insertions(+) - -diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c -index fe93b80f1cf..8fb8918ae7e 100644 ---- a/grub-core/net/bootp.c -+++ b/grub-core/net/bootp.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -500,6 +501,60 @@ grub_net_configure_by_dhcp_ack (const char *name, - if (opt && opt_len) - grub_env_set_net_property (name, "rootpath", (const char *) opt, opt_len); - -+ opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER, &opt_len); -+ if (opt && opt_len) -+ { -+ grub_env_set_net_property (name, "vendor_class_identifier", (const char *) opt, opt_len); -+ if (opt && grub_strcmp (opt, "HTTPClient") == 0) -+ { -+ char *proto, *ip, *pa; -+ -+ if (!dissect_url (bp->boot_file, &proto, &ip, &pa)) -+ return inter; -+ -+ grub_env_set_net_property (name, "boot_file", pa, grub_strlen (pa)); -+ if (is_def) -+ { -+ grub_net_default_server = grub_strdup (ip); -+ grub_env_set ("net_default_interface", name); -+ grub_env_export ("net_default_interface"); -+ } -+ if (device && !*device) -+ { -+ *device = grub_xasprintf ("%s,%s", proto, ip); -+ grub_print_error (); -+ } -+ if (path) -+ { -+ *path = grub_strdup (pa); -+ grub_print_error (); -+ if (*path) -+ { -+ char *slash; -+ slash = grub_strrchr (*path, '/'); -+ if (slash) -+ *slash = 0; -+ else -+ **path = 0; -+ } -+ } -+ grub_net_add_ipv4_local (inter, mask); -+ inter->dhcp_ack = grub_malloc (size); -+ if (inter->dhcp_ack) -+ { -+ grub_memcpy (inter->dhcp_ack, bp, size); -+ inter->dhcp_acklen = size; -+ } -+ else -+ grub_errno = GRUB_ERR_NONE; -+ -+ grub_free (proto); -+ grub_free (ip); -+ grub_free (pa); -+ return inter; -+ } -+ } -+ - opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_EXTENSIONS_PATH, &opt_len); - if (opt && opt_len) - grub_env_set_net_property (name, "extensionspath", (const char *) opt, opt_len); -diff --git a/include/grub/net.h b/include/grub/net.h -index 543251f7273..42af7de250a 100644 ---- a/include/grub/net.h -+++ b/include/grub/net.h -@@ -531,6 +531,7 @@ enum - GRUB_NET_DHCP_MESSAGE_TYPE = 53, - GRUB_NET_DHCP_SERVER_IDENTIFIER = 54, - GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55, -+ GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 60, - GRUB_NET_BOOTP_CLIENT_ID = 61, - GRUB_NET_DHCP_TFTP_SERVER_NAME = 66, - GRUB_NET_DHCP_BOOTFILE_NAME = 67, diff --git a/SOURCES/0093-Make-grub_error-more-verbose.patch b/SOURCES/0093-Make-grub_error-more-verbose.patch new file mode 100644 index 0000000..306a3d3 --- /dev/null +++ b/SOURCES/0093-Make-grub_error-more-verbose.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 27 Aug 2018 13:14:06 -0400 +Subject: [PATCH] Make grub_error() more verbose + +Signed-off-by: Peter Jones +--- + grub-core/kern/err.c | 13 +++++++++++-- + include/grub/err.h | 8 ++++++-- + 2 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c +index 53c734de70..aebfe0cf83 100644 +--- a/grub-core/kern/err.c ++++ b/grub-core/kern/err.c +@@ -33,15 +33,24 @@ static struct grub_error_saved grub_error_stack_items[GRUB_ERROR_STACK_SIZE]; + static int grub_error_stack_pos; + static int grub_error_stack_assert; + ++#ifdef grub_error ++#undef grub_error ++#endif ++ + grub_err_t +-grub_error (grub_err_t n, const char *fmt, ...) ++grub_error (grub_err_t n, const char *file, const int line, const char *fmt, ...) + { + va_list ap; ++ int m; + + grub_errno = n; + ++ m = grub_snprintf (grub_errmsg, sizeof (grub_errmsg), "%s:%d:", file, line); ++ if (m < 0) ++ m = 0; ++ + va_start (ap, fmt); +- grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), _(fmt), ap); ++ grub_vsnprintf (grub_errmsg + m, sizeof (grub_errmsg) - m, _(fmt), ap); + va_end (ap); + + return n; +diff --git a/include/grub/err.h b/include/grub/err.h +index b08d5d0de4..c0f90ef07c 100644 +--- a/include/grub/err.h ++++ b/include/grub/err.h +@@ -85,8 +85,12 @@ struct grub_error_saved + extern grub_err_t EXPORT_VAR(grub_errno); + extern char EXPORT_VAR(grub_errmsg)[GRUB_MAX_ERRMSG]; + +-grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *fmt, ...) +- __attribute__ ((format (GNU_PRINTF, 2, 3))); ++grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *file, const int line, const char *fmt, ...) ++ __attribute__ ((format (GNU_PRINTF, 4, 5))); ++ ++#define grub_error(n, fmt, ...) grub_error (n, __FILE__, __LINE__, fmt, ##__VA_ARGS__) ++ ++ + void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn)); + void EXPORT_FUNC(grub_error_push) (void); + int EXPORT_FUNC(grub_error_pop) (void); diff --git a/SOURCES/0093-efinet-Setting-network-from-UEFI-device-path.patch b/SOURCES/0093-efinet-Setting-network-from-UEFI-device-path.patch deleted file mode 100644 index 11b2a72..0000000 --- a/SOURCES/0093-efinet-Setting-network-from-UEFI-device-path.patch +++ /dev/null @@ -1,405 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Sun, 10 Jul 2016 23:46:31 +0800 -Subject: [PATCH] efinet: Setting network from UEFI device path - -The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no -longer provided for HTTP Boot. Instead, we have to get the HTTP boot -information from the device path nodes defined in following UEFI Specification -sections. - - 9.3.5.12 IPv4 Device Path - 9.3.5.13 IPv6 Device Path - 9.3.5.23 Uniform Resource Identifiers (URI) Device Path - -This patch basically does: - -include/grub/efi/api.h: -Add new structure of Uniform Resource Identifiers (URI) Device Path - -grub-core/net/drivers/efi/efinet.c: -Check if PXE Base Code is available, if not it will try to obtain the netboot -information from the device path where the image booted from. The DHCPACK -packet is recoverd from the information in device patch and feed into the same -DHCP packet processing functions to ensure the network interface is setting up -the same way it used to be. - -Signed-off-by: Michael Chang -Signed-off-by: Ken Lin ---- - grub-core/net/drivers/efi/efinet.c | 284 +++++++++++++++++++++++++++++++++++-- - include/grub/efi/api.h | 11 ++ - 2 files changed, 280 insertions(+), 15 deletions(-) - -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index 014e5bf9802..8171ecaa5e4 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -331,6 +332,227 @@ grub_efinet_findcards (void) - grub_free (handles); - } - -+static struct grub_net_buff * -+grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6) -+{ -+ grub_efi_uint16_t uri_len; -+ grub_efi_device_path_t *ldp, *ddp; -+ grub_efi_uri_device_path_t *uri_dp; -+ struct grub_net_buff *nb; -+ grub_err_t err; -+ -+ ddp = grub_efi_duplicate_device_path (dp); -+ if (!ddp) -+ return NULL; -+ -+ ldp = grub_efi_find_last_device_path (ddp); -+ -+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE -+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) -+ { -+ grub_free (ddp); -+ return NULL; -+ } -+ -+ uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0; -+ -+ if (!uri_len) -+ { -+ grub_free (ddp); -+ return NULL; -+ } -+ -+ uri_dp = (grub_efi_uri_device_path_t *) ldp; -+ -+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ ldp->length = sizeof (*ldp); -+ -+ ldp = grub_efi_find_last_device_path (ddp); -+ -+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE -+ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE -+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) -+ { -+ grub_free (ddp); -+ return NULL; -+ } -+ -+ nb = grub_netbuff_alloc (512); -+ if (!nb) -+ { -+ grub_free (ddp); -+ return NULL; -+ } -+ -+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) -+ { -+ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp; -+ struct grub_net_bootp_packet *bp; -+ grub_uint8_t *ptr; -+ -+ bp = (struct grub_net_bootp_packet *) nb->tail; -+ err = grub_netbuff_put (nb, sizeof (*bp) + 4); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ -+ if (sizeof(bp->boot_file) < uri_len) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ grub_memcpy (bp->boot_file, uri_dp->uri, uri_len); -+ grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip)); -+ grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip)); -+ -+ bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0; -+ bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1; -+ bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2; -+ bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3; -+ -+ ptr = nb->tail; -+ err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ *ptr++ = GRUB_NET_BOOTP_NETMASK; -+ *ptr++ = sizeof (ipv4->subnet_mask); -+ grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask)); -+ -+ ptr = nb->tail; -+ err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ *ptr++ = GRUB_NET_BOOTP_ROUTER; -+ *ptr++ = sizeof (ipv4->gateway_ip_address); -+ grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address)); -+ -+ ptr = nb->tail; -+ err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER; -+ *ptr++ = sizeof ("HTTPClient") - 1; -+ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1); -+ -+ ptr = nb->tail; -+ err = grub_netbuff_put (nb, 1); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ *ptr = GRUB_NET_BOOTP_END; -+ *use_ipv6 = 0; -+ -+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ ldp->length = sizeof (*ldp); -+ ldp = grub_efi_find_last_device_path (ddp); -+ -+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE) -+ { -+ grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp; -+ bp->hw_type = mac->if_type; -+ bp->hw_len = sizeof (bp->mac_addr); -+ grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len); -+ } -+ } -+ else -+ { -+ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp; -+ -+ struct grub_net_dhcp6_packet *d6p; -+ struct grub_net_dhcp6_option *opt; -+ struct grub_net_dhcp6_option_iana *iana; -+ struct grub_net_dhcp6_option_iaaddr *iaaddr; -+ -+ d6p = (struct grub_net_dhcp6_packet *)nb->tail; -+ err = grub_netbuff_put (nb, sizeof(*d6p)); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ d6p->message_type = GRUB_NET_DHCP6_REPLY; -+ -+ opt = (struct grub_net_dhcp6_option *)nb->tail; -+ err = grub_netbuff_put (nb, sizeof(*opt)); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); -+ opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr)); -+ -+ err = grub_netbuff_put (nb, sizeof(*iana)); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ -+ opt = (struct grub_net_dhcp6_option *)nb->tail; -+ err = grub_netbuff_put (nb, sizeof(*opt)); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR); -+ opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr)); -+ -+ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail; -+ err = grub_netbuff_put (nb, sizeof(*iaaddr)); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address)); -+ -+ opt = (struct grub_net_dhcp6_option *)nb->tail; -+ err = grub_netbuff_put (nb, sizeof(*opt) + uri_len); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL); -+ opt->len = grub_cpu_to_be16 (uri_len); -+ grub_memcpy (opt->data, uri_dp->uri, uri_len); -+ -+ *use_ipv6 = 1; -+ } -+ -+ grub_free (ddp); -+ return nb; -+} -+ - static void - grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - char **path) -@@ -346,7 +568,11 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - { - grub_efi_device_path_t *cdp; - struct grub_efi_pxe *pxe; -- struct grub_efi_pxe_mode *pxe_mode; -+ struct grub_efi_pxe_mode *pxe_mode = NULL; -+ grub_uint8_t *packet_buf; -+ grub_size_t packet_bufsz ; -+ int ipv6; -+ struct grub_net_buff *nb = NULL; - - if (card->driver != &efidriver) - continue; -@@ -370,11 +596,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - */ - if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE - || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE -- && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) -+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE -+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) - continue; - dup_dp = grub_efi_duplicate_device_path (dp); - if (!dup_dp) - continue; -+ -+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) -+ { -+ dup_ldp = grub_efi_find_last_device_path (dup_dp); -+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ dup_ldp->length = sizeof (*dup_ldp); -+ } -+ - dup_ldp = grub_efi_find_last_device_path (dup_dp); - dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -@@ -387,23 +623,37 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - - pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, - GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -- if (! pxe) -- continue; -+ if (!pxe) -+ { -+ nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6); -+ if (!nb) -+ { -+ grub_print_error (); -+ continue; -+ } -+ packet_buf = nb->head; -+ packet_bufsz = nb->tail - nb->head; -+ } -+ else -+ { -+ pxe_mode = pxe->mode; -+ packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack; -+ packet_bufsz = sizeof (pxe_mode->dhcp_ack); -+ ipv6 = pxe_mode->using_ipv6; -+ } - -- pxe_mode = pxe->mode; -- if (pxe_mode->using_ipv6) -+ if (ipv6) - { - grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); -- grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", -- pxe_mode->dhcp_ack_received ? "yes" : "no", -- pxe_mode->dhcp_ack_received ? "" : " cannot continue"); -- if (!pxe_mode->dhcp_ack_received) -- continue; -+ if (pxe_mode) -+ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", -+ pxe_mode->dhcp_ack_received ? "yes" : "no", -+ pxe_mode->dhcp_ack_received ? "" : " cannot continue"); - - grub_net_configure_by_dhcpv6_reply (card->name, card, 0, - (struct grub_net_dhcp6_packet *) -- &pxe_mode->dhcp_ack, -- sizeof (pxe_mode->dhcp_ack), -+ packet_buf, -+ packet_bufsz, - 1, device, path); - if (grub_errno) - grub_print_error (); -@@ -417,11 +667,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - grub_dprintf ("efinet", "using ipv4 and dhcp\n"); - grub_net_configure_by_dhcp_ack (card->name, card, 0, - (struct grub_net_bootp_packet *) -- &pxe_mode->dhcp_ack, -- sizeof (pxe_mode->dhcp_ack), -+ packet_buf, -+ packet_bufsz, - 1, device, path); - grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); - } -+ -+ if (nb) -+ grub_netbuff_free (nb); -+ - return; - } - } -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 91ab528e4d0..4a51667adb1 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -864,6 +864,8 @@ struct grub_efi_ipv4_device_path - grub_efi_uint16_t remote_port; - grub_efi_uint16_t protocol; - grub_efi_uint8_t static_ip_address; -+ grub_efi_ipv4_address_t gateway_ip_address; -+ grub_efi_ipv4_address_t subnet_mask; - } GRUB_PACKED; - typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t; - -@@ -918,6 +920,15 @@ struct grub_efi_sata_device_path - } GRUB_PACKED; - typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t; - -+#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24 -+ -+struct grub_efi_uri_device_path -+{ -+ grub_efi_device_path_t header; -+ grub_efi_uint8_t uri[0]; -+} GRUB_PACKED; -+typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t; -+ - #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 - - /* Media Device Path. */ diff --git a/SOURCES/0094-Make-reset-an-alias-for-the-reboot-command.patch b/SOURCES/0094-Make-reset-an-alias-for-the-reboot-command.patch new file mode 100644 index 0000000..22475d6 --- /dev/null +++ b/SOURCES/0094-Make-reset-an-alias-for-the-reboot-command.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 31 Aug 2018 16:42:03 -0400 +Subject: [PATCH] Make "reset" an alias for the "reboot" command. + +I'm really tired of half the tools I get to use having one and the other half +having the other. + +Signed-off-by: Peter Jones +--- + grub-core/commands/reboot.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/grub-core/commands/reboot.c b/grub-core/commands/reboot.c +index 46d364c99a..f5cc228363 100644 +--- a/grub-core/commands/reboot.c ++++ b/grub-core/commands/reboot.c +@@ -32,15 +32,18 @@ grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)), + grub_reboot (); + } + +-static grub_command_t cmd; ++static grub_command_t reboot_cmd, reset_cmd; + + GRUB_MOD_INIT(reboot) + { +- cmd = grub_register_command ("reboot", grub_cmd_reboot, +- 0, N_("Reboot the computer.")); ++ reboot_cmd = grub_register_command ("reboot", grub_cmd_reboot, ++ 0, N_("Reboot the computer.")); ++ reset_cmd = grub_register_command ("reset", grub_cmd_reboot, ++ 0, N_("Reboot the computer.")); + } + + GRUB_MOD_FINI(reboot) + { +- grub_unregister_command (cmd); ++ grub_unregister_command (reboot_cmd); ++ grub_unregister_command (reset_cmd); + } diff --git a/SOURCES/0094-efinet-Setting-DNS-server-from-UEFI-protocol.patch b/SOURCES/0094-efinet-Setting-DNS-server-from-UEFI-protocol.patch deleted file mode 100644 index 1460c8a..0000000 --- a/SOURCES/0094-efinet-Setting-DNS-server-from-UEFI-protocol.patch +++ /dev/null @@ -1,336 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Thu, 14 Jul 2016 17:48:45 +0800 -Subject: [PATCH] efinet: Setting DNS server from UEFI protocol - -In the URI device path node, any name rahter than address can be used for -looking up the resources so that DNS service become needed to get answer of the -name's address. Unfortunately the DNS is not defined in any of the device path -nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL -to obtain it. - -These two protcols are defined the sections of UEFI specification. - - 27.5 EFI IPv4 Configuration II Protocol - 27.7 EFI IPv6 Configuration Protocol - -include/grub/efi/api.h: -Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and -EFI_IP6_CONFIG_PROTOCOL. - -grub-core/net/drivers/efi/efinet.c: -Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list -of DNS server address for IPv4 and IPv6 respectively. The address of DNS -servers is structured into DHCPACK packet and feed into the same DHCP packet -processing functions to ensure the network interface is setting up the same way -it used to be. - -Signed-off-by: Michael Chang -Signed-off-by: Ken Lin ---- - grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++ - include/grub/efi/api.h | 75 +++++++++++++++++ - 2 files changed, 238 insertions(+) - -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index 8171ecaa5e4..715a6168d77 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -33,6 +33,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); - /* GUID. */ - static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; - static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; -+static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID; -+static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID; - - static grub_err_t - send_card_buffer (struct grub_net_card *dev, -@@ -332,6 +334,125 @@ grub_efinet_findcards (void) - grub_free (handles); - } - -+static grub_efi_handle_t -+grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path, -+ grub_efi_device_path_t **r_device_path) -+{ -+ grub_efi_handle_t handle; -+ grub_efi_status_t status; -+ -+ status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path, -+ protocol, &device_path, &handle); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ -+ if (r_device_path) -+ *r_device_path = device_path; -+ -+ return handle; -+} -+ -+static grub_efi_ipv4_address_t * -+grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns) -+{ -+ grub_efi_handle_t hnd; -+ grub_efi_status_t status; -+ grub_efi_ip4_config2_protocol_t *conf; -+ grub_efi_ipv4_address_t *addrs; -+ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t); -+ -+ hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL); -+ -+ if (!hnd) -+ return 0; -+ -+ conf = grub_efi_open_protocol (hnd, &ip4_config_guid, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ -+ if (!conf) -+ return 0; -+ -+ addrs = grub_malloc (data_size); -+ if (!addrs) -+ return 0; -+ -+ status = efi_call_4 (conf->get_data, conf, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, -+ &data_size, addrs); -+ -+ if (status == GRUB_EFI_BUFFER_TOO_SMALL) -+ { -+ grub_free (addrs); -+ addrs = grub_malloc (data_size); -+ if (!addrs) -+ return 0; -+ -+ status = efi_call_4 (conf->get_data, conf, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, -+ &data_size, addrs); -+ } -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (addrs); -+ return 0; -+ } -+ -+ *num_dns = data_size / sizeof (grub_efi_ipv4_address_t); -+ return addrs; -+} -+ -+static grub_efi_ipv6_address_t * -+grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns) -+{ -+ grub_efi_handle_t hnd; -+ grub_efi_status_t status; -+ grub_efi_ip6_config_protocol_t *conf; -+ grub_efi_ipv6_address_t *addrs; -+ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t); -+ -+ hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL); -+ -+ if (!hnd) -+ return 0; -+ -+ conf = grub_efi_open_protocol (hnd, &ip6_config_guid, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ -+ if (!conf) -+ return 0; -+ -+ addrs = grub_malloc (data_size); -+ if (!addrs) -+ return 0; -+ -+ status = efi_call_4 (conf->get_data, conf, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, -+ &data_size, addrs); -+ -+ if (status == GRUB_EFI_BUFFER_TOO_SMALL) -+ { -+ grub_free (addrs); -+ addrs = grub_malloc (data_size); -+ if (!addrs) -+ return 0; -+ -+ status = efi_call_4 (conf->get_data, conf, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, -+ &data_size, addrs); -+ } -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (addrs); -+ return 0; -+ } -+ -+ *num_dns = data_size / sizeof (grub_efi_ipv6_address_t); -+ return addrs; -+} -+ - static struct grub_net_buff * - grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6) - { -@@ -390,6 +511,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u - grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp; - struct grub_net_bootp_packet *bp; - grub_uint8_t *ptr; -+ grub_efi_ipv4_address_t *dns; -+ grub_efi_uintn_t num_dns; - - bp = (struct grub_net_bootp_packet *) nb->tail; - err = grub_netbuff_put (nb, sizeof (*bp) + 4); -@@ -451,6 +574,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u - *ptr++ = sizeof ("HTTPClient") - 1; - grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1); - -+ dns = grub_dns_server_ip4_address (dp, &num_dns); -+ if (dns) -+ { -+ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns; -+ -+ ptr = nb->tail; -+ err = grub_netbuff_put (nb, size_dns + 2); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ *ptr++ = GRUB_NET_BOOTP_DNS; -+ *ptr++ = size_dns; -+ grub_memcpy (ptr, dns, size_dns); -+ grub_free (dns); -+ } -+ - ptr = nb->tail; - err = grub_netbuff_put (nb, 1); - if (err) -@@ -483,6 +625,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u - struct grub_net_dhcp6_option *opt; - struct grub_net_dhcp6_option_iana *iana; - struct grub_net_dhcp6_option_iaaddr *iaaddr; -+ grub_efi_ipv6_address_t *dns; -+ grub_efi_uintn_t num_dns; - - d6p = (struct grub_net_dhcp6_packet *)nb->tail; - err = grub_netbuff_put (nb, sizeof(*d6p)); -@@ -546,6 +690,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u - opt->len = grub_cpu_to_be16 (uri_len); - grub_memcpy (opt->data, uri_dp->uri, uri_len); - -+ dns = grub_dns_server_ip6_address (dp, &num_dns); -+ if (dns) -+ { -+ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns; -+ -+ opt = (struct grub_net_dhcp6_option *)nb->tail; -+ err = grub_netbuff_put (nb, sizeof(*opt) + size_dns); -+ if (err) -+ { -+ grub_free (ddp); -+ grub_netbuff_free (nb); -+ return NULL; -+ } -+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS); -+ opt->len = grub_cpu_to_be16 (size_dns); -+ grub_memcpy (opt->data, dns, size_dns); -+ grub_free (dns); -+ } -+ - *use_ipv6 = 1; - } - -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 4a51667adb1..0b490195ad9 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -352,6 +352,15 @@ - #define GRUB_EFI_RNG_PROTOCOL_GUID \ - { 0x3152bca5, 0xeade, 0x433d, \ - { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \ -+ -+#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \ -+ { 0x5b446ed1, 0xe30b, 0x4faa, \ -+ { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \ -+ } -+ -+#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \ -+ { 0x937fe521, 0x95ae, 0x4d1a, \ -+ { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ - } - - struct grub_efi_sal_system_table -@@ -1883,6 +1892,72 @@ struct grub_efi_rng_protocol - }; - typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t; - -+enum grub_efi_ip4_config2_data_type { -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM -+}; -+typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t; -+ -+struct grub_efi_ip4_config2_protocol -+{ -+ grub_efi_status_t (*set_data) (struct grub_efi_ip4_config2_protocol *this, -+ grub_efi_ip4_config2_data_type_t data_type, -+ grub_efi_uintn_t data_size, -+ void *data); -+ -+ grub_efi_status_t (*get_data) (struct grub_efi_ip4_config2_protocol *this, -+ grub_efi_ip4_config2_data_type_t data_type, -+ grub_efi_uintn_t *data_size, -+ void *data); -+ -+ grub_efi_status_t (*register_data_notify) (struct grub_efi_ip4_config2_protocol *this, -+ grub_efi_ip4_config2_data_type_t data_type, -+ grub_efi_event_t event); -+ -+ grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this, -+ grub_efi_ip4_config2_data_type_t data_type, -+ grub_efi_event_t event); -+}; -+typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t; -+ -+enum grub_efi_ip6_config_data_type { -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM -+}; -+typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t; -+ -+struct grub_efi_ip6_config_protocol -+{ -+ grub_efi_status_t (*set_data) (struct grub_efi_ip6_config_protocol *this, -+ grub_efi_ip6_config_data_type_t data_type, -+ grub_efi_uintn_t data_size, -+ void *data); -+ -+ grub_efi_status_t (*get_data) (struct grub_efi_ip6_config_protocol *this, -+ grub_efi_ip6_config_data_type_t data_type, -+ grub_efi_uintn_t *data_size, -+ void *data); -+ -+ grub_efi_status_t (*register_data_notify) (struct grub_efi_ip6_config_protocol *this, -+ grub_efi_ip6_config_data_type_t data_type, -+ grub_efi_event_t event); -+ -+ grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip6_config_protocol *this, -+ grub_efi_ip6_config_data_type_t data_type, -+ grub_efi_event_t event); -+}; -+typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t; -+ - #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ - || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ - || defined(__riscv) diff --git a/SOURCES/0095-Add-a-version-command.patch b/SOURCES/0095-Add-a-version-command.patch new file mode 100644 index 0000000..18c355c --- /dev/null +++ b/SOURCES/0095-Add-a-version-command.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 11 Sep 2018 14:20:37 -0400 +Subject: [PATCH] Add a "version" command + +This adds a command that shows you info about grub's version, the grub +target platform, the compiler version, and if you built with +--with-rpm-version=, the rpm package version. + +Signed-off-by: Peter Jones +[rharwood: don't say GNU, commit message cleanup] +Signed-off-by: Robbie Harwood +--- + configure.ac | 13 ++++++++++ + grub-core/Makefile.core.def | 5 ++++ + grub-core/commands/version.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ + config.h.in | 1 + + 4 files changed, 75 insertions(+) + create mode 100644 grub-core/commands/version.c + +diff --git a/configure.ac b/configure.ac +index 54462e0892..7b4e1854d3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -284,6 +284,19 @@ AC_SUBST(target_cpu) + AC_SUBST(platform) + + # Define default variables ++have_with_rpm_version=n ++AC_ARG_WITH([rpm_version], ++ AS_HELP_STRING([--with-rpm-version=VERSION], ++ [set the rpm package version [[guessed]]]), ++ [have_with_rpm_version=y], ++ [have_with_rpm_version=n]) ++if test x$have_with_rpm_version = xy; then ++ rpm_version="$with_rpm_version" ++else ++ rpm_version="" ++fi ++GRUB_RPM_VERSION="$rpm_version" ++AC_SUBST(GRUB_RPM_VERSION) + + have_with_bootdir=n + AC_ARG_WITH([bootdir], +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 4e7d90da76..4f203533f5 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -579,6 +579,11 @@ image = { + enable = mips_loongson; + }; + ++module = { ++ name = version; ++ common = commands/version.c; ++}; ++ + module = { + name = disk; + common = lib/disk.c; +diff --git a/grub-core/commands/version.c b/grub-core/commands/version.c +new file mode 100644 +index 0000000000..de0acb07ba +--- /dev/null ++++ b/grub-core/commands/version.c +@@ -0,0 +1,56 @@ ++/* version.c - Command to print the grub version and build info. */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_err_t ++grub_cmd_version (grub_command_t cmd UNUSED, int argc, char **args UNUSED) ++{ ++ if (argc != 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("no arguments expected")); ++ ++ grub_printf (_("GRUB version %s\n"), PACKAGE_VERSION); ++ grub_printf (_("Platform %s-%s\n"), GRUB_TARGET_CPU, GRUB_PLATFORM); ++ if (grub_strlen(GRUB_RPM_VERSION) != 0) ++ grub_printf (_("RPM package version %s\n"), GRUB_RPM_VERSION); ++ grub_printf (_("Compiler version %s\n"), __VERSION__); ++ ++ return 0; ++} ++ ++static grub_command_t cmd; ++ ++GRUB_MOD_INIT(version) ++{ ++ cmd = grub_register_command ("version", grub_cmd_version, NULL, ++ N_("Print version and build information.")); ++} ++ ++GRUB_MOD_FINI(version) ++{ ++ grub_unregister_command (cmd); ++} +diff --git a/config.h.in b/config.h.in +index 9e8f9911b1..c7e316f0f1 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -59,6 +59,7 @@ + + #define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" + #define GRUB_PLATFORM "@GRUB_PLATFORM@" ++#define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" + + #define RE_ENABLE_I18N 1 + diff --git a/SOURCES/0095-Support-UEFI-networking-protocols.patch b/SOURCES/0095-Support-UEFI-networking-protocols.patch deleted file mode 100644 index fb14386..0000000 --- a/SOURCES/0095-Support-UEFI-networking-protocols.patch +++ /dev/null @@ -1,5053 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang -Date: Wed, 22 Feb 2017 14:27:50 +0800 -Subject: [PATCH] Support UEFI networking protocols - -References: fate#320130, bsc#1015589, bsc#1076132 -Patch-Mainline: no - -V1: - * Add preliminary support of UEFI networking protocols - * Support UEFI HTTPS Boot - -V2: - * Workaround http data access in firmware - * Fix DNS device path parsing for efinet device - * Relaxed UEFI Protocol requirement - * Support Intel OPA (Omni-Path Architecture) PXE Boot - -V3: - * Fix bufio in calculating address of next_buf - * Check HTTP respond code - * Use HEAD request method to test before GET - * Finish HTTP transaction in one go - * Fix bsc#1076132 - -Signed-off-by: Michael Chang -[pjones: make efi_netfs not duplicate symbols from efinet] -Signed-off-by: Peter Jones ---- - grub-core/Makefile.core.def | 12 + - grub-core/io/bufio.c | 2 +- - grub-core/kern/efi/efi.c | 96 ++- - grub-core/net/drivers/efi/efinet.c | 27 + - grub-core/net/efi/dhcp.c | 397 ++++++++++ - grub-core/net/efi/efi_netfs.c | 57 ++ - grub-core/net/efi/http.c | 419 +++++++++++ - grub-core/net/efi/ip4_config.c | 398 ++++++++++ - grub-core/net/efi/ip6_config.c | 422 +++++++++++ - grub-core/net/efi/net.c | 1428 ++++++++++++++++++++++++++++++++++++ - grub-core/net/efi/pxe.c | 424 +++++++++++ - grub-core/net/net.c | 74 ++ - util/grub-mknetdir.c | 23 +- - include/grub/efi/api.h | 180 ++++- - include/grub/efi/dhcp.h | 343 +++++++++ - include/grub/efi/http.h | 215 ++++++ - include/grub/net/efi.h | 144 ++++ - 17 files changed, 4620 insertions(+), 41 deletions(-) - create mode 100644 grub-core/net/efi/dhcp.c - create mode 100644 grub-core/net/efi/efi_netfs.c - create mode 100644 grub-core/net/efi/http.c - create mode 100644 grub-core/net/efi/ip4_config.c - create mode 100644 grub-core/net/efi/ip6_config.c - create mode 100644 grub-core/net/efi/net.c - create mode 100644 grub-core/net/efi/pxe.c - create mode 100644 include/grub/efi/dhcp.h - create mode 100644 include/grub/efi/http.h - create mode 100644 include/grub/net/efi.h - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 4b7c45a7b06..c40170f2dd2 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2299,6 +2299,12 @@ module = { - common = hook/datehook.c; - }; - -+module = { -+ name = efi_netfs; -+ common = net/efi/efi_netfs.c; -+ enable = efi; -+}; -+ - module = { - name = net; - common = net/net.c; -@@ -2312,6 +2318,12 @@ module = { - common = net/ethernet.c; - common = net/arp.c; - common = net/netbuff.c; -+ efi = net/efi/net.c; -+ efi = net/efi/http.c; -+ efi = net/efi/pxe.c; -+ efi = net/efi/ip4_config.c; -+ efi = net/efi/ip6_config.c; -+ efi = net/efi/dhcp.c; - }; - - module = { -diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c -index a458c3aca78..1637731535e 100644 ---- a/grub-core/io/bufio.c -+++ b/grub-core/io/bufio.c -@@ -139,7 +139,7 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len) - return res; - - /* Need to read some more. */ -- next_buf = (file->offset + res + len - 1) & ~((grub_off_t) bufio->block_size - 1); -+ next_buf = (grub_divmod64 (file->offset + res + len - 1, bufio->block_size, NULL)) * bufio->block_size; - /* Now read between file->offset + res and bufio->buffer_at. */ - if (file->offset + res < next_buf) - { -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index d6a2fb57789..2a446f5031b 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -755,7 +755,7 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) - { - grub_efi_ipv4_device_path_t *ipv4 - = (grub_efi_ipv4_device_path_t *) dp; -- grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)", -+ grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x", - (unsigned) ipv4->local_ip_address[0], - (unsigned) ipv4->local_ip_address[1], - (unsigned) ipv4->local_ip_address[2], -@@ -768,33 +768,60 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) - (unsigned) ipv4->remote_port, - (unsigned) ipv4->protocol, - (unsigned) ipv4->static_ip_address); -+ if (len == sizeof (*ipv4)) -+ { -+ grub_printf (",%u.%u.%u.%u,%u.%u.%u.%u", -+ (unsigned) ipv4->gateway_ip_address[0], -+ (unsigned) ipv4->gateway_ip_address[1], -+ (unsigned) ipv4->gateway_ip_address[2], -+ (unsigned) ipv4->gateway_ip_address[3], -+ (unsigned) ipv4->subnet_mask[0], -+ (unsigned) ipv4->subnet_mask[1], -+ (unsigned) ipv4->subnet_mask[2], -+ (unsigned) ipv4->subnet_mask[3]); -+ } -+ grub_printf (")"); - } - break; - case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE: - { - grub_efi_ipv6_device_path_t *ipv6 - = (grub_efi_ipv6_device_path_t *) dp; -- grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)", -- (unsigned) ipv6->local_ip_address[0], -- (unsigned) ipv6->local_ip_address[1], -- (unsigned) ipv6->local_ip_address[2], -- (unsigned) ipv6->local_ip_address[3], -- (unsigned) ipv6->local_ip_address[4], -- (unsigned) ipv6->local_ip_address[5], -- (unsigned) ipv6->local_ip_address[6], -- (unsigned) ipv6->local_ip_address[7], -- (unsigned) ipv6->remote_ip_address[0], -- (unsigned) ipv6->remote_ip_address[1], -- (unsigned) ipv6->remote_ip_address[2], -- (unsigned) ipv6->remote_ip_address[3], -- (unsigned) ipv6->remote_ip_address[4], -- (unsigned) ipv6->remote_ip_address[5], -- (unsigned) ipv6->remote_ip_address[6], -- (unsigned) ipv6->remote_ip_address[7], -+ grub_printf ("/IPv6(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%u,%u,%x,%x", -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[0]), -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[1]), -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[2]), -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[3]), -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[4]), -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[5]), -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[6]), -+ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[7]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[0]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[1]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[2]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[3]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[4]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[5]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[6]), -+ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[7]), - (unsigned) ipv6->local_port, - (unsigned) ipv6->remote_port, - (unsigned) ipv6->protocol, - (unsigned) ipv6->static_ip_address); -+ if (len == sizeof (*ipv6)) -+ { -+ grub_printf (",%u,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", -+ (unsigned) ipv6->prefix_length, -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[0]), -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[1]), -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[2]), -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[3]), -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[4]), -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[5]), -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[6]), -+ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[7])); -+ } -+ grub_printf (")"); - } - break; - case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE: -@@ -834,6 +861,39 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) - dump_vendor_path ("Messaging", - (grub_efi_vendor_device_path_t *) dp); - break; -+ case GRUB_EFI_URI_DEVICE_PATH_SUBTYPE: -+ { -+ grub_efi_uri_device_path_t *uri -+ = (grub_efi_uri_device_path_t *) dp; -+ grub_printf ("/URI(%s)", uri->uri); -+ } -+ break; -+ case GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE: -+ { -+ grub_efi_dns_device_path_t *dns -+ = (grub_efi_dns_device_path_t *) dp; -+ if (dns->is_ipv6) -+ { -+ grub_printf ("/DNS(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)", -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0]) >> 16), -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0])), -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1]) >> 16), -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1])), -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2]) >> 16), -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2])), -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]) >> 16), -+ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]))); -+ } -+ else -+ { -+ grub_printf ("/DNS(%d.%d.%d.%d)", -+ dns->dns_server_ip[0].v4.addr[0], -+ dns->dns_server_ip[0].v4.addr[1], -+ dns->dns_server_ip[0].v4.addr[2], -+ dns->dns_server_ip[0].v4.addr[3]); -+ } -+ } -+ break; - default: - grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype); - break; -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index 715a6168d77..e11d759f19a 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -491,6 +492,17 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u - - ldp = grub_efi_find_last_device_path (ddp); - -+ /* Skip the DNS Device */ -+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE -+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE) -+ { -+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ ldp->length = sizeof (*ldp); -+ -+ ldp = grub_efi_find_last_device_path (ddp); -+ } -+ - if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE - || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE - && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) -@@ -760,6 +772,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE - || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE - && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE -+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE - && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) - continue; - dup_dp = grub_efi_duplicate_device_path (dp); -@@ -774,6 +787,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - dup_ldp->length = sizeof (*dup_ldp); - } - -+ dup_ldp = grub_efi_find_last_device_path (dup_dp); -+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE) -+ { -+ dup_ldp = grub_efi_find_last_device_path (dup_dp); -+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ dup_ldp->length = sizeof (*dup_ldp); -+ } -+ - dup_ldp = grub_efi_find_last_device_path (dup_dp); - dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -@@ -845,6 +867,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - - GRUB_MOD_INIT(efinet) - { -+ if (grub_efi_net_config) -+ return; -+ - grub_efinet_findcards (); - grub_efi_net_config = grub_efi_net_config_real; - } -@@ -856,5 +881,7 @@ GRUB_MOD_FINI(efinet) - FOR_NET_CARDS_SAFE (card, next) - if (card->driver == &efidriver) - grub_net_card_unregister (card); -+ -+ grub_efi_net_config = NULL; - } - -diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c -new file mode 100644 -index 00000000000..dbef63d8c08 ---- /dev/null -+++ b/grub-core/net/efi/dhcp.c -@@ -0,0 +1,397 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef GRUB_EFI_NET_DEBUG -+static void -+dhcp4_mode_print (grub_efi_dhcp4_mode_data_t *mode) -+{ -+ switch (mode->state) -+ { -+ case GRUB_EFI_DHCP4_STOPPED: -+ grub_printf ("STATE: STOPPED\n"); -+ break; -+ case GRUB_EFI_DHCP4_INIT: -+ grub_printf ("STATE: INIT\n"); -+ break; -+ case GRUB_EFI_DHCP4_SELECTING: -+ grub_printf ("STATE: SELECTING\n"); -+ break; -+ case GRUB_EFI_DHCP4_REQUESTING: -+ grub_printf ("STATE: REQUESTING\n"); -+ break; -+ case GRUB_EFI_DHCP4_BOUND: -+ grub_printf ("STATE: BOUND\n"); -+ break; -+ case GRUB_EFI_DHCP4_RENEWING: -+ grub_printf ("STATE: RENEWING\n"); -+ break; -+ case GRUB_EFI_DHCP4_REBINDING: -+ grub_printf ("STATE: REBINDING\n"); -+ break; -+ case GRUB_EFI_DHCP4_INIT_REBOOT: -+ grub_printf ("STATE: INIT_REBOOT\n"); -+ break; -+ case GRUB_EFI_DHCP4_REBOOTING: -+ grub_printf ("STATE: REBOOTING\n"); -+ break; -+ default: -+ grub_printf ("STATE: UNKNOWN\n"); -+ break; -+ } -+ -+ grub_printf ("CLIENT_ADDRESS: %u.%u.%u.%u\n", -+ mode->client_address[0], -+ mode->client_address[1], -+ mode->client_address[2], -+ mode->client_address[3]); -+ grub_printf ("SERVER_ADDRESS: %u.%u.%u.%u\n", -+ mode->server_address[0], -+ mode->server_address[1], -+ mode->server_address[2], -+ mode->server_address[3]); -+ grub_printf ("SUBNET_MASK: %u.%u.%u.%u\n", -+ mode->subnet_mask[0], -+ mode->subnet_mask[1], -+ mode->subnet_mask[2], -+ mode->subnet_mask[3]); -+ grub_printf ("ROUTER_ADDRESS: %u.%u.%u.%u\n", -+ mode->router_address[0], -+ mode->router_address[1], -+ mode->router_address[2], -+ mode->router_address[3]); -+} -+#endif -+ -+static grub_efi_ipv4_address_t * -+grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packet_t *reply_packet) -+{ -+ grub_efi_dhcp4_packet_option_t **option_list; -+ grub_efi_status_t status; -+ grub_efi_uint32_t option_count = 0; -+ grub_efi_uint32_t i; -+ -+ status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, NULL); -+ -+ if (status != GRUB_EFI_BUFFER_TOO_SMALL) -+ return NULL; -+ -+ option_list = grub_malloc (option_count * sizeof(*option_list)); -+ if (!option_list) -+ return NULL; -+ -+ status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, option_list); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (option_list); -+ return NULL; -+ } -+ -+ for (i = 0; i < option_count; ++i) -+ { -+ if (option_list[i]->op_code == 6) -+ { -+ grub_efi_ipv4_address_t *dns_address; -+ -+ if (((option_list[i]->length & 0x3) != 0) || (option_list[i]->length == 0)) -+ continue; -+ -+ /* We only contact primary dns */ -+ dns_address = grub_malloc (sizeof (*dns_address)); -+ if (!dns_address) -+ { -+ grub_free (option_list); -+ return NULL; -+ } -+ grub_memcpy (dns_address, option_list[i]->data, sizeof (dns_address)); -+ grub_free (option_list); -+ return dns_address; -+ } -+ } -+ -+ grub_free (option_list); -+ return NULL; -+} -+ -+#if 0 -+/* Somehow this doesn't work ... */ -+static grub_err_t -+grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)), -+ int argc __attribute__ ((unused)), -+ char **args __attribute__ ((unused))) -+{ -+ struct grub_efi_net_device *dev; -+ for (dev = net_devices; dev; dev = dev->next) -+ { -+ grub_efi_pxe_t *pxe = dev->ip4_pxe; -+ grub_efi_pxe_mode_t *mode = pxe->mode; -+ grub_efi_status_t status; -+ -+ if (!mode->started) -+ { -+ status = efi_call_2 (pxe->start, pxe, 0); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ grub_printf ("Couldn't start PXE\n"); -+ } -+ -+ status = efi_call_2 (pxe->dhcp, pxe, 0); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("dhcp4 configure failed, %d\n", (int)status); -+ continue; -+ } -+ -+ dev->prefer_ip6 = 0; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+#endif -+ -+static grub_err_t -+grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)), -+ int argc, -+ char **args) -+{ -+ struct grub_efi_net_device *netdev; -+ -+ for (netdev = net_devices; netdev; netdev = netdev->next) -+ { -+ grub_efi_status_t status; -+ grub_efi_dhcp4_mode_data_t mode; -+ grub_efi_dhcp4_config_data_t config; -+ grub_efi_dhcp4_packet_option_t *options; -+ grub_efi_ipv4_address_t *dns_address; -+ grub_efi_net_ip_manual_address_t net_ip; -+ grub_efi_net_ip_address_t ip_addr; -+ grub_efi_net_interface_t *inf = NULL; -+ -+ if (argc > 0 && grub_strcmp (netdev->card_name, args[0]) != 0) -+ continue; -+ -+ grub_memset (&config, 0, sizeof(config)); -+ -+ config.option_count = 1; -+ options = grub_malloc (sizeof(*options) + 2); -+ /* Parameter request list */ -+ options->op_code = 55; -+ options->length = 3; -+ /* subnet mask */ -+ options->data[0] = 1; -+ /* router */ -+ options->data[1] = 3; -+ /* DNS */ -+ options->data[2] = 6; -+ config.option_list = &options; -+ -+ /* FIXME: What if the dhcp has bounded */ -+ status = efi_call_2 (netdev->dhcp4->configure, netdev->dhcp4, &config); -+ grub_free (options); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("dhcp4 configure failed, %d\n", (int)status); -+ continue; -+ } -+ -+ status = efi_call_2 (netdev->dhcp4->start, netdev->dhcp4, NULL); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("dhcp4 start failed, %d\n", (int)status); -+ continue; -+ } -+ -+ status = efi_call_2 (netdev->dhcp4->get_mode_data, netdev->dhcp4, &mode); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("dhcp4 get mode failed, %d\n", (int)status); -+ continue; -+ } -+ -+#ifdef GRUB_EFI_NET_DEBUG -+ dhcp4_mode_print (&mode); -+#endif -+ -+ for (inf = netdev->net_interfaces; inf; inf = inf->next) -+ if (inf->prefer_ip6 == 0) -+ break; -+ -+ grub_memcpy (net_ip.ip4.address, mode.client_address, sizeof (net_ip.ip4.address)); -+ grub_memcpy (net_ip.ip4.subnet_mask, mode.subnet_mask, sizeof (net_ip.ip4.subnet_mask)); -+ -+ if (!inf) -+ { -+ char *name = grub_xasprintf ("%s:dhcp", netdev->card_name); -+ -+ net_ip.is_ip6 = 0; -+ inf = grub_efi_net_create_interface (netdev, -+ name, -+ &net_ip, -+ 1); -+ grub_free (name); -+ } -+ else -+ { -+ efi_net_interface_set_address (inf, &net_ip, 1); -+ } -+ -+ grub_memcpy (ip_addr.ip4, mode.router_address, sizeof (ip_addr.ip4)); -+ efi_net_interface_set_gateway (inf, &ip_addr); -+ -+ dns_address = grub_efi_dhcp4_parse_dns (netdev->dhcp4, mode.reply_packet); -+ if (dns_address) -+ efi_net_interface_set_dns (inf, (grub_efi_net_ip_address_t *)&dns_address); -+ -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+ -+static grub_err_t -+grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)), -+ int argc, -+ char **args) -+{ -+ struct grub_efi_net_device *dev; -+ grub_efi_uint32_t ia_id; -+ -+ for (dev = net_devices, ia_id = 0; dev; dev = dev->next, ia_id++) -+ { -+ grub_efi_dhcp6_config_data_t config; -+ grub_efi_dhcp6_packet_option_t *option_list[1]; -+ grub_efi_dhcp6_packet_option_t *opt; -+ grub_efi_status_t status; -+ grub_efi_dhcp6_mode_data_t mode; -+ grub_efi_dhcp6_retransmission_t retrans; -+ grub_efi_net_ip_manual_address_t net_ip; -+ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; -+ grub_efi_net_interface_t *inf = NULL; -+ -+ if (argc > 0 && grub_strcmp (dev->card_name, args[0]) != 0) -+ continue; -+ -+ opt = grub_malloc (sizeof(*opt) + 2 * sizeof (grub_efi_uint16_t)); -+ -+#define GRUB_EFI_DHCP6_OPT_ORO 6 -+ -+ opt->op_code = grub_cpu_to_be16_compile_time (GRUB_EFI_DHCP6_OPT_ORO); -+ opt->op_len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_efi_uint16_t)); -+ -+#define GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL 59 -+#define GRUB_EFI_DHCP6_OPT_DNS_SERVERS 23 -+ -+ grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL)); -+ grub_set_unaligned16 (opt->data + 1 * sizeof (grub_efi_uint16_t), -+ grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS)); -+ -+ option_list[0] = opt; -+ retrans.irt = 4; -+ retrans.mrc = 4; -+ retrans.mrt = 32; -+ retrans.mrd = 60; -+ -+ config.dhcp6_callback = NULL; -+ config.callback_context = NULL; -+ config.option_count = 1; -+ config.option_list = option_list; -+ config.ia_descriptor.ia_id = ia_id; -+ config.ia_descriptor.type = GRUB_EFI_DHCP6_IA_TYPE_NA; -+ config.ia_info_event = NULL; -+ config.reconfigure_accept = 0; -+ config.rapid_commit = 0; -+ config.solicit_retransmission = &retrans; -+ -+ status = efi_call_2 (dev->dhcp6->configure, dev->dhcp6, &config); -+ grub_free (opt); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("dhcp6 configure failed, %d\n", (int)status); -+ continue; -+ } -+ status = efi_call_1 (dev->dhcp6->start, dev->dhcp6); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("dhcp6 start failed, %d\n", (int)status); -+ continue; -+ } -+ -+ status = efi_call_3 (dev->dhcp6->get_mode_data, dev->dhcp6, &mode, NULL); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("dhcp4 get mode failed, %d\n", (int)status); -+ continue; -+ } -+ -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ if (inf->prefer_ip6 == 1) -+ break; -+ -+ grub_memcpy (net_ip.ip6.address, mode.ia->ia_address[0].ip_address, sizeof (net_ip.ip6.address)); -+ net_ip.ip6.prefix_length = 64; -+ net_ip.ip6.is_anycast = 0; -+ net_ip.is_ip6 = 1; -+ -+ if (!inf) -+ { -+ char *name = grub_xasprintf ("%s:dhcp", dev->card_name); -+ -+ inf = grub_efi_net_create_interface (dev, -+ name, -+ &net_ip, -+ 1); -+ grub_free (name); -+ } -+ else -+ { -+ efi_net_interface_set_address (inf, &net_ip, 1); -+ } -+ -+ { -+ grub_efi_uint32_t count = 0; -+ grub_efi_dhcp6_packet_option_t **options = NULL; -+ grub_efi_uint32_t i; -+ -+ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, NULL); -+ -+ if (status == GRUB_EFI_BUFFER_TOO_SMALL && count) -+ { -+ options = grub_malloc (count * sizeof(*options)); -+ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options); -+ } -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ if (options) -+ grub_free (options); -+ continue; -+ } -+ -+ for (i = 0; i < count; ++i) -+ { -+ if (options[i]->op_code == grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS)) -+ { -+ grub_efi_net_ip_address_t dns; -+ grub_memcpy (dns.ip6, options[i]->data, sizeof(net_ip.ip6)); -+ efi_net_interface_set_dns (inf, &dns); -+ break; -+ } -+ } -+ -+ if (options) -+ grub_free (options); -+ } -+ -+ efi_call_1 (b->free_pool, mode.client_id); -+ efi_call_1 (b->free_pool, mode.ia); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+grub_command_func_t grub_efi_net_bootp = grub_cmd_efi_bootp; -+grub_command_func_t grub_efi_net_bootp6 = grub_cmd_efi_bootp6; -diff --git a/grub-core/net/efi/efi_netfs.c b/grub-core/net/efi/efi_netfs.c -new file mode 100644 -index 00000000000..ef371d885ea ---- /dev/null -+++ b/grub-core/net/efi/efi_netfs.c -@@ -0,0 +1,57 @@ -+#include -+#include -+#define EFI_NET_CMD_PREFIX "net_efi" -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static grub_command_t cmd_efi_lsroutes; -+static grub_command_t cmd_efi_lscards; -+static grub_command_t cmd_efi_lsaddrs; -+static grub_command_t cmd_efi_addaddr; -+static grub_command_t cmd_efi_bootp; -+static grub_command_t cmd_efi_bootp6; -+ -+static int initialized; -+ -+GRUB_MOD_INIT(efi_netfs) -+{ -+ if (grub_net_open) -+ return; -+ -+ if (grub_efi_net_fs_init ()) -+ { -+ cmd_efi_lsroutes = grub_register_command ("net_efi_ls_routes", grub_efi_net_list_routes, -+ "", N_("list network routes")); -+ cmd_efi_lscards = grub_register_command ("net_efi_ls_cards", grub_efi_net_list_cards, -+ "", N_("list network cards")); -+ cmd_efi_lsaddrs = grub_register_command ("net_efi_ls_addr", grub_efi_net_list_addrs, -+ "", N_("list network addresses")); -+ cmd_efi_addaddr = grub_register_command ("net_efi_add_addr", grub_efi_net_add_addr, -+ N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), -+ N_("Add a network address.")); -+ cmd_efi_bootp = grub_register_command ("net_efi_bootp", grub_efi_net_bootp, -+ N_("[CARD]"), -+ N_("perform a bootp autoconfiguration")); -+ cmd_efi_bootp6 = grub_register_command ("net_efi_bootp6", grub_efi_net_bootp6, -+ N_("[CARD]"), -+ N_("perform a bootp autoconfiguration")); -+ initialized = 1; -+ } -+} -+ -+GRUB_MOD_FINI(efi_netfs) -+{ -+ if (initialized) -+ { -+ grub_unregister_command (cmd_efi_lsroutes); -+ grub_unregister_command (cmd_efi_lscards); -+ grub_unregister_command (cmd_efi_lsaddrs); -+ grub_unregister_command (cmd_efi_addaddr); -+ grub_unregister_command (cmd_efi_bootp); -+ grub_unregister_command (cmd_efi_bootp6); -+ grub_efi_net_fs_fini (); -+ initialized = 0; -+ return; -+ } -+} -diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c -new file mode 100644 -index 00000000000..3f61fd2fa5b ---- /dev/null -+++ b/grub-core/net/efi/http.c -@@ -0,0 +1,419 @@ -+ -+#include -+#include -+#include -+#include -+#include -+ -+static void -+http_configure (struct grub_efi_net_device *dev, int prefer_ip6) -+{ -+ grub_efi_http_config_data_t http_config; -+ grub_efi_httpv4_access_point_t httpv4_node; -+ grub_efi_httpv6_access_point_t httpv6_node; -+ grub_efi_status_t status; -+ -+ grub_efi_http_t *http = dev->http; -+ -+ grub_memset (&http_config, 0, sizeof(http_config)); -+ http_config.http_version = GRUB_EFI_HTTPVERSION11; -+ http_config.timeout_millisec = 5000; -+ -+ if (prefer_ip6) -+ { -+ grub_efi_uintn_t sz; -+ grub_efi_ip6_config_manual_address_t manual_address; -+ -+ http_config.local_address_is_ipv6 = 1; -+ sz = sizeof (manual_address); -+ status = efi_call_4 (dev->ip6_config->get_data, dev->ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, -+ &sz, &manual_address); -+ -+ if (status == GRUB_EFI_NOT_FOUND) -+ { -+ grub_printf ("The MANUAL ADDRESS is not found\n"); -+ } -+ -+ /* FIXME: The manual interface would return BUFFER TOO SMALL !!! */ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_printf ("??? %d\n",(int) status); -+ return; -+ } -+ -+ grub_memcpy (httpv6_node.local_address, manual_address.address, sizeof (httpv6_node.local_address)); -+ httpv6_node.local_port = 0; -+ http_config.access_point.ipv6_node = &httpv6_node; -+ } -+ else -+ { -+ http_config.local_address_is_ipv6 = 0; -+ grub_memset (&httpv4_node, 0, sizeof(httpv4_node)); -+ httpv4_node.use_default_address = 1; -+ -+ /* Use random port here */ -+ /* See TcpBind() in edk2/NetworkPkg/TcpDxe/TcpDispatcher.c */ -+ httpv4_node.local_port = 0; -+ http_config.access_point.ipv4_node = &httpv4_node; -+ } -+ -+ status = efi_call_2 (http->configure, http, &http_config); -+ -+ if (status == GRUB_EFI_ALREADY_STARTED) -+ { -+ /* XXX: This hangs HTTPS boot */ -+#if 0 -+ if (efi_call_2 (http->configure, http, NULL) != GRUB_EFI_SUCCESS) -+ { -+ grub_error (GRUB_ERR_IO, N_("couldn't reset http instance")); -+ grub_print_error (); -+ return; -+ } -+ status = efi_call_2 (http->configure, http, &http_config); -+#endif -+ return; -+ } -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_error (GRUB_ERR_IO, N_("couldn't configure http protocol, reason: %d"), (int)status); -+ grub_print_error (); -+ return ; -+ } -+} -+ -+static grub_efi_boolean_t request_callback_done; -+static grub_efi_boolean_t response_callback_done; -+ -+static void -+grub_efi_http_request_callback (grub_efi_event_t event __attribute__ ((unused)), -+ void *context __attribute__ ((unused))) -+{ -+ request_callback_done = 1; -+} -+ -+static void -+grub_efi_http_response_callback (grub_efi_event_t event __attribute__ ((unused)), -+ void *context __attribute__ ((unused))) -+{ -+ response_callback_done = 1; -+} -+ -+static grub_err_t -+efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, int headeronly, grub_off_t *file_size) -+{ -+ grub_efi_http_request_data_t request_data; -+ grub_efi_http_message_t request_message; -+ grub_efi_http_token_t request_token; -+ grub_efi_http_response_data_t response_data; -+ grub_efi_http_message_t response_message; -+ grub_efi_http_token_t response_token; -+ grub_efi_http_header_t request_headers[3]; -+ -+ grub_efi_status_t status; -+ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; -+ char *url = NULL; -+ -+ request_headers[0].field_name = (grub_efi_char8_t *)"Host"; -+ request_headers[0].field_value = (grub_efi_char8_t *)server; -+ request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; -+ request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; -+ request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; -+ request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0"; -+ -+ { -+ grub_efi_ipv6_address_t address; -+ const char *rest; -+ grub_efi_char16_t *ucs2_url; -+ grub_size_t url_len, ucs2_url_len; -+ const char *protocol = (use_https == 1) ? "https" : "http"; -+ -+ if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0) -+ url = grub_xasprintf ("%s://[%s]%s", protocol, server, name); -+ else -+ url = grub_xasprintf ("%s://%s%s", protocol, server, name); -+ -+ if (!url) -+ { -+ return grub_errno; -+ } -+ -+ url_len = grub_strlen (url); -+ ucs2_url_len = url_len * GRUB_MAX_UTF16_PER_UTF8; -+ ucs2_url = grub_malloc ((ucs2_url_len + 1) * sizeof (ucs2_url[0])); -+ -+ if (!ucs2_url) -+ { -+ grub_free (url); -+ return grub_errno; -+ } -+ -+ ucs2_url_len = grub_utf8_to_utf16 (ucs2_url, ucs2_url_len, (grub_uint8_t *)url, url_len, NULL); /* convert string format from ascii to usc2 */ -+ ucs2_url[ucs2_url_len] = 0; -+ grub_free (url); -+ request_data.url = ucs2_url; -+ } -+ -+ request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET; -+ -+ request_message.data.request = &request_data; -+ request_message.header_count = 3; -+ request_message.headers = request_headers; -+ request_message.body_length = 0; -+ request_message.body = NULL; -+ -+ /* request token */ -+ request_token.event = NULL; -+ request_token.status = GRUB_EFI_NOT_READY; -+ request_token.message = &request_message; -+ -+ request_callback_done = 0; -+ status = efi_call_5 (b->create_event, -+ GRUB_EFI_EVT_NOTIFY_SIGNAL, -+ GRUB_EFI_TPL_CALLBACK, -+ grub_efi_http_request_callback, -+ NULL, -+ &request_token.event); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (request_data.url); -+ return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status); -+ } -+ -+ status = efi_call_2 (http->request, http, &request_token); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ efi_call_1 (b->close_event, request_token.event); -+ grub_free (request_data.url); -+ return grub_error (GRUB_ERR_IO, "Fail to send a request! status=0x%x\n", status); -+ } -+ /* TODO: Add Timeout */ -+ while (!request_callback_done) -+ efi_call_1(http->poll, http); -+ -+ response_data.status_code = GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS; -+ response_message.data.response = &response_data; -+ /* herader_count will be updated by the HTTP driver on response */ -+ response_message.header_count = 0; -+ /* headers will be populated by the driver on response */ -+ response_message.headers = NULL; -+ /* use zero BodyLength to only receive the response headers */ -+ response_message.body_length = 0; -+ response_message.body = NULL; -+ response_token.event = NULL; -+ -+ status = efi_call_5 (b->create_event, -+ GRUB_EFI_EVT_NOTIFY_SIGNAL, -+ GRUB_EFI_TPL_CALLBACK, -+ grub_efi_http_response_callback, -+ NULL, -+ &response_token.event); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ efi_call_1 (b->close_event, request_token.event); -+ grub_free (request_data.url); -+ return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status); -+ } -+ -+ response_token.status = GRUB_EFI_SUCCESS; -+ response_token.message = &response_message; -+ -+ /* wait for HTTP response */ -+ response_callback_done = 0; -+ status = efi_call_2 (http->response, http, &response_token); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ efi_call_1 (b->close_event, response_token.event); -+ efi_call_1 (b->close_event, request_token.event); -+ grub_free (request_data.url); -+ return grub_error (GRUB_ERR_IO, "Fail to receive a response! status=%d\n", (int)status); -+ } -+ -+ /* TODO: Add Timeout */ -+ while (!response_callback_done) -+ efi_call_1 (http->poll, http); -+ -+ if (response_message.data.response->status_code != GRUB_EFI_HTTP_STATUS_200_OK) -+ { -+ grub_efi_http_status_code_t status_code = response_message.data.response->status_code; -+ -+ if (response_message.headers) -+ efi_call_1 (b->free_pool, response_message.headers); -+ efi_call_1 (b->close_event, response_token.event); -+ efi_call_1 (b->close_event, request_token.event); -+ grub_free (request_data.url); -+ if (status_code == GRUB_EFI_HTTP_STATUS_404_NOT_FOUND) -+ { -+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, _("file `%s' not found"), name); -+ } -+ else -+ { -+ return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR, -+ _("unsupported uefi http status code 0x%x"), status_code); -+ } -+ } -+ -+ if (file_size) -+ { -+ int i; -+ /* parse the length of the file from the ContentLength header */ -+ for (*file_size = 0, i = 0; i < (int)response_message.header_count; ++i) -+ { -+ if (!grub_strcmp((const char*)response_message.headers[i].field_name, "Content-Length")) -+ { -+ *file_size = grub_strtoul((const char*)response_message.headers[i].field_value, 0, 10); -+ break; -+ } -+ } -+ } -+ -+ if (response_message.headers) -+ efi_call_1 (b->free_pool, response_message.headers); -+ efi_call_1 (b->close_event, response_token.event); -+ efi_call_1 (b->close_event, request_token.event); -+ grub_free (request_data.url); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_ssize_t -+efihttp_read (struct grub_efi_net_device *dev, -+ char *buf, -+ grub_size_t len) -+{ -+ grub_efi_http_message_t response_message; -+ grub_efi_http_token_t response_token; -+ -+ grub_efi_status_t status; -+ grub_size_t sum = 0; -+ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; -+ grub_efi_http_t *http = dev->http; -+ -+ if (!len) -+ { -+ grub_error (GRUB_ERR_BUG, "Invalid arguments to EFI HTTP Read"); -+ return -1; -+ } -+ -+ efi_call_5 (b->create_event, -+ GRUB_EFI_EVT_NOTIFY_SIGNAL, -+ GRUB_EFI_TPL_CALLBACK, -+ grub_efi_http_response_callback, -+ NULL, -+ &response_token.event); -+ -+ while (len) -+ { -+ response_message.data.response = NULL; -+ response_message.header_count = 0; -+ response_message.headers = NULL; -+ response_message.body_length = len; -+ response_message.body = buf; -+ -+ response_token.message = &response_message; -+ response_token.status = GRUB_EFI_NOT_READY; -+ -+ response_callback_done = 0; -+ -+ status = efi_call_2 (http->response, http, &response_token); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ efi_call_1 (b->close_event, response_token.event); -+ grub_error (GRUB_ERR_IO, "Error! status=%d\n", (int)status); -+ return -1; -+ } -+ -+ while (!response_callback_done) -+ efi_call_1(http->poll, http); -+ -+ sum += response_message.body_length; -+ buf += response_message.body_length; -+ len -= response_message.body_length; -+ } -+ -+ efi_call_1 (b->close_event, response_token.event); -+ -+ return sum; -+} -+ -+static grub_err_t -+grub_efihttp_open (struct grub_efi_net_device *dev, -+ int prefer_ip6 __attribute__ ((unused)), -+ grub_file_t file, -+ const char *filename __attribute__ ((unused)), -+ int type) -+{ -+ grub_err_t err; -+ grub_off_t size; -+ char *buf; -+ -+ err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ -+ err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ -+ buf = grub_malloc (size); -+ efihttp_read (dev, buf, size); -+ -+ file->size = size; -+ file->data = buf; -+ file->not_easily_seekable = 0; -+ file->device->net->offset = 0; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_efihttp_close (struct grub_efi_net_device *dev __attribute__ ((unused)), -+ int prefer_ip6 __attribute__ ((unused)), -+ grub_file_t file) -+{ -+ if (file->data) -+ grub_free (file->data); -+ -+ file->data = 0; -+ file->offset = 0; -+ file->size = 0; -+ file->device->net->offset = 0; -+ return GRUB_ERR_NONE; -+} -+ -+static grub_ssize_t -+grub_efihttp_read (struct grub_efi_net_device *dev __attribute__((unused)), -+ int prefer_ip6 __attribute__((unused)), -+ grub_file_t file, -+ char *buf, -+ grub_size_t len) -+{ -+ grub_size_t r = len; -+ -+ if (!file->data || !buf || !len) -+ return 0; -+ -+ if ((file->device->net->offset + len) > file->size) -+ r = file->size - file->device->net->offset; -+ -+ if (r) -+ { -+ grub_memcpy (buf, (char *)file->data + file->device->net->offset, r); -+ file->device->net->offset += r; -+ } -+ -+ return r; -+} -+ -+struct grub_efi_net_io io_http = -+ { -+ .configure = http_configure, -+ .open = grub_efihttp_open, -+ .read = grub_efihttp_read, -+ .close = grub_efihttp_close -+ }; -diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c -new file mode 100644 -index 00000000000..b711a5d9457 ---- /dev/null -+++ b/grub-core/net/efi/ip4_config.c -@@ -0,0 +1,398 @@ -+ -+#include -+#include -+#include -+#include -+#include -+ -+char * -+grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address) -+{ -+ char *hw_addr, *p; -+ int sz, s; -+ int i; -+ -+ sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1; -+ -+ hw_addr = grub_malloc (sz); -+ if (!hw_addr) -+ return NULL; -+ -+ p = hw_addr; -+ s = sz; -+ for (i = 0; i < (int)hw_address_size; i++) -+ { -+ grub_snprintf (p, sz, "%02x:", hw_address[i]); -+ p += sizeof ("XX:") - 1; -+ s -= sizeof ("XX:") - 1; -+ } -+ -+ hw_addr[sz - 2] = '\0'; -+ return hw_addr; -+} -+ -+char * -+grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address) -+{ -+ char *addr; -+ -+ addr = grub_malloc (sizeof ("XXX.XXX.XXX.XXX")); -+ if (!addr) -+ return NULL; -+ -+ /* FIXME: Use grub_xasprintf ? */ -+ grub_snprintf (addr, -+ sizeof ("XXX.XXX.XXX.XXX"), -+ "%u.%u.%u.%u", -+ (*address)[0], -+ (*address)[1], -+ (*address)[2], -+ (*address)[3]); -+ -+ return addr; -+} -+ -+int -+grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest) -+{ -+ grub_uint32_t newip = 0; -+ int i; -+ const char *ptr = val; -+ -+ for (i = 0; i < 4; i++) -+ { -+ unsigned long t; -+ t = grub_strtoul (ptr, (char **) &ptr, 0); -+ if (grub_errno) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ if (*ptr != '.' && i == 0) -+ { -+ /* XXX: t is in host byte order */ -+ newip = t; -+ break; -+ } -+ if (t & ~0xff) -+ return 0; -+ newip <<= 8; -+ newip |= t; -+ if (i != 3 && *ptr != '.') -+ return 0; -+ ptr++; -+ } -+ -+ newip = grub_cpu_to_be32 (newip); -+ -+ grub_memcpy (address, &newip, sizeof(*address)); -+ -+ if (rest) -+ *rest = (ptr - 1); -+ return 1; -+} -+ -+static grub_efi_ip4_config2_interface_info_t * -+efi_ip4_config_interface_info (grub_efi_ip4_config2_protocol_t *ip4_config) -+{ -+ grub_efi_uintn_t sz; -+ grub_efi_status_t status; -+ grub_efi_ip4_config2_interface_info_t *interface_info; -+ -+ sz = sizeof (*interface_info) + sizeof (*interface_info->route_table); -+ interface_info = grub_malloc (sz); -+ if (!interface_info) -+ return NULL; -+ -+ status = efi_call_4 (ip4_config->get_data, ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, -+ &sz, interface_info); -+ -+ if (status == GRUB_EFI_BUFFER_TOO_SMALL) -+ { -+ grub_free (interface_info); -+ interface_info = grub_malloc (sz); -+ status = efi_call_4 (ip4_config->get_data, ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, -+ &sz, interface_info); -+ } -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (interface_info); -+ return NULL; -+ } -+ -+ return interface_info; -+} -+ -+static grub_efi_ip4_config2_manual_address_t * -+efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config) -+{ -+ grub_efi_uintn_t sz; -+ grub_efi_status_t status; -+ grub_efi_ip4_config2_manual_address_t *manual_address; -+ -+ sz = sizeof (*manual_address); -+ manual_address = grub_malloc (sz); -+ if (!manual_address) -+ return NULL; -+ -+ status = efi_call_4 (ip4_config->get_data, ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, -+ &sz, manual_address); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (manual_address); -+ return NULL; -+ } -+ -+ return manual_address; -+} -+ -+char * -+grub_efi_ip4_interface_name (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip4_config2_interface_info_t *interface_info; -+ char *name; -+ -+ interface_info = efi_ip4_config_interface_info (dev->ip4_config); -+ -+ if (!interface_info) -+ return NULL; -+ -+ name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE -+ * GRUB_MAX_UTF8_PER_UTF16 + 1); -+ *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name, -+ GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0; -+ grub_free (interface_info); -+ return name; -+} -+ -+static char * -+grub_efi_ip4_interface_hw_address (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip4_config2_interface_info_t *interface_info; -+ char *hw_addr; -+ -+ interface_info = efi_ip4_config_interface_info (dev->ip4_config); -+ -+ if (!interface_info) -+ return NULL; -+ -+ hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address); -+ grub_free (interface_info); -+ -+ return hw_addr; -+} -+ -+static char * -+grub_efi_ip4_interface_address (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip4_config2_manual_address_t *manual_address; -+ char *addr; -+ -+ manual_address = efi_ip4_config_manual_address (dev->ip4_config); -+ -+ if (!manual_address) -+ return NULL; -+ -+ addr = grub_efi_ip4_address_to_string (&manual_address->address); -+ grub_free (manual_address); -+ return addr; -+} -+ -+ -+static int -+address_mask_size (grub_efi_ipv4_address_t *address) -+{ -+ grub_uint8_t i; -+ grub_uint32_t u32_addr = grub_be_to_cpu32 (grub_get_unaligned32 (address)); -+ -+ if (u32_addr == 0) -+ return 0; -+ -+ for (i = 0; i < 32 ; ++i) -+ { -+ if (u32_addr == ((0xffffffff >> i) << i)) -+ return (32 - i); -+ } -+ -+ return -1; -+} -+ -+static char ** -+grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip4_config2_interface_info_t *interface_info; -+ char **ret; -+ int i, id; -+ -+ interface_info = efi_ip4_config_interface_info (dev->ip4_config); -+ if (!interface_info) -+ return NULL; -+ -+ ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1)); -+ -+ if (!ret) -+ { -+ grub_free (interface_info); -+ return NULL; -+ } -+ -+ id = 0; -+ for (i = 0; i < (int)interface_info->route_table_size; i++) -+ { -+ char *subnet, *gateway, *mask; -+ grub_uint32_t u32_subnet, u32_gateway; -+ int mask_size; -+ grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i; -+ grub_efi_net_interface_t *inf; -+ char *interface_name = NULL; -+ -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ if (!inf->prefer_ip6) -+ interface_name = inf->name; -+ -+ u32_gateway = grub_get_unaligned32 (&route_table->gateway_address); -+ gateway = grub_efi_ip4_address_to_string (&route_table->gateway_address); -+ u32_subnet = grub_get_unaligned32 (&route_table->subnet_address); -+ subnet = grub_efi_ip4_address_to_string (&route_table->subnet_address); -+ mask_size = address_mask_size (&route_table->subnet_mask); -+ mask = grub_efi_ip4_address_to_string (&route_table->subnet_mask); -+ if (u32_subnet && !u32_gateway && interface_name) -+ ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, subnet, mask_size, interface_name); -+ else if (u32_subnet && u32_gateway) -+ ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, subnet, mask_size, gateway); -+ else if (!u32_subnet && u32_gateway) -+ ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, subnet, mask_size, gateway); -+ grub_free (subnet); -+ grub_free (gateway); -+ grub_free (mask); -+ } -+ -+ ret[id] = NULL; -+ grub_free (interface_info); -+ return ret; -+} -+ -+static grub_efi_net_interface_t * -+grub_efi_ip4_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address) -+{ -+ grub_efi_ip4_config2_interface_info_t *interface_info; -+ grub_efi_net_interface_t *inf; -+ int i; -+ grub_efi_ipv4_address_t *address = &ip_address->ip4; -+ -+ interface_info = efi_ip4_config_interface_info (dev->ip4_config); -+ if (!interface_info) -+ return NULL; -+ -+ for (i = 0; i < (int)interface_info->route_table_size; i++) -+ { -+ grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i; -+ grub_uint32_t u32_address, u32_mask, u32_subnet; -+ -+ u32_address = grub_get_unaligned32 (address); -+ u32_subnet = grub_get_unaligned32 (route_table->subnet_address); -+ u32_mask = grub_get_unaligned32 (route_table->subnet_mask); -+ -+ /* SKIP Default GATEWAY */ -+ if (!u32_subnet && !u32_mask) -+ continue; -+ -+ if ((u32_address & u32_mask) == u32_subnet) -+ { -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ if (!inf->prefer_ip6) -+ { -+ grub_free (interface_info); -+ return inf; -+ } -+ } -+ } -+ -+ grub_free (interface_info); -+ return NULL; -+} -+ -+static int -+grub_efi_ip4_interface_set_manual_address (struct grub_efi_net_device *dev, -+ grub_efi_net_ip_manual_address_t *net_ip, -+ int with_subnet) -+{ -+ grub_efi_status_t status; -+ grub_efi_ip4_config2_manual_address_t *address = &net_ip->ip4; -+ -+ if (!with_subnet) -+ { -+ grub_efi_ip4_config2_manual_address_t *manual_address = -+ efi_ip4_config_manual_address (dev->ip4_config); -+ -+ if (manual_address) -+ { -+ grub_memcpy (address->subnet_mask, manual_address->subnet_mask, sizeof(address->subnet_mask)); -+ grub_free (manual_address); -+ } -+ else -+ { -+ /* XXX: */ -+ address->subnet_mask[0] = 0xff; -+ address->subnet_mask[1] = 0xff; -+ address->subnet_mask[2] = 0xff; -+ address->subnet_mask[3] = 0; -+ } -+ } -+ -+ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, -+ sizeof(*address), address); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ -+ return 1; -+} -+ -+static int -+grub_efi_ip4_interface_set_gateway (struct grub_efi_net_device *dev, -+ grub_efi_net_ip_address_t *address) -+{ -+ grub_efi_status_t status; -+ -+ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY, -+ sizeof (address->ip4), &address->ip4); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ return 1; -+} -+ -+/* FIXME: Multiple DNS */ -+static int -+grub_efi_ip4_interface_set_dns (struct grub_efi_net_device *dev, -+ grub_efi_net_ip_address_t *address) -+{ -+ grub_efi_status_t status; -+ -+ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, -+ sizeof (address->ip4), &address->ip4); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ return 1; -+} -+ -+grub_efi_net_ip_config_t *efi_net_ip4_config = &(grub_efi_net_ip_config_t) -+ { -+ .get_hw_address = grub_efi_ip4_interface_hw_address, -+ .get_address = grub_efi_ip4_interface_address, -+ .get_route_table = grub_efi_ip4_interface_route_table, -+ .best_interface = grub_efi_ip4_interface_match, -+ .set_address = grub_efi_ip4_interface_set_manual_address, -+ .set_gateway = grub_efi_ip4_interface_set_gateway, -+ .set_dns = grub_efi_ip4_interface_set_dns -+ }; -diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c -new file mode 100644 -index 00000000000..017c4d05bc7 ---- /dev/null -+++ b/grub-core/net/efi/ip6_config.c -@@ -0,0 +1,422 @@ -+#include -+#include -+#include -+#include -+#include -+ -+char * -+grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address) -+{ -+ char *str = grub_malloc (sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX")); -+ char *p; -+ int i; -+ int squash; -+ -+ if (!str) -+ return NULL; -+ -+ p = str; -+ squash = 0; -+ for (i = 0; i < 8; ++i) -+ { -+ grub_uint16_t addr; -+ -+ if (i == 7) -+ squash = 2; -+ -+ addr = grub_get_unaligned16 (address->addr + i * 2); -+ -+ if (grub_be_to_cpu16 (addr)) -+ { -+ char buf[sizeof ("XXXX")]; -+ if (i > 0) -+ *p++ = ':'; -+ grub_snprintf (buf, sizeof (buf), "%x", grub_be_to_cpu16 (addr)); -+ grub_strcpy (p, buf); -+ p += grub_strlen (buf); -+ -+ if (squash == 1) -+ squash = 2; -+ } -+ else -+ { -+ if (squash == 0) -+ { -+ *p++ = ':'; -+ squash = 1; -+ } -+ else if (squash == 2) -+ { -+ *p++ = ':'; -+ *p++ = '0'; -+ } -+ } -+ } -+ *p = '\0'; -+ return str; -+} -+ -+int -+grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest) -+{ -+ grub_uint16_t newip[8]; -+ const char *ptr = val; -+ int word, quaddot = -1; -+ int bracketed = 0; -+ -+ if (ptr[0] == '[') { -+ bracketed = 1; -+ ptr++; -+ } -+ -+ if (ptr[0] == ':' && ptr[1] != ':') -+ return 0; -+ if (ptr[0] == ':') -+ ptr++; -+ -+ for (word = 0; word < 8; word++) -+ { -+ unsigned long t; -+ if (*ptr == ':') -+ { -+ quaddot = word; -+ word--; -+ ptr++; -+ continue; -+ } -+ t = grub_strtoul (ptr, (char **) &ptr, 16); -+ if (grub_errno) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ break; -+ } -+ if (t & ~0xffff) -+ return 0; -+ newip[word] = grub_cpu_to_be16 (t); -+ if (*ptr != ':') -+ break; -+ ptr++; -+ } -+ if (quaddot == -1 && word < 7) -+ return 0; -+ if (quaddot != -1) -+ { -+ grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], -+ (word - quaddot + 1) * sizeof (newip[0])); -+ grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); -+ } -+ grub_memcpy (address, newip, 16); -+ if (bracketed && *ptr == ']') { -+ ptr++; -+ } -+ if (rest) -+ *rest = ptr; -+ return 1; -+} -+ -+static grub_efi_ip6_config_interface_info_t * -+efi_ip6_config_interface_info (grub_efi_ip6_config_protocol_t *ip6_config) -+{ -+ grub_efi_uintn_t sz; -+ grub_efi_status_t status; -+ grub_efi_ip6_config_interface_info_t *interface_info; -+ -+ sz = sizeof (*interface_info) + sizeof (*interface_info->route_table); -+ interface_info = grub_malloc (sz); -+ -+ status = efi_call_4 (ip6_config->get_data, ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, -+ &sz, interface_info); -+ -+ if (status == GRUB_EFI_BUFFER_TOO_SMALL) -+ { -+ grub_free (interface_info); -+ interface_info = grub_malloc (sz); -+ status = efi_call_4 (ip6_config->get_data, ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, -+ &sz, interface_info); -+ } -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (interface_info); -+ return NULL; -+ } -+ -+ return interface_info; -+} -+ -+static grub_efi_ip6_config_manual_address_t * -+efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config) -+{ -+ grub_efi_uintn_t sz; -+ grub_efi_status_t status; -+ grub_efi_ip6_config_manual_address_t *manual_address; -+ -+ sz = sizeof (*manual_address); -+ manual_address = grub_malloc (sz); -+ if (!manual_address) -+ return NULL; -+ -+ status = efi_call_4 (ip6_config->get_data, ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, -+ &sz, manual_address); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (manual_address); -+ return NULL; -+ } -+ -+ return manual_address; -+} -+ -+char * -+grub_efi_ip6_interface_name (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip6_config_interface_info_t *interface_info; -+ char *name; -+ -+ interface_info = efi_ip6_config_interface_info (dev->ip6_config); -+ -+ if (!interface_info) -+ return NULL; -+ -+ name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE -+ * GRUB_MAX_UTF8_PER_UTF16 + 1); -+ *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name, -+ GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0; -+ grub_free (interface_info); -+ return name; -+} -+ -+static char * -+grub_efi_ip6_interface_hw_address (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip6_config_interface_info_t *interface_info; -+ char *hw_addr; -+ -+ interface_info = efi_ip6_config_interface_info (dev->ip6_config); -+ -+ if (!interface_info) -+ return NULL; -+ -+ hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address); -+ grub_free (interface_info); -+ -+ return hw_addr; -+} -+ -+static char * -+grub_efi_ip6_interface_address (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip6_config_manual_address_t *manual_address; -+ char *addr; -+ -+ manual_address = efi_ip6_config_manual_address (dev->ip6_config); -+ -+ if (!manual_address) -+ return NULL; -+ -+ addr = grub_efi_ip6_address_to_string ((grub_efi_pxe_ipv6_address_t *)&manual_address->address); -+ grub_free (manual_address); -+ return addr; -+} -+ -+static char ** -+grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev) -+{ -+ grub_efi_ip6_config_interface_info_t *interface_info; -+ char **ret; -+ int i, id; -+ -+ interface_info = efi_ip6_config_interface_info (dev->ip6_config); -+ if (!interface_info) -+ return NULL; -+ -+ ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1)); -+ -+ if (!ret) -+ { -+ grub_free (interface_info); -+ return NULL; -+ } -+ -+ id = 0; -+ for (i = 0; i < (int)interface_info->route_count ; i++) -+ { -+ char *gateway, *destination; -+ grub_uint64_t u64_gateway[2]; -+ grub_uint64_t u64_destination[2]; -+ grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i; -+ grub_efi_net_interface_t *inf; -+ char *interface_name = NULL; -+ -+ gateway = grub_efi_ip6_address_to_string (&route_table->gateway); -+ destination = grub_efi_ip6_address_to_string (&route_table->destination); -+ -+ u64_gateway[0] = grub_get_unaligned64 (route_table->gateway.addr); -+ u64_gateway[1] = grub_get_unaligned64 (route_table->gateway.addr + 8); -+ u64_destination[0] = grub_get_unaligned64 (route_table->destination.addr); -+ u64_destination[1] = grub_get_unaligned64 (route_table->destination.addr + 8); -+ -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ if (inf->prefer_ip6) -+ interface_name = inf->name; -+ -+ if ((!u64_gateway[0] && !u64_gateway[1]) -+ && (u64_destination[0] || u64_destination[1])) -+ { -+ if (interface_name) -+ { -+ if ((grub_be_to_cpu64 (u64_destination[0]) == 0xfe80000000000000ULL) -+ && (!u64_destination[1]) -+ && (route_table->prefix_length == 64)) -+ ret[id++] = grub_xasprintf ("%s:link %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name); -+ else -+ ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name); -+ } -+ } -+ else if ((u64_gateway[0] || u64_gateway[1]) -+ && (u64_destination[0] || u64_destination[1])) -+ ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway); -+ else if ((u64_gateway[0] || u64_gateway[1]) -+ && (!u64_destination[0] && !u64_destination[1])) -+ ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway); -+ -+ grub_free (gateway); -+ grub_free (destination); -+ } -+ -+ ret[id] = NULL; -+ grub_free (interface_info); -+ return ret; -+} -+ -+static grub_efi_net_interface_t * -+grub_efi_ip6_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address) -+{ -+ grub_efi_ip6_config_interface_info_t *interface_info; -+ grub_efi_net_interface_t *inf; -+ int i; -+ grub_efi_ipv6_address_t *address = &ip_address->ip6; -+ -+ interface_info = efi_ip6_config_interface_info (dev->ip6_config); -+ if (!interface_info) -+ return NULL; -+ -+ for (i = 0; i < (int)interface_info->route_count ; i++) -+ { -+ grub_uint64_t u64_addr[2]; -+ grub_uint64_t u64_subnet[2]; -+ grub_uint64_t u64_mask[2]; -+ -+ grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i; -+ -+ /* SKIP Default GATEWAY */ -+ if (route_table->prefix_length == 0) -+ continue; -+ -+ u64_addr[0] = grub_get_unaligned64 (address); -+ u64_addr[1] = grub_get_unaligned64 (address + 4); -+ u64_subnet[0] = grub_get_unaligned64 (route_table->destination.addr); -+ u64_subnet[1] = grub_get_unaligned64 (route_table->destination.addr + 8); -+ u64_mask[0] = (route_table->prefix_length <= 64) ? -+ 0xffffffffffffffffULL << (64 - route_table->prefix_length) : -+ 0xffffffffffffffffULL; -+ u64_mask[1] = (route_table->prefix_length <= 64) ? -+ 0 : -+ 0xffffffffffffffffULL << (128 - route_table->prefix_length); -+ -+ if (((u64_addr[0] & u64_mask[0]) == u64_subnet[0]) -+ && ((u64_addr[1] & u64_mask[1]) == u64_subnet[1])) -+ { -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ if (inf->prefer_ip6) -+ { -+ grub_free (interface_info); -+ return inf; -+ } -+ } -+ } -+ -+ grub_free (interface_info); -+ return NULL; -+} -+ -+static int -+grub_efi_ip6_interface_set_manual_address (struct grub_efi_net_device *dev, -+ grub_efi_net_ip_manual_address_t *net_ip, -+ int with_subnet) -+{ -+ grub_efi_status_t status; -+ grub_efi_ip6_config_manual_address_t *address = &net_ip->ip6; -+ -+ if (!with_subnet) -+ { -+ grub_efi_ip6_config_manual_address_t *manual_address = -+ efi_ip6_config_manual_address (dev->ip6_config); -+ -+ if (manual_address) -+ { -+ address->prefix_length = manual_address->prefix_length; -+ grub_free (manual_address); -+ } -+ else -+ { -+ /* XXX: */ -+ address->prefix_length = 64; -+ } -+ } -+ -+ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, -+ sizeof(*address), address); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ -+ return 1; -+} -+ -+static int -+grub_efi_ip6_interface_set_gateway (struct grub_efi_net_device *dev, -+ grub_efi_net_ip_address_t *address) -+{ -+ grub_efi_status_t status; -+ -+ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY, -+ sizeof (address->ip6), &address->ip6); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ return 1; -+} -+ -+static int -+grub_efi_ip6_interface_set_dns (struct grub_efi_net_device *dev, -+ grub_efi_net_ip_address_t *address) -+{ -+ -+ grub_efi_status_t status; -+ -+ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, -+ sizeof (address->ip6), &address->ip6); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ return 1; -+} -+ -+grub_efi_net_ip_config_t *efi_net_ip6_config = &(grub_efi_net_ip_config_t) -+ { -+ .get_hw_address = grub_efi_ip6_interface_hw_address, -+ .get_address = grub_efi_ip6_interface_address, -+ .get_route_table = grub_efi_ip6_interface_route_table, -+ .best_interface = grub_efi_ip6_interface_match, -+ .set_address = grub_efi_ip6_interface_set_manual_address, -+ .set_gateway = grub_efi_ip6_interface_set_gateway, -+ .set_dns = grub_efi_ip6_interface_set_dns -+ }; -diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c -new file mode 100644 -index 00000000000..86bce6535d3 ---- /dev/null -+++ b/grub-core/net/efi/net.c -@@ -0,0 +1,1428 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+#define GRUB_EFI_IP6_PREFIX_LENGTH 64 -+ -+static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID; -+static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID; -+static grub_efi_guid_t http_service_binding_guid = GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID; -+static grub_efi_guid_t http_guid = GRUB_EFI_HTTP_PROTOCOL_GUID; -+static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; -+static grub_efi_guid_t dhcp4_service_binding_guid = GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID; -+static grub_efi_guid_t dhcp4_guid = GRUB_EFI_DHCP4_PROTOCOL_GUID; -+static grub_efi_guid_t dhcp6_service_binding_guid = GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID; -+static grub_efi_guid_t dhcp6_guid = GRUB_EFI_DHCP6_PROTOCOL_GUID; -+ -+struct grub_efi_net_device *net_devices; -+ -+static char *default_server; -+static grub_efi_net_interface_t *net_interface; -+static grub_efi_net_interface_t *net_default_interface; -+ -+#define efi_net_interface_configure(inf) inf->io->configure (inf->dev, inf->prefer_ip6) -+#define efi_net_interface_open(inf, file, name) inf->io->open (inf->dev, inf->prefer_ip6, file, name, inf->io_type) -+#define efi_net_interface_read(inf, file, buf, sz) inf->io->read (inf->dev, inf->prefer_ip6, file, buf, sz) -+#define efi_net_interface_close(inf, file) inf->io->close (inf->dev, inf->prefer_ip6, file) -+#define efi_net_interface(m,...) efi_net_interface_ ## m (net_interface, ## __VA_ARGS__) -+ -+static grub_efi_handle_t -+grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path, -+ grub_efi_device_path_t **r_device_path) -+{ -+ grub_efi_handle_t handle; -+ grub_efi_status_t status; -+ -+ status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path, -+ protocol, &device_path, &handle); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return 0; -+ -+ if (r_device_path) -+ *r_device_path = device_path; -+ -+ return handle; -+} -+ -+static int -+url_parse_fields (const char *url, char **proto, char **host, char **path) -+{ -+ const char *p, *ps; -+ grub_size_t l; -+ -+ *proto = *host = *path = NULL; -+ ps = p = url; -+ -+ while ((p = grub_strchr (p, ':'))) -+ { -+ if (grub_strlen (p) < sizeof ("://") - 1) -+ break; -+ if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0) -+ { -+ l = p - ps; -+ *proto = grub_malloc (l + 1); -+ if (!*proto) -+ { -+ grub_print_error (); -+ return 0; -+ } -+ -+ grub_memcpy (*proto, ps, l); -+ (*proto)[l] = '\0'; -+ p += sizeof ("://") - 1; -+ break; -+ } -+ ++p; -+ } -+ -+ if (!*proto) -+ { -+ grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url); -+ return 0; -+ } -+ -+ ps = p; -+ p = grub_strchr (p, '/'); -+ -+ if (!p) -+ { -+ grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url); -+ grub_free (*proto); -+ *proto = NULL; -+ return 0; -+ } -+ -+ l = p - ps; -+ -+ if (l > 2 && ps[0] == '[' && ps[l - 1] == ']') -+ { -+ *host = grub_malloc (l - 1); -+ if (!*host) -+ { -+ grub_print_error (); -+ grub_free (*proto); -+ *proto = NULL; -+ return 0; -+ } -+ grub_memcpy (*host, ps + 1, l - 2); -+ (*host)[l - 2] = 0; -+ } -+ else -+ { -+ *host = grub_malloc (l + 1); -+ if (!*host) -+ { -+ grub_print_error (); -+ grub_free (*proto); -+ *proto = NULL; -+ return 0; -+ } -+ grub_memcpy (*host, ps, l); -+ (*host)[l] = 0; -+ } -+ -+ *path = grub_strdup (p); -+ if (!*path) -+ { -+ grub_print_error (); -+ grub_free (*host); -+ grub_free (*proto); -+ *host = NULL; -+ *proto = NULL; -+ return 0; -+ } -+ return 1; -+} -+ -+static void -+url_get_boot_location (const char *url, char **device, char **path, int is_default) -+{ -+ char *protocol, *server, *file; -+ char *slash; -+ -+ if (!url_parse_fields (url, &protocol, &server, &file)) -+ return; -+ -+ if ((slash = grub_strrchr (file, '/'))) -+ *slash = 0; -+ else -+ *file = 0; -+ -+ *device = grub_xasprintf ("%s,%s", protocol, server); -+ *path = grub_strdup(file); -+ -+ if (is_default) -+ default_server = server; -+ else -+ grub_free (server); -+ -+ grub_free (protocol); -+ grub_free (file); -+} -+ -+static void -+pxe_get_boot_location (const struct grub_net_bootp_packet *bp, -+ char **device, -+ char **path, -+ int is_default) -+{ -+ char *server = grub_xasprintf ("%d.%d.%d.%d", -+ ((grub_uint8_t *) &bp->server_ip)[0], -+ ((grub_uint8_t *) &bp->server_ip)[1], -+ ((grub_uint8_t *) &bp->server_ip)[2], -+ ((grub_uint8_t *) &bp->server_ip)[3]); -+ -+ *device = grub_xasprintf ("tftp,%s", server); -+ -+ *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); -+ -+ if (*path) -+ { -+ char *slash; -+ slash = grub_strrchr (*path, '/'); -+ if (slash) -+ *slash = 0; -+ else -+ **path = 0; -+ } -+ -+ if (is_default) -+ default_server = server; -+ else -+ grub_free (server); -+} -+ -+static void -+pxe_get_boot_location_v6 (const struct grub_net_dhcp6_packet *dp, -+ grub_size_t dhcp_size, -+ char **device, -+ char **path) -+{ -+ -+ struct grub_net_dhcp6_option *dhcp_opt; -+ grub_size_t dhcp_remain_size; -+ *device = *path = 0; -+ -+ if (dhcp_size < sizeof (*dp)) -+ { -+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small")); -+ return; -+ } -+ -+ dhcp_remain_size = dhcp_size - sizeof (*dp); -+ dhcp_opt = (struct grub_net_dhcp6_option *)dp->dhcp_options; -+ -+ while (dhcp_remain_size) -+ { -+ grub_uint16_t code = grub_be_to_cpu16 (dhcp_opt->code); -+ grub_uint16_t len = grub_be_to_cpu16 (dhcp_opt->len); -+ grub_uint16_t option_size = sizeof (*dhcp_opt) + len; -+ -+ if (dhcp_remain_size < option_size || code == 0) -+ break; -+ -+ if (code == GRUB_NET_DHCP6_OPTION_BOOTFILE_URL) -+ { -+ char *url = grub_malloc (len + 1); -+ -+ grub_memcpy (url, dhcp_opt->data, len); -+ url[len] = 0; -+ -+ url_get_boot_location ((const char *)url, device, path, 1); -+ grub_free (url); -+ break; -+ } -+ -+ dhcp_remain_size -= option_size; -+ dhcp_opt = (struct grub_net_dhcp6_option *)((grub_uint8_t *)dhcp_opt + option_size); -+ } -+} -+ -+static grub_efi_net_interface_t * -+grub_efi_net_config_from_device_path (grub_efi_device_path_t *dp, -+ struct grub_efi_net_device *netdev, -+ char **device, -+ char **path) -+{ -+ grub_efi_net_interface_t *inf = NULL; -+ -+ while (1) -+ { -+ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); -+ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); -+ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); -+ -+ if (type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) -+ { -+ if (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) -+ { -+ grub_efi_uri_device_path_t *uri_dp; -+ uri_dp = (grub_efi_uri_device_path_t *) dp; -+ /* Beware that uri_dp->uri may not be null terminated */ -+ url_get_boot_location ((const char *)uri_dp->uri, device, path, 1); -+ } -+ else if (subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) -+ { -+ grub_efi_net_ip_manual_address_t net_ip; -+ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) dp; -+ -+ if (inf) -+ continue; -+ grub_memcpy (net_ip.ip4.address, ipv4->local_ip_address, sizeof (net_ip.ip4.address)); -+ grub_memcpy (net_ip.ip4.subnet_mask, ipv4->subnet_mask, sizeof (net_ip.ip4.subnet_mask)); -+ net_ip.is_ip6 = 0; -+ inf = grub_efi_net_create_interface (netdev, -+ netdev->card_name, -+ &net_ip, -+ 1); -+ } -+ else if (subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) -+ { -+ grub_efi_net_ip_manual_address_t net_ip; -+ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) dp; -+ -+ if (inf) -+ continue; -+ grub_memcpy (net_ip.ip6.address, ipv6->local_ip_address, sizeof (net_ip.ip6.address)); -+ net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH; -+ net_ip.ip6.is_anycast = 0; -+ net_ip.is_ip6 = 1; -+ inf = grub_efi_net_create_interface (netdev, -+ netdev->card_name, -+ &net_ip, -+ 1); -+ } -+ } -+ -+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) -+ break; -+ dp = (grub_efi_device_path_t *) ((char *) dp + len); -+ } -+ -+ return inf; -+} -+ -+static grub_efi_net_interface_t * -+grub_efi_net_config_from_handle (grub_efi_handle_t *hnd, -+ struct grub_efi_net_device *netdev, -+ char **device, -+ char **path) -+{ -+ grub_efi_pxe_t *pxe = NULL; -+ -+ if (hnd == netdev->ip4_pxe_handle) -+ pxe = netdev->ip4_pxe; -+ else if (hnd == netdev->ip6_pxe_handle) -+ pxe = netdev->ip6_pxe; -+ -+ if (!pxe) -+ return (grub_efi_net_config_from_device_path ( -+ grub_efi_get_device_path (hnd), -+ netdev, -+ device, -+ path)); -+ -+ if (pxe->mode->using_ipv6) -+ { -+ grub_efi_net_ip_manual_address_t net_ip; -+ -+ pxe_get_boot_location_v6 ( -+ (const struct grub_net_dhcp6_packet *) &pxe->mode->dhcp_ack, -+ sizeof (pxe->mode->dhcp_ack), -+ device, -+ path); -+ -+ grub_memcpy (net_ip.ip6.address, pxe->mode->station_ip.v6, sizeof(net_ip.ip6.address)); -+ net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH; -+ net_ip.ip6.is_anycast = 0; -+ net_ip.is_ip6 = 1; -+ return (grub_efi_net_create_interface (netdev, -+ netdev->card_name, -+ &net_ip, -+ 1)); -+ } -+ else -+ { -+ grub_efi_net_ip_manual_address_t net_ip; -+ -+ pxe_get_boot_location ( -+ (const struct grub_net_bootp_packet *) &pxe->mode->dhcp_ack, -+ device, -+ path, -+ 1); -+ -+ grub_memcpy (net_ip.ip4.address, pxe->mode->station_ip.v4, sizeof (net_ip.ip4.address)); -+ grub_memcpy (net_ip.ip4.subnet_mask, pxe->mode->subnet_mask.v4, sizeof (net_ip.ip4.subnet_mask)); -+ net_ip.is_ip6 = 0; -+ return (grub_efi_net_create_interface (netdev, -+ netdev->card_name, -+ &net_ip, -+ 1)); -+ } -+} -+ -+static const char * -+grub_efi_net_var_get_address (struct grub_env_var *var, -+ const char *val __attribute__ ((unused))) -+{ -+ struct grub_efi_net_device *dev; -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ { -+ grub_efi_net_interface_t *inf; -+ -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ { -+ char *var_name; -+ -+ var_name = grub_xasprintf ("net_%s_ip", inf->name); -+ if (grub_strcmp (var_name, var->name) == 0) -+ return efi_net_interface_get_address (inf); -+ grub_free (var_name); -+ var_name = grub_xasprintf ("net_%s_mac", inf->name); -+ if (grub_strcmp (var_name, var->name) == 0) -+ return efi_net_interface_get_hw_address (inf); -+ grub_free (var_name); -+ } -+ } -+ -+ return NULL; -+} -+ -+static char * -+grub_efi_net_var_set_interface (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val) -+{ -+ struct grub_efi_net_device *dev; -+ grub_efi_net_interface_t *inf; -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ if (grub_strcmp (inf->name, val) == 0) -+ { -+ net_default_interface = inf; -+ return grub_strdup (val); -+ } -+ -+ return NULL; -+} -+ -+static char * -+grub_efi_net_var_set_server (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val) -+{ -+ grub_free (default_server); -+ default_server = grub_strdup (val); -+ return grub_strdup (val); -+} -+ -+static const char * -+grub_efi_net_var_get_server (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val __attribute__ ((unused))) -+{ -+ return default_server ? : ""; -+} -+ -+static const char * -+grub_efi_net_var_get_ip (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val __attribute__ ((unused))) -+{ -+ const char *intf = grub_env_get ("net_default_interface"); -+ const char *ret = NULL; -+ if (intf) -+ { -+ char *buf = grub_xasprintf ("net_%s_ip", intf); -+ if (buf) -+ ret = grub_env_get (buf); -+ grub_free (buf); -+ } -+ return ret; -+} -+ -+static const char * -+grub_efi_net_var_get_mac (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val __attribute__ ((unused))) -+{ -+ const char *intf = grub_env_get ("net_default_interface"); -+ const char *ret = NULL; -+ if (intf) -+ { -+ char *buf = grub_xasprintf ("net_%s_mac", intf); -+ if (buf) -+ ret = grub_env_get (buf); -+ grub_free (buf); -+ } -+ return ret; -+} -+ -+static void -+grub_efi_net_export_interface_vars (void) -+{ -+ struct grub_efi_net_device *dev; -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ { -+ grub_efi_net_interface_t *inf; -+ -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ { -+ char *var; -+ -+ var = grub_xasprintf ("net_%s_ip", inf->name); -+ grub_register_variable_hook (var, grub_efi_net_var_get_address, 0); -+ grub_env_export (var); -+ grub_free (var); -+ var = grub_xasprintf ("net_%s_mac", inf->name); -+ grub_register_variable_hook (var, grub_efi_net_var_get_address, 0); -+ grub_env_export (var); -+ grub_free (var); -+ } -+ } -+} -+ -+static void -+grub_efi_net_unset_interface_vars (void) -+{ -+ struct grub_efi_net_device *dev; -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ { -+ grub_efi_net_interface_t *inf; -+ -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ { -+ char *var; -+ -+ var = grub_xasprintf ("net_%s_ip", inf->name); -+ grub_register_variable_hook (var, 0, 0); -+ grub_env_unset (var); -+ grub_free (var); -+ var = grub_xasprintf ("net_%s_mac", inf->name); -+ grub_register_variable_hook (var, 0, 0); -+ grub_env_unset (var); -+ grub_free (var); -+ } -+ } -+} -+ -+grub_efi_net_interface_t * -+grub_efi_net_create_interface (struct grub_efi_net_device *dev, -+ const char *interface_name, -+ grub_efi_net_ip_manual_address_t *net_ip, -+ int has_subnet) -+{ -+ grub_efi_net_interface_t *inf; -+ -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ { -+ if (inf->prefer_ip6 == net_ip->is_ip6) -+ break; -+ } -+ -+ if (!inf) -+ { -+ inf = grub_malloc (sizeof(*inf)); -+ inf->name = grub_strdup (interface_name); -+ inf->prefer_ip6 = net_ip->is_ip6; -+ inf->dev = dev; -+ inf->next = dev->net_interfaces; -+ inf->ip_config = (net_ip->is_ip6) ? efi_net_ip6_config : efi_net_ip4_config ; -+ dev->net_interfaces = inf; -+ } -+ else -+ { -+ grub_free (inf->name); -+ inf->name = grub_strdup (interface_name); -+ } -+ -+ if (!efi_net_interface_set_address (inf, net_ip, has_subnet)) -+ { -+ grub_error (GRUB_ERR_BUG, N_("Set Address Failed")); -+ return NULL; -+ } -+ -+ return inf; -+} -+ -+static void -+grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, -+ char **path) -+{ -+ grub_efi_handle_t config_hnd; -+ -+ struct grub_efi_net_device *netdev; -+ grub_efi_net_interface_t *inf; -+ -+ config_hnd = grub_efi_locate_device_path (&ip4_config_guid, grub_efi_get_device_path (hnd), NULL); -+ -+ if (!config_hnd) -+ return; -+ -+ for (netdev = net_devices; netdev; netdev = netdev->next) -+ if (netdev->handle == config_hnd) -+ break; -+ -+ if (!netdev) -+ return; -+ -+ if (!(inf = grub_efi_net_config_from_handle (hnd, netdev, device, path))) -+ return; -+ -+ grub_env_set ("net_default_interface", inf->name); -+ grub_efi_net_export_interface_vars (); -+} -+ -+static grub_err_t -+grub_efi_netfs_dir (grub_device_t device, const char *path __attribute__ ((unused)), -+ grub_fs_dir_hook_t hook __attribute__ ((unused)), -+ void *hook_data __attribute__ ((unused))) -+{ -+ if (!device->net) -+ return grub_error (GRUB_ERR_BUG, "invalid net device"); -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_efi_netfs_open (struct grub_file *file_out __attribute__ ((unused)), -+ const char *name __attribute__ ((unused))) -+{ -+ struct grub_file *file, *bufio; -+ -+ file = grub_malloc (sizeof (*file)); -+ if (!file) -+ return grub_errno; -+ -+ grub_memcpy (file, file_out, sizeof (struct grub_file)); -+ file->device->net->name = grub_strdup (name); -+ -+ if (!file->device->net->name) -+ { -+ grub_free (file); -+ return grub_errno; -+ } -+ -+ efi_net_interface(open, file, name); -+ grub_print_error (); -+ -+ bufio = grub_bufio_open (file, 32768); -+ if (!bufio) -+ { -+ grub_free (file->device->net->name); -+ grub_free (file); -+ return grub_errno; -+ } -+ grub_memcpy (file_out, bufio, sizeof (struct grub_file)); -+ grub_free (bufio); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_ssize_t -+grub_efihttp_chunk_read (grub_file_t file, char *buf, -+ grub_size_t len, grub_size_t chunk_size) -+{ -+ char *chunk = grub_malloc (chunk_size); -+ grub_size_t sum = 0; -+ -+ while (len) -+ { -+ grub_ssize_t rd; -+ grub_size_t sz = (len > chunk_size) ? chunk_size : len; -+ -+ rd = efi_net_interface (read, file, chunk, sz); -+ -+ if (rd <= 0) -+ return rd; -+ -+ if (buf) -+ { -+ grub_memcpy (buf, chunk, rd); -+ buf += rd; -+ } -+ sum += rd; -+ len -= rd; -+ } -+ -+ grub_free (chunk); -+ return sum; -+} -+ -+static grub_ssize_t -+grub_efi_netfs_read (grub_file_t file __attribute__ ((unused)), -+ char *buf __attribute__ ((unused)), grub_size_t len __attribute__ ((unused))) -+{ -+ if (file->offset > file->device->net->offset) -+ { -+ grub_efihttp_chunk_read (file, NULL, file->offset - file->device->net->offset, 10240); -+ } -+ else if (file->offset < file->device->net->offset) -+ { -+ efi_net_interface (close, file); -+ efi_net_interface (open, file, file->device->net->name); -+ if (file->offset) -+ grub_efihttp_chunk_read (file, NULL, file->offset, 10240); -+ } -+ -+ return efi_net_interface (read, file, buf, len); -+} -+ -+static grub_err_t -+grub_efi_netfs_close (grub_file_t file) -+{ -+ efi_net_interface (close, file); -+ return GRUB_ERR_NONE; -+} -+ -+static grub_efi_handle_t -+grub_efi_service_binding (grub_efi_handle_t dev, grub_efi_guid_t *service_binding_guid) -+{ -+ grub_efi_service_binding_t *service; -+ grub_efi_status_t status; -+ grub_efi_handle_t child_dev = NULL; -+ -+ service = grub_efi_open_protocol (dev, service_binding_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ if (!service) -+ { -+ grub_error (GRUB_ERR_IO, N_("couldn't open efi service binding protocol")); -+ return NULL; -+ } -+ -+ status = efi_call_2 (service->create_child, service, &child_dev); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_error (GRUB_ERR_IO, N_("Failed to create child device of http service %x"), status); -+ return NULL; -+ } -+ -+ return child_dev; -+} -+ -+static grub_err_t -+grub_efi_net_parse_address (const char *address, -+ grub_efi_ip4_config2_manual_address_t *ip4, -+ grub_efi_ip6_config_manual_address_t *ip6, -+ int *is_ip6, -+ int *has_cidr) -+{ -+ const char *rest; -+ -+ if (grub_efi_string_to_ip4_address (address, &ip4->address, &rest)) -+ { -+ *is_ip6 = 0; -+ if (*rest == '/') -+ { -+ grub_uint32_t subnet_mask_size; -+ -+ subnet_mask_size = grub_strtoul (rest + 1, (char **) &rest, 0); -+ -+ if (!grub_errno && subnet_mask_size <= 32 && *rest == 0) -+ { -+ grub_uint32_t subnet_mask; -+ -+ subnet_mask = grub_cpu_to_be32 ((0xffffffffU << (32 - subnet_mask_size))); -+ grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); -+ if (has_cidr) -+ *has_cidr = 1; -+ return GRUB_ERR_NONE; -+ } -+ } -+ else if (*rest == 0) -+ { -+ grub_uint32_t subnet_mask = 0xffffffffU; -+ grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); -+ if (has_cidr) -+ *has_cidr = 0; -+ return GRUB_ERR_NONE; -+ } -+ } -+ else if (grub_efi_string_to_ip6_address (address, &ip6->address, &rest)) -+ { -+ *is_ip6 = 1; -+ if (*rest == '/') -+ { -+ grub_efi_uint8_t prefix_length; -+ -+ prefix_length = grub_strtoul (rest + 1, (char **) &rest, 0); -+ if (!grub_errno && prefix_length <= 128 && *rest == 0) -+ { -+ ip6->prefix_length = prefix_length; -+ ip6->is_anycast = 0; -+ if (has_cidr) -+ *has_cidr = 1; -+ return GRUB_ERR_NONE; -+ } -+ } -+ else if (*rest == 0) -+ { -+ ip6->prefix_length = 128; -+ ip6->is_anycast = 0; -+ if (has_cidr) -+ *has_cidr = 0; -+ return GRUB_ERR_NONE; -+ } -+ } -+ -+ return grub_error (GRUB_ERR_NET_BAD_ADDRESS, -+ N_("unrecognised network address `%s'"), -+ address); -+} -+ -+static grub_efi_net_interface_t * -+match_route (const char *server) -+{ -+ grub_err_t err; -+ grub_efi_ip4_config2_manual_address_t ip4; -+ grub_efi_ip6_config_manual_address_t ip6; -+ grub_efi_net_interface_t *inf; -+ int is_ip6 = 0; -+ -+ err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0); -+ -+ if (err) -+ { -+ grub_print_error (); -+ return NULL; -+ } -+ -+ if (is_ip6) -+ { -+ struct grub_efi_net_device *dev; -+ grub_efi_net_ip_address_t addr; -+ -+ grub_memcpy (addr.ip6, ip6.address, sizeof(ip6.address)); -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ if ((inf = efi_net_ip6_config->best_interface (dev, &addr))) -+ return inf; -+ } -+ else -+ { -+ struct grub_efi_net_device *dev; -+ grub_efi_net_ip_address_t addr; -+ -+ grub_memcpy (addr.ip4, ip4.address, sizeof(ip4.address)); -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ if ((inf = efi_net_ip4_config->best_interface (dev, &addr))) -+ return inf; -+ } -+ -+ return 0; -+} -+ -+static void -+grub_efi_net_add_pxebc_to_cards (void) -+{ -+ grub_efi_uintn_t num_handles; -+ grub_efi_handle_t *handles; -+ grub_efi_handle_t *handle; -+ -+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &pxe_io_guid, -+ 0, &num_handles); -+ if (!handles) -+ return; -+ -+ for (handle = handles; num_handles--; handle++) -+ { -+ grub_efi_device_path_t *dp, *ddp, *ldp; -+ grub_efi_pxe_t *pxe; -+ struct grub_efi_net_device *d; -+ int is_ip6 = 0; -+ -+ dp = grub_efi_get_device_path (*handle); -+ if (!dp) -+ continue; -+ -+ ddp = grub_efi_duplicate_device_path (dp); -+ ldp = grub_efi_find_last_device_path (ddp); -+ -+ if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE -+ && ldp->subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) -+ { -+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ ldp->length = sizeof (*ldp); -+ } -+ else if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE -+ && ldp->subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) -+ { -+ is_ip6 = 1; -+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; -+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; -+ ldp->length = sizeof (*ldp); -+ } -+ -+ for (d = net_devices; d; d = d->next) -+ if (grub_efi_compare_device_paths (ddp, grub_efi_get_device_path (d->handle)) == 0) -+ break; -+ -+ if (!d) -+ { -+ grub_free (ddp); -+ continue; -+ } -+ -+ pxe = grub_efi_open_protocol (*handle, &pxe_io_guid, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ -+ if (!pxe) -+ { -+ grub_free (ddp); -+ continue; -+ } -+ -+ if (is_ip6) -+ { -+ d->ip6_pxe_handle = *handle; -+ d->ip6_pxe = pxe; -+ } -+ else -+ { -+ d->ip4_pxe_handle = *handle; -+ d->ip4_pxe = pxe; -+ } -+ -+ grub_free (ddp); -+ } -+ -+ grub_free (handles); -+} -+ -+static void -+set_ip_policy_to_static (void) -+{ -+ struct grub_efi_net_device *dev; -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ { -+ grub_efi_ip4_config2_policy_t ip4_policy = GRUB_EFI_IP4_CONFIG2_POLICY_STATIC; -+ -+ if (efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, -+ sizeof (ip4_policy), &ip4_policy) != GRUB_EFI_SUCCESS) -+ grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP4_CONFIG2_POLICY_STATIC on dev `%s'", dev->card_name); -+ -+ if (dev->ip6_config) -+ { -+ grub_efi_ip6_config_policy_t ip6_policy = GRUB_EFI_IP6_CONFIG_POLICY_MANUAL; -+ -+ if (efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, -+ sizeof (ip6_policy), &ip6_policy) != GRUB_EFI_SUCCESS) -+ grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP6_CONFIG_POLICY_MANUAL on dev `%s'", dev->card_name); -+ } -+ } -+} -+ -+/* FIXME: Do not fail if the card did not support any of the protocol (Eg http) */ -+static void -+grub_efi_net_find_cards (void) -+{ -+ grub_efi_uintn_t num_handles; -+ grub_efi_handle_t *handles; -+ grub_efi_handle_t *handle; -+ int id; -+ -+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &ip4_config_guid, -+ 0, &num_handles); -+ if (!handles) -+ return; -+ -+ for (id = 0, handle = handles; num_handles--; handle++, id++) -+ { -+ grub_efi_device_path_t *dp; -+ grub_efi_ip4_config2_protocol_t *ip4_config; -+ grub_efi_ip6_config_protocol_t *ip6_config; -+ grub_efi_handle_t http_handle; -+ grub_efi_http_t *http; -+ grub_efi_handle_t dhcp4_handle; -+ grub_efi_dhcp4_protocol_t *dhcp4; -+ grub_efi_handle_t dhcp6_handle; -+ grub_efi_dhcp6_protocol_t *dhcp6; -+ -+ struct grub_efi_net_device *d; -+ -+ dp = grub_efi_get_device_path (*handle); -+ if (!dp) -+ continue; -+ -+ ip4_config = grub_efi_open_protocol (*handle, &ip4_config_guid, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ if (!ip4_config) -+ continue; -+ -+ ip6_config = grub_efi_open_protocol (*handle, &ip6_config_guid, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); -+ -+ http_handle = grub_efi_service_binding (*handle, &http_service_binding_guid); -+ grub_errno = GRUB_ERR_NONE; -+ http = (http_handle) -+ ? grub_efi_open_protocol (http_handle, &http_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) -+ : NULL; -+ -+ dhcp4_handle = grub_efi_service_binding (*handle, &dhcp4_service_binding_guid); -+ grub_errno = GRUB_ERR_NONE; -+ dhcp4 = (dhcp4_handle) -+ ? grub_efi_open_protocol (dhcp4_handle, &dhcp4_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) -+ : NULL; -+ -+ -+ dhcp6_handle = grub_efi_service_binding (*handle, &dhcp6_service_binding_guid); -+ grub_errno = GRUB_ERR_NONE; -+ dhcp6 = (dhcp6_handle) -+ ? grub_efi_open_protocol (dhcp6_handle, &dhcp6_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) -+ : NULL; -+ -+ d = grub_malloc (sizeof (*d)); -+ if (!d) -+ { -+ grub_free (handles); -+ while (net_devices) -+ { -+ d = net_devices->next; -+ grub_free (net_devices); -+ net_devices = d; -+ } -+ return; -+ } -+ d->handle = *handle; -+ d->ip4_config = ip4_config; -+ d->ip6_config = ip6_config; -+ d->http_handle = http_handle; -+ d->http = http; -+ d->dhcp4_handle = dhcp4_handle; -+ d->dhcp4 = dhcp4; -+ d->dhcp6_handle = dhcp6_handle; -+ d->dhcp6 = dhcp6; -+ d->next = net_devices; -+ d->card_name = grub_xasprintf ("efinet%d", id); -+ d->net_interfaces = NULL; -+ net_devices = d; -+ } -+ -+ grub_efi_net_add_pxebc_to_cards (); -+ grub_free (handles); -+ set_ip_policy_to_static (); -+} -+ -+static void -+listroutes_ip4 (struct grub_efi_net_device *netdev) -+{ -+ char **routes; -+ -+ routes = NULL; -+ -+ if ((routes = efi_net_ip4_config->get_route_table (netdev))) -+ { -+ char **r; -+ -+ for (r = routes; *r; ++r) -+ grub_printf ("%s\n", *r); -+ } -+ -+ if (routes) -+ { -+ char **r; -+ -+ for (r = routes; *r; ++r) -+ grub_free (*r); -+ grub_free (routes); -+ } -+} -+ -+static void -+listroutes_ip6 (struct grub_efi_net_device *netdev) -+{ -+ char **routes; -+ -+ routes = NULL; -+ -+ if ((routes = efi_net_ip6_config->get_route_table (netdev))) -+ { -+ char **r; -+ -+ for (r = routes; *r; ++r) -+ grub_printf ("%s\n", *r); -+ } -+ -+ if (routes) -+ { -+ char **r; -+ -+ for (r = routes; *r; ++r) -+ grub_free (*r); -+ grub_free (routes); -+ } -+} -+ -+static grub_err_t -+grub_cmd_efi_listroutes (struct grub_command *cmd __attribute__ ((unused)), -+ int argc __attribute__ ((unused)), -+ char **args __attribute__ ((unused))) -+{ -+ struct grub_efi_net_device *netdev; -+ -+ for (netdev = net_devices; netdev; netdev = netdev->next) -+ { -+ listroutes_ip4 (netdev); -+ listroutes_ip6 (netdev); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+static grub_err_t -+grub_cmd_efi_listcards (struct grub_command *cmd __attribute__ ((unused)), -+ int argc __attribute__ ((unused)), -+ char **args __attribute__ ((unused))) -+{ -+ struct grub_efi_net_device *dev; -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ { -+ char *hw_addr; -+ -+ hw_addr = efi_net_ip4_config->get_hw_address (dev); -+ -+ if (hw_addr) -+ { -+ grub_printf ("%s %s\n", dev->card_name, hw_addr); -+ grub_free (hw_addr); -+ } -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_efi_listaddrs (struct grub_command *cmd __attribute__ ((unused)), -+ int argc __attribute__ ((unused)), -+ char **args __attribute__ ((unused))) -+{ -+ struct grub_efi_net_device *dev; -+ grub_efi_net_interface_t *inf; -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ for (inf = dev->net_interfaces; inf; inf = inf->next) -+ { -+ char *hw_addr = NULL; -+ char *addr = NULL; -+ -+ if ((hw_addr = efi_net_interface_get_hw_address (inf)) -+ && (addr = efi_net_interface_get_address (inf))) -+ grub_printf ("%s %s %s\n", inf->name, hw_addr, addr); -+ -+ if (hw_addr) -+ grub_free (hw_addr); -+ if (addr) -+ grub_free (addr); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+/* FIXME: support MAC specifying. */ -+static grub_err_t -+grub_cmd_efi_addaddr (struct grub_command *cmd __attribute__ ((unused)), -+ int argc, char **args) -+{ -+ struct grub_efi_net_device *dev; -+ grub_err_t err; -+ grub_efi_ip4_config2_manual_address_t ip4; -+ grub_efi_ip6_config_manual_address_t ip6; -+ grub_efi_net_ip_manual_address_t net_ip; -+ int is_ip6 = 0; -+ int cidr = 0; -+ -+ if (argc != 3) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); -+ -+ for (dev = net_devices; dev; dev = dev->next) -+ { -+ if (grub_strcmp (dev->card_name, args[1]) == 0) -+ break; -+ } -+ -+ if (!dev) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); -+ -+ err = grub_efi_net_parse_address (args[2], &ip4, &ip6, &is_ip6, &cidr); -+ -+ if (err) -+ return err; -+ -+ net_ip.is_ip6 = is_ip6; -+ if (is_ip6) -+ grub_memcpy (&net_ip.ip6, &ip6, sizeof(net_ip.ip6)); -+ else -+ grub_memcpy (&net_ip.ip4, &ip4, sizeof(net_ip.ip4)); -+ -+ if (!grub_efi_net_create_interface (dev, -+ args[0], -+ &net_ip, -+ cidr)) -+ return grub_errno; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static struct grub_fs grub_efi_netfs; -+ -+static grub_net_t -+grub_net_open_real (const char *name __attribute__ ((unused))) -+{ -+ grub_size_t protnamelen; -+ const char *protname, *server; -+ grub_net_t ret; -+ -+ net_interface = NULL; -+ -+ if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) -+ { -+ protname = "tftp"; -+ protnamelen = sizeof ("tftp") - 1; -+ server = name + sizeof ("pxe:") - 1; -+ } -+ else if (grub_strcmp (name, "pxe") == 0) -+ { -+ protname = "tftp"; -+ protnamelen = sizeof ("tftp") - 1; -+ server = default_server; -+ } -+ else -+ { -+ const char *comma; -+ -+ comma = grub_strchr (name, ','); -+ if (comma) -+ { -+ protnamelen = comma - name; -+ server = comma + 1; -+ protname = name; -+ } -+ else -+ { -+ protnamelen = grub_strlen (name); -+ server = default_server; -+ protname = name; -+ } -+ } -+ -+ if (!server) -+ { -+ grub_error (GRUB_ERR_NET_BAD_ADDRESS, -+ N_("no server is specified")); -+ return NULL; -+ } -+ -+ /*FIXME: Use DNS translate name to address */ -+ net_interface = match_route (server); -+ -+ /*XXX: should we check device with default gateway ? */ -+ if (!net_interface && !(net_interface = net_default_interface)) -+ { -+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"), -+ name); -+ return NULL; -+ } -+ -+ if ((protnamelen == (sizeof ("https") - 1) -+ && grub_memcmp ("https", protname, protnamelen) == 0)) -+ { -+ net_interface->io = &io_http; -+ net_interface->io_type = 1; -+ } -+ else if ((protnamelen == (sizeof ("http") - 1) -+ && grub_memcmp ("http", protname, protnamelen) == 0)) -+ { -+ net_interface->io = &io_http; -+ net_interface->io_type = 0; -+ } -+ else if (protnamelen == (sizeof ("tftp") - 1) -+ && grub_memcmp ("tftp", protname, protnamelen) == 0) -+ { -+ net_interface->io = &io_pxe; -+ net_interface->io_type = 0; -+ } -+ else -+ { -+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), -+ name); -+ return NULL; -+ } -+ -+ /*XXX: Should we try to avoid doing excess "reconfigure" here ??? */ -+ efi_net_interface (configure); -+ -+ ret = grub_zalloc (sizeof (*ret)); -+ if (!ret) -+ return NULL; -+ -+ ret->server = grub_strdup (server); -+ if (!ret->server) -+ { -+ grub_free (ret); -+ return NULL; -+ } -+ -+ ret->fs = &grub_efi_netfs; -+ return ret; -+} -+#if 0 -+static grub_command_t cmd_efi_lsaddr; -+static grub_command_t cmd_efi_lscards; -+static grub_command_t cmd_efi_lsroutes; -+static grub_command_t cmd_efi_addaddr; -+#endif -+ -+static struct grub_fs grub_efi_netfs = -+ { -+ .name = "efi netfs", -+ .fs_dir = grub_efi_netfs_dir, -+ .fs_open = grub_efi_netfs_open, -+ .fs_read = grub_efi_netfs_read, -+ .fs_close = grub_efi_netfs_close, -+ .fs_label = NULL, -+ .fs_uuid = NULL, -+ .fs_mtime = NULL, -+ }; -+ -+int -+grub_efi_net_boot_from_https (void) -+{ -+ grub_efi_loaded_image_t *image = NULL; -+ grub_efi_device_path_t *dp; -+ -+ image = grub_efi_get_loaded_image (grub_efi_image_handle); -+ if (!image) -+ return 0; -+ -+ dp = grub_efi_get_device_path (image->device_handle); -+ -+ while (1) -+ { -+ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); -+ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); -+ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); -+ -+ if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) -+ && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) -+ { -+ grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp; -+ return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0; -+ } -+ -+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) -+ break; -+ dp = (grub_efi_device_path_t *) ((char *) dp + len); -+ } -+ -+ return 0; -+} -+ -+int -+grub_efi_net_boot_from_opa (void) -+{ -+ grub_efi_loaded_image_t *image = NULL; -+ grub_efi_device_path_t *dp; -+ -+ image = grub_efi_get_loaded_image (grub_efi_image_handle); -+ if (!image) -+ return 0; -+ -+ dp = grub_efi_get_device_path (image->device_handle); -+ -+ while (1) -+ { -+ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); -+ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); -+ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); -+ -+ if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) -+ && (subtype == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)) -+ { -+ grub_efi_mac_address_device_path_t *mac_dp = (grub_efi_mac_address_device_path_t *)dp; -+ return (mac_dp->if_type == 0xC7) ? 1 : 0; -+ } -+ -+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) -+ break; -+ dp = (grub_efi_device_path_t *) ((char *) dp + len); -+ } -+ -+ return 0; -+} -+ -+static char * -+grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val __attribute__ ((unused))) -+{ -+ return NULL; -+} -+ -+grub_command_func_t grub_efi_net_list_routes = grub_cmd_efi_listroutes; -+grub_command_func_t grub_efi_net_list_cards = grub_cmd_efi_listcards; -+grub_command_func_t grub_efi_net_list_addrs = grub_cmd_efi_listaddrs; -+grub_command_func_t grub_efi_net_add_addr = grub_cmd_efi_addaddr; -+ -+int -+grub_efi_net_fs_init () -+{ -+ grub_efi_net_find_cards (); -+ grub_efi_net_config = grub_efi_net_config_real; -+ grub_net_open = grub_net_open_real; -+ grub_register_variable_hook ("net_default_server", grub_efi_net_var_get_server, -+ grub_efi_net_var_set_server); -+ grub_env_export ("net_default_server"); -+ grub_register_variable_hook ("pxe_default_server", grub_efi_net_var_get_server, -+ grub_efi_net_var_set_server); -+ grub_env_export ("pxe_default_server"); -+ grub_register_variable_hook ("net_default_interface", 0, -+ grub_efi_net_var_set_interface); -+ grub_env_export ("net_default_interface"); -+ grub_register_variable_hook ("net_default_ip", grub_efi_net_var_get_ip, -+ 0); -+ grub_env_export ("net_default_ip"); -+ grub_register_variable_hook ("net_default_mac", grub_efi_net_var_get_mac, -+ 0); -+ grub_env_export ("net_default_mac"); -+ -+ grub_env_set ("grub_netfs_type", "efi"); -+ grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly); -+ grub_env_export ("grub_netfs_type"); -+ -+ return 1; -+} -+ -+void -+grub_efi_net_fs_fini (void) -+{ -+ grub_env_unset ("grub_netfs_type"); -+ grub_efi_net_unset_interface_vars (); -+ grub_register_variable_hook ("net_default_server", 0, 0); -+ grub_env_unset ("net_default_server"); -+ grub_register_variable_hook ("net_default_interface", 0, 0); -+ grub_env_unset ("net_default_interface"); -+ grub_register_variable_hook ("pxe_default_server", 0, 0); -+ grub_env_unset ("pxe_default_server"); -+ grub_register_variable_hook ("net_default_ip", 0, 0); -+ grub_env_unset ("net_default_ip"); -+ grub_register_variable_hook ("net_default_mac", 0, 0); -+ grub_env_unset ("net_default_mac"); -+ grub_efi_net_config = NULL; -+ grub_net_open = NULL; -+ grub_fs_unregister (&grub_efi_netfs); -+} -diff --git a/grub-core/net/efi/pxe.c b/grub-core/net/efi/pxe.c -new file mode 100644 -index 00000000000..531949cba5c ---- /dev/null -+++ b/grub-core/net/efi/pxe.c -@@ -0,0 +1,424 @@ -+ -+#include -+#include -+#include -+#include -+#include -+ -+static grub_efi_ip6_config_manual_address_t * -+efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config) -+{ -+ grub_efi_uintn_t sz; -+ grub_efi_status_t status; -+ grub_efi_ip6_config_manual_address_t *manual_address; -+ -+ sz = sizeof (*manual_address); -+ manual_address = grub_malloc (sz); -+ if (!manual_address) -+ return NULL; -+ -+ status = efi_call_4 (ip6_config->get_data, ip6_config, -+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, -+ &sz, manual_address); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (manual_address); -+ return NULL; -+ } -+ -+ return manual_address; -+} -+ -+static grub_efi_ip4_config2_manual_address_t * -+efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config) -+{ -+ grub_efi_uintn_t sz; -+ grub_efi_status_t status; -+ grub_efi_ip4_config2_manual_address_t *manual_address; -+ -+ sz = sizeof (*manual_address); -+ manual_address = grub_malloc (sz); -+ if (!manual_address) -+ return NULL; -+ -+ status = efi_call_4 (ip4_config->get_data, ip4_config, -+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, -+ &sz, manual_address); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_free (manual_address); -+ return NULL; -+ } -+ -+ return manual_address; -+} -+ -+static void -+pxe_configure (struct grub_efi_net_device *dev, int prefer_ip6) -+{ -+ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; -+ -+ grub_efi_pxe_mode_t *mode = pxe->mode; -+ -+ if (!mode->started) -+ { -+ grub_efi_status_t status; -+ status = efi_call_2 (pxe->start, pxe, prefer_ip6); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ grub_printf ("Couldn't start PXE\n"); -+ } -+ -+#if 0 -+ grub_printf ("PXE STARTED: %u\n", mode->started); -+ grub_printf ("PXE USING IPV6: %u\n", mode->using_ipv6); -+#endif -+ -+ if (mode->using_ipv6) -+ { -+ grub_efi_ip6_config_manual_address_t *manual_address; -+ manual_address = efi_ip6_config_manual_address (dev->ip6_config); -+ -+ if (manual_address && -+ grub_memcmp (manual_address->address, mode->station_ip.v6, sizeof (manual_address->address)) != 0) -+ { -+ grub_efi_status_t status; -+ grub_efi_pxe_ip_address_t station_ip; -+ -+ grub_memcpy (station_ip.v6.addr, manual_address->address, sizeof (station_ip.v6.addr)); -+ status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, NULL); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ grub_printf ("Couldn't set station ip\n"); -+ -+ grub_free (manual_address); -+ } -+ } -+ else -+ { -+ grub_efi_ip4_config2_manual_address_t *manual_address; -+ manual_address = efi_ip4_config_manual_address (dev->ip4_config); -+ -+ if (manual_address && -+ grub_memcmp (manual_address->address, mode->station_ip.v4, sizeof (manual_address->address)) != 0) -+ { -+ grub_efi_status_t status; -+ grub_efi_pxe_ip_address_t station_ip; -+ grub_efi_pxe_ip_address_t subnet_mask; -+ -+ grub_memcpy (station_ip.v4.addr, manual_address->address, sizeof (station_ip.v4.addr)); -+ grub_memcpy (subnet_mask.v4.addr, manual_address->subnet_mask, sizeof (subnet_mask.v4.addr)); -+ -+ status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, &subnet_mask); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ grub_printf ("Couldn't set station ip\n"); -+ -+ grub_free (manual_address); -+ } -+ } -+ -+#if 0 -+ if (mode->using_ipv6) -+ { -+ grub_printf ("PXE STATION IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", -+ mode->station_ip.v6.addr[0], -+ mode->station_ip.v6.addr[1], -+ mode->station_ip.v6.addr[2], -+ mode->station_ip.v6.addr[3], -+ mode->station_ip.v6.addr[4], -+ mode->station_ip.v6.addr[5], -+ mode->station_ip.v6.addr[6], -+ mode->station_ip.v6.addr[7], -+ mode->station_ip.v6.addr[8], -+ mode->station_ip.v6.addr[9], -+ mode->station_ip.v6.addr[10], -+ mode->station_ip.v6.addr[11], -+ mode->station_ip.v6.addr[12], -+ mode->station_ip.v6.addr[13], -+ mode->station_ip.v6.addr[14], -+ mode->station_ip.v6.addr[15]); -+ } -+ else -+ { -+ grub_printf ("PXE STATION IP: %d.%d.%d.%d\n", -+ mode->station_ip.v4.addr[0], -+ mode->station_ip.v4.addr[1], -+ mode->station_ip.v4.addr[2], -+ mode->station_ip.v4.addr[3]); -+ grub_printf ("PXE SUBNET MASK: %d.%d.%d.%d\n", -+ mode->subnet_mask.v4.addr[0], -+ mode->subnet_mask.v4.addr[1], -+ mode->subnet_mask.v4.addr[2], -+ mode->subnet_mask.v4.addr[3]); -+ } -+#endif -+ -+ /* TODO: Set The Station IP to the IP2 Config */ -+} -+ -+static int -+parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) -+{ -+ grub_uint16_t newip[8]; -+ const char *ptr = val; -+ int word, quaddot = -1; -+ int bracketed = 0; -+ -+ if (ptr[0] == '[') { -+ bracketed = 1; -+ ptr++; -+ } -+ -+ if (ptr[0] == ':' && ptr[1] != ':') -+ return 0; -+ if (ptr[0] == ':') -+ ptr++; -+ -+ for (word = 0; word < 8; word++) -+ { -+ unsigned long t; -+ if (*ptr == ':') -+ { -+ quaddot = word; -+ word--; -+ ptr++; -+ continue; -+ } -+ t = grub_strtoul (ptr, (char **) &ptr, 16); -+ if (grub_errno) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ break; -+ } -+ if (t & ~0xffff) -+ return 0; -+ newip[word] = grub_cpu_to_be16 (t); -+ if (*ptr != ':') -+ break; -+ ptr++; -+ } -+ if (quaddot == -1 && word < 7) -+ return 0; -+ if (quaddot != -1) -+ { -+ grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], -+ (word - quaddot + 1) * sizeof (newip[0])); -+ grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); -+ } -+ grub_memcpy (ip, newip, 16); -+ if (bracketed && *ptr == ']') { -+ ptr++; -+ } -+ if (rest) -+ *rest = ptr; -+ return 1; -+} -+ -+static grub_err_t -+pxe_open (struct grub_efi_net_device *dev, -+ int prefer_ip6, -+ grub_file_t file, -+ const char *filename, -+ int type __attribute__((unused))) -+{ -+ int i; -+ char *p; -+ grub_efi_status_t status; -+ grub_efi_pxe_ip_address_t server_ip; -+ grub_efi_uint64_t file_size = 0; -+ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; -+ -+ if (pxe->mode->using_ipv6) -+ { -+ const char *rest; -+ grub_uint64_t ip6[2]; -+ if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0) -+ grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr)); -+ /* TODO: ERROR Handling Here */ -+#if 0 -+ grub_printf ("PXE SERVER IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", -+ server_ip.v6.addr[0], -+ server_ip.v6.addr[1], -+ server_ip.v6.addr[2], -+ server_ip.v6.addr[3], -+ server_ip.v6.addr[4], -+ server_ip.v6.addr[5], -+ server_ip.v6.addr[6], -+ server_ip.v6.addr[7], -+ server_ip.v6.addr[8], -+ server_ip.v6.addr[9], -+ server_ip.v6.addr[10], -+ server_ip.v6.addr[11], -+ server_ip.v6.addr[12], -+ server_ip.v6.addr[13], -+ server_ip.v6.addr[14], -+ server_ip.v6.addr[15]); -+#endif -+ } -+ else -+ { -+ for (i = 0, p = file->device->net->server; i < 4; ++i, ++p) -+ server_ip.v4.addr[i] = grub_strtoul (p, &p, 10); -+ } -+ -+ status = efi_call_10 (pxe->mtftp, -+ pxe, -+ GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, -+ NULL, -+ 0, -+ &file_size, -+ NULL, -+ &server_ip, -+ (grub_efi_char8_t *)filename, -+ NULL, -+ 0); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ return grub_error (GRUB_ERR_IO, "Couldn't get file size"); -+ -+ file->size = (grub_off_t)file_size; -+ file->not_easily_seekable = 0; -+ file->data = 0; -+ file->device->net->offset = 0; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+pxe_close (struct grub_efi_net_device *dev __attribute__((unused)), -+ int prefer_ip6 __attribute__((unused)), -+ grub_file_t file __attribute__((unused))) -+{ -+ file->offset = 0; -+ file->size = 0; -+ file->device->net->offset = 0; -+ -+ if (file->data) -+ { -+ grub_free (file->data); -+ file->data = NULL; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_ssize_t -+pxe_read (struct grub_efi_net_device *dev, -+ int prefer_ip6, -+ grub_file_t file, -+ char *buf, -+ grub_size_t len) -+{ -+ int i; -+ char *p; -+ grub_efi_status_t status; -+ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; -+ grub_efi_uint64_t bufsz = len; -+ grub_efi_pxe_ip_address_t server_ip; -+ char *buf2 = NULL; -+ -+ if (file->data) -+ { -+ /* TODO: RANGE Check for offset and file size */ -+ grub_memcpy (buf, (char*)file->data + file->device->net->offset, len); -+ file->device->net->offset += len; -+ return len; -+ } -+ -+ if (file->device->net->offset) -+ { -+ grub_error (GRUB_ERR_BUG, "No Offet Read Possible"); -+ grub_print_error (); -+ return 0; -+ } -+ -+ if (pxe->mode->using_ipv6) -+ { -+ const char *rest; -+ grub_uint64_t ip6[2]; -+ if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0) -+ grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr)); -+ /* TODO: ERROR Handling Here */ -+ } -+ else -+ { -+ for (i = 0, p = file->device->net->server; i < 4; ++i, ++p) -+ server_ip.v4.addr[i] = grub_strtoul (p, &p, 10); -+ } -+ -+ status = efi_call_10 (pxe->mtftp, -+ pxe, -+ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, -+ buf, -+ 0, -+ &bufsz, -+ NULL, -+ &server_ip, -+ (grub_efi_char8_t *)file->device->net->name, -+ NULL, -+ 0); -+ -+ if (bufsz != file->size) -+ { -+ grub_error (GRUB_ERR_BUG, "Short read should not happen here"); -+ grub_print_error (); -+ return 0; -+ } -+ -+ if (status == GRUB_EFI_BUFFER_TOO_SMALL) -+ { -+ -+ buf2 = grub_malloc (bufsz); -+ -+ if (!buf2) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "ERROR OUT OF MEMORY"); -+ grub_print_error (); -+ return 0; -+ } -+ -+ status = efi_call_10 (pxe->mtftp, -+ pxe, -+ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, -+ buf2, -+ 0, -+ &bufsz, -+ NULL, -+ &server_ip, -+ (grub_efi_char8_t *)file->device->net->name, -+ NULL, -+ 0); -+ } -+ -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ if (buf2) -+ grub_free (buf2); -+ -+ grub_error (GRUB_ERR_IO, "Failed to Read File"); -+ grub_print_error (); -+ return 0; -+ } -+ -+ if (buf2) -+ grub_memcpy (buf, buf2, len); -+ -+ file->device->net->offset = len; -+ -+ if (buf2) -+ file->data = buf2; -+ -+ return len; -+} -+ -+struct grub_efi_net_io io_pxe = -+ { -+ .configure = pxe_configure, -+ .open = pxe_open, -+ .read = pxe_read, -+ .close = pxe_close -+ }; -+ -diff --git a/grub-core/net/net.c b/grub-core/net/net.c -index 0ce5e675ed7..55aed92722c 100644 ---- a/grub-core/net/net.c -+++ b/grub-core/net/net.c -@@ -32,6 +32,9 @@ - #include - #include - #include -+#ifdef GRUB_MACHINE_EFI -+#include -+#endif - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -2033,8 +2036,49 @@ static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; - static grub_command_t cmd_lsroutes, cmd_lscards; - static grub_command_t cmd_lsaddr, cmd_slaac; - -+#ifdef GRUB_MACHINE_EFI -+ -+static enum { -+ INIT_MODE_NONE, -+ INIT_MODE_GRUB, -+ INIT_MODE_EFI -+} init_mode; -+ -+static grub_command_t cmd_bootp, cmd_bootp6; -+ -+#endif -+ - GRUB_MOD_INIT(net) - { -+#ifdef GRUB_MACHINE_EFI -+ if (grub_net_open) -+ return; -+ -+ if ((grub_efi_net_boot_from_https () || grub_efi_net_boot_from_opa ()) -+ && grub_efi_net_fs_init ()) -+ { -+ cmd_lsroutes = grub_register_command ("net_ls_routes", grub_efi_net_list_routes, -+ "", N_("list network routes")); -+ cmd_lscards = grub_register_command ("net_ls_cards", grub_efi_net_list_cards, -+ "", N_("list network cards")); -+ cmd_lsaddr = grub_register_command ("net_ls_addr", grub_efi_net_list_addrs, -+ "", N_("list network addresses")); -+ cmd_addaddr = grub_register_command ("net_add_addr", grub_efi_net_add_addr, -+ /* TRANSLATORS: HWADDRESS stands for -+ "hardware address". */ -+ N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), -+ N_("Add a network address.")); -+ cmd_bootp = grub_register_command ("net_bootp", grub_efi_net_bootp, -+ N_("[CARD]"), -+ N_("perform a bootp autoconfiguration")); -+ cmd_bootp6 = grub_register_command ("net_bootp6", grub_efi_net_bootp6, -+ N_("[CARD]"), -+ N_("perform a bootp autoconfiguration")); -+ init_mode = INIT_MODE_EFI; -+ return; -+ } -+#endif -+ - grub_register_variable_hook ("net_default_server", defserver_get_env, - defserver_set_env); - grub_env_export ("net_default_server"); -@@ -2082,10 +2126,37 @@ GRUB_MOD_INIT(net) - grub_net_restore_hw, - GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); - grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; -+ -+#ifdef GRUB_MACHINE_EFI -+ grub_env_set ("grub_netfs_type", "grub"); -+ grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly); -+ grub_env_export ("grub_netfs_type"); -+ init_mode = INIT_MODE_GRUB; -+#endif -+ - } - - GRUB_MOD_FINI(net) - { -+ -+#ifdef GRUB_MACHINE_EFI -+ if (init_mode == INIT_MODE_NONE) -+ return; -+ -+ if (init_mode == INIT_MODE_EFI) -+ { -+ grub_unregister_command (cmd_lsroutes); -+ grub_unregister_command (cmd_lscards); -+ grub_unregister_command (cmd_lsaddr); -+ grub_unregister_command (cmd_addaddr); -+ grub_unregister_command (cmd_bootp); -+ grub_unregister_command (cmd_bootp6); -+ grub_efi_net_fs_fini (); -+ init_mode = INIT_MODE_NONE; -+ return; -+ } -+#endif -+ - grub_register_variable_hook ("net_default_server", 0, 0); - grub_register_variable_hook ("pxe_default_server", 0, 0); - -@@ -2104,4 +2175,7 @@ GRUB_MOD_FINI(net) - grub_net_fini_hw (0); - grub_loader_unregister_preboot_hook (fini_hnd); - grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; -+#ifdef GRUB_MACHINE_EFI -+ init_mode = INIT_MODE_NONE; -+#endif - } -diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c -index a2461cda1c4..77958dd9dd5 100644 ---- a/util/grub-mknetdir.c -+++ b/util/grub-mknetdir.c -@@ -32,13 +32,15 @@ - - static char *rootdir = NULL, *subdir = NULL; - static char *debug_image = NULL; -+static char efi_netfs = 0; - - enum - { - OPTION_NET_DIRECTORY = 0x301, - OPTION_SUBDIR, - OPTION_DEBUG, -- OPTION_DEBUG_IMAGE -+ OPTION_DEBUG_IMAGE, -+ OPTION_DEBUG_EFI_NETFS - }; - - static struct argp_option options[] = { -@@ -49,6 +51,7 @@ static struct argp_option options[] = { - 0, N_("relative subdirectory on network server"), 2}, - {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, - {"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2}, -+ {"debug-efi-netfs", OPTION_DEBUG_EFI_NETFS, 0, OPTION_HIDDEN, 0, 2}, - {0, 0, 0, 0, 0, 0} - }; - -@@ -67,6 +70,9 @@ argp_parser (int key, char *arg, struct argp_state *state) - free (subdir); - subdir = xstrdup (arg); - return 0; -+ case OPTION_DEBUG_EFI_NETFS: -+ efi_netfs = 1; -+ return 0; - /* This is an undocumented feature... */ - case OPTION_DEBUG: - verbosity++; -@@ -82,7 +88,6 @@ argp_parser (int key, char *arg, struct argp_state *state) - } - } - -- - struct argp argp = { - options, argp_parser, NULL, - "\v"N_("Prepares GRUB network boot images at net_directory/subdir " -@@ -92,7 +97,7 @@ struct argp argp = { - - static char *base; - --static const struct -+static struct - { - const char *mkimage_target; - const char *netmodule; -@@ -156,6 +161,7 @@ process_input_dir (const char *input_dir, enum grub_install_plat platform) - grub_install_push_module (targets[platform].netmodule); - - output = grub_util_path_concat_ext (2, grubdir, "core", targets[platform].ext); -+ - grub_install_make_image_wrap (input_dir, prefix, output, - 0, load_cfg, - targets[platform].mkimage_target, 0); -@@ -195,7 +201,16 @@ main (int argc, char *argv[]) - - grub_install_mkdir_p (base); - -- grub_install_push_module ("tftp"); -+ if (!efi_netfs) -+ { -+ grub_install_push_module ("tftp"); -+ grub_install_push_module ("http"); -+ } -+ else -+ { -+ targets[GRUB_INSTALL_PLATFORM_I386_EFI].netmodule = "efi_netfs"; -+ targets[GRUB_INSTALL_PLATFORM_X86_64_EFI].netmodule = "efi_netfs"; -+ } - - if (!grub_install_source_directory) - { -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index 0b490195ad9..f431f49973e 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -622,6 +622,23 @@ typedef union - - typedef grub_efi_uint64_t grub_efi_physical_address_t; - typedef grub_efi_uint64_t grub_efi_virtual_address_t; -+typedef struct { -+ grub_uint8_t addr[4]; -+} grub_efi_pxe_ipv4_address_t; -+ -+typedef struct { -+ grub_uint8_t addr[16]; -+} grub_efi_pxe_ipv6_address_t; -+ -+typedef struct { -+ grub_uint8_t addr[32]; -+} grub_efi_pxe_mac_address_t; -+ -+typedef union { -+ grub_uint32_t addr[4]; -+ grub_efi_pxe_ipv4_address_t v4; -+ grub_efi_pxe_ipv6_address_t v6; -+} grub_efi_pxe_ip_address_t; - - struct grub_efi_guid - { -@@ -889,6 +906,8 @@ struct grub_efi_ipv6_device_path - grub_efi_uint16_t remote_port; - grub_efi_uint16_t protocol; - grub_efi_uint8_t static_ip_address; -+ grub_efi_uint8_t prefix_length; -+ grub_efi_ipv6_address_t gateway_ip_address; - } GRUB_PACKED; - typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t; - -@@ -938,6 +957,15 @@ struct grub_efi_uri_device_path - } GRUB_PACKED; - typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t; - -+#define GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE 31 -+struct grub_efi_dns_device_path -+{ -+ grub_efi_device_path_t header; -+ grub_efi_uint8_t is_ipv6; -+ grub_efi_pxe_ip_address_t dns_server_ip[0]; -+} GRUB_PACKED; -+typedef struct grub_efi_dns_device_path grub_efi_dns_device_path_t; -+ - #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 - - /* Media Device Path. */ -@@ -1020,6 +1048,23 @@ struct grub_efi_bios_device_path - } GRUB_PACKED; - typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t; - -+/* Service Binding definitions */ -+struct grub_efi_service_binding; -+ -+typedef grub_efi_status_t -+(*grub_efi_service_binding_create_child) (struct grub_efi_service_binding *this, -+ grub_efi_handle_t *child_handle); -+ -+typedef grub_efi_status_t -+(*grub_efi_service_binding_destroy_child) (struct grub_efi_service_binding *this, -+ grub_efi_handle_t *child_handle); -+ -+typedef struct grub_efi_service_binding -+{ -+ grub_efi_service_binding_create_child create_child; -+ grub_efi_service_binding_destroy_child destroy_child; -+} grub_efi_service_binding_t; -+ - struct grub_efi_open_protocol_information_entry - { - grub_efi_handle_t agent_handle; -@@ -1569,23 +1614,27 @@ typedef struct grub_efi_pxe_tftp_error - grub_efi_char8_t error_string[127]; - } grub_efi_pxe_tftp_error_t; - --typedef struct { -- grub_uint8_t addr[4]; --} grub_efi_pxe_ipv4_address_t; -+typedef grub_efi_uint16_t grub_efi_pxe_base_code_udp_port_t; - --typedef struct { -- grub_uint8_t addr[16]; --} grub_efi_pxe_ipv6_address_t; -+typedef enum { -+ GRUB_EFI_PXE_BASE_CODE_TFTP_FIRST, -+ GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, -+ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, -+ GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, -+ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, -+ GRUB_EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, -+ GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_FILE, -+ GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, -+ GRUB_EFI_PXE_BASE_CODE_MTFTP_LAST -+} grub_efi_pxe_base_code_tftp_opcode_t; - - typedef struct { -- grub_uint8_t addr[32]; --} grub_efi_pxe_mac_address_t; -- --typedef union { -- grub_uint32_t addr[4]; -- grub_efi_pxe_ipv4_address_t v4; -- grub_efi_pxe_ipv6_address_t v6; --} grub_efi_pxe_ip_address_t; -+ grub_efi_ip_address_t mcast_ip; -+ grub_efi_pxe_base_code_udp_port_t c_port; -+ grub_efi_pxe_base_code_udp_port_t s_port; -+ grub_efi_uint16_t listen_timeout; -+ grub_efi_uint16_t transmit_timeout; -+} grub_efi_pxe_base_code_mtftp_info_t; - - #define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 - typedef struct grub_efi_pxe_ip_filter -@@ -1652,17 +1701,31 @@ typedef struct grub_efi_pxe_mode - typedef struct grub_efi_pxe - { - grub_uint64_t rev; -- void (*start) (void); -+ grub_efi_status_t (*start) (struct grub_efi_pxe *this, grub_efi_boolean_t use_ipv6); - void (*stop) (void); -- void (*dhcp) (void); -+ grub_efi_status_t (*dhcp) (struct grub_efi_pxe *this, -+ grub_efi_boolean_t sort_offers); - void (*discover) (void); -- void (*mftp) (void); -+ grub_efi_status_t (*mtftp) (struct grub_efi_pxe *this, -+ grub_efi_pxe_base_code_tftp_opcode_t operation, -+ void *buffer_ptr, -+ grub_efi_boolean_t overwrite, -+ grub_efi_uint64_t *buffer_size, -+ grub_efi_uintn_t *block_size, -+ grub_efi_pxe_ip_address_t *server_ip, -+ //grub_efi_ip_address_t *server_ip, -+ grub_efi_char8_t *filename, -+ grub_efi_pxe_base_code_mtftp_info_t *info, -+ grub_efi_boolean_t dont_use_buffer); - void (*udpwrite) (void); - void (*udpread) (void); - void (*setipfilter) (void); - void (*arp) (void); - void (*setparams) (void); -- void (*setstationip) (void); -+ grub_efi_status_t (*set_station_ip) (struct grub_efi_pxe *this, -+ grub_efi_pxe_ip_address_t *new_station_ip, -+ grub_efi_pxe_ip_address_t *new_subnet_mask); -+ //void (*setstationip) (void); - void (*setpackets) (void); - struct grub_efi_pxe_mode *mode; - } grub_efi_pxe_t; -@@ -1924,6 +1987,44 @@ struct grub_efi_ip4_config2_protocol - }; - typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t; - -+struct grub_efi_ip4_route_table { -+ grub_efi_ipv4_address_t subnet_address; -+ grub_efi_ipv4_address_t subnet_mask; -+ grub_efi_ipv4_address_t gateway_address; -+}; -+ -+typedef struct grub_efi_ip4_route_table grub_efi_ip4_route_table_t; -+ -+#define GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32 -+ -+struct grub_efi_ip4_config2_interface_info { -+ grub_efi_char16_t name[GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE]; -+ grub_efi_uint8_t if_type; -+ grub_efi_uint32_t hw_address_size; -+ grub_efi_mac_address_t hw_address; -+ grub_efi_ipv4_address_t station_address; -+ grub_efi_ipv4_address_t subnet_mask; -+ grub_efi_uint32_t route_table_size; -+ grub_efi_ip4_route_table_t *route_table; -+}; -+ -+typedef struct grub_efi_ip4_config2_interface_info grub_efi_ip4_config2_interface_info_t; -+ -+enum grub_efi_ip4_config2_policy { -+ GRUB_EFI_IP4_CONFIG2_POLICY_STATIC, -+ GRUB_EFI_IP4_CONFIG2_POLICY_DHCP, -+ GRUB_EFI_IP4_CONFIG2_POLICY_MAX -+}; -+ -+typedef enum grub_efi_ip4_config2_policy grub_efi_ip4_config2_policy_t; -+ -+struct grub_efi_ip4_config2_manual_address { -+ grub_efi_ipv4_address_t address; -+ grub_efi_ipv4_address_t subnet_mask; -+}; -+ -+typedef struct grub_efi_ip4_config2_manual_address grub_efi_ip4_config2_manual_address_t; -+ - enum grub_efi_ip6_config_data_type { - GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, - GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID, -@@ -1958,6 +2059,49 @@ struct grub_efi_ip6_config_protocol - }; - typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t; - -+enum grub_efi_ip6_config_policy { -+ GRUB_EFI_IP6_CONFIG_POLICY_MANUAL, -+ GRUB_EFI_IP6_CONFIG_POLICY_AUTOMATIC -+}; -+typedef enum grub_efi_ip6_config_policy grub_efi_ip6_config_policy_t; -+ -+struct grub_efi_ip6_address_info { -+ grub_efi_ipv6_address_t address; -+ grub_efi_uint8_t prefix_length; -+}; -+typedef struct grub_efi_ip6_address_info grub_efi_ip6_address_info_t; -+ -+struct grub_efi_ip6_route_table { -+ grub_efi_pxe_ipv6_address_t gateway; -+ grub_efi_pxe_ipv6_address_t destination; -+ grub_efi_uint8_t prefix_length; -+}; -+typedef struct grub_efi_ip6_route_table grub_efi_ip6_route_table_t; -+ -+struct grub_efi_ip6_config_interface_info { -+ grub_efi_char16_t name[32]; -+ grub_efi_uint8_t if_type; -+ grub_efi_uint32_t hw_address_size; -+ grub_efi_mac_address_t hw_address; -+ grub_efi_uint32_t address_info_count; -+ grub_efi_ip6_address_info_t *address_info; -+ grub_efi_uint32_t route_count; -+ grub_efi_ip6_route_table_t *route_table; -+}; -+typedef struct grub_efi_ip6_config_interface_info grub_efi_ip6_config_interface_info_t; -+ -+struct grub_efi_ip6_config_dup_addr_detect_transmits { -+ grub_efi_uint32_t dup_addr_detect_transmits; -+}; -+typedef struct grub_efi_ip6_config_dup_addr_detect_transmits grub_efi_ip6_config_dup_addr_detect_transmits_t; -+ -+struct grub_efi_ip6_config_manual_address { -+ grub_efi_ipv6_address_t address; -+ grub_efi_boolean_t is_anycast; -+ grub_efi_uint8_t prefix_length; -+}; -+typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; -+ - #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ - || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ - || defined(__riscv) -diff --git a/include/grub/efi/dhcp.h b/include/grub/efi/dhcp.h -new file mode 100644 -index 00000000000..fdb88eb810e ---- /dev/null -+++ b/include/grub/efi/dhcp.h -@@ -0,0 +1,343 @@ -+#ifndef GRUB_EFI_DHCP_HEADER -+#define GRUB_EFI_DHCP_HEADER 1 -+ -+#define GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \ -+ { 0x9d9a39d8, 0xbd42, 0x4a73, \ -+ { 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \ -+ } -+ -+#define GRUB_EFI_DHCP4_PROTOCOL_GUID \ -+ { 0x8a219718, 0x4ef5, 0x4761, \ -+ { 0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \ -+ } -+ -+#define GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \ -+ { 0x9fb9a8a1, 0x2f4a, 0x43a6, \ -+ { 0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4 ,0x7a, 0xd5 } \ -+ } -+ -+#define GRUB_EFI_DHCP6_PROTOCOL_GUID \ -+ { 0x87c8bad7, 0x595, 0x4053, \ -+ { 0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \ -+ } -+ -+typedef struct grub_efi_dhcp4_protocol grub_efi_dhcp4_protocol_t; -+ -+enum grub_efi_dhcp4_state { -+ GRUB_EFI_DHCP4_STOPPED, -+ GRUB_EFI_DHCP4_INIT, -+ GRUB_EFI_DHCP4_SELECTING, -+ GRUB_EFI_DHCP4_REQUESTING, -+ GRUB_EFI_DHCP4_BOUND, -+ GRUB_EFI_DHCP4_RENEWING, -+ GRUB_EFI_DHCP4_REBINDING, -+ GRUB_EFI_DHCP4_INIT_REBOOT, -+ GRUB_EFI_DHCP4_REBOOTING -+}; -+ -+typedef enum grub_efi_dhcp4_state grub_efi_dhcp4_state_t; -+ -+struct grub_efi_dhcp4_header { -+ grub_efi_uint8_t op_code; -+ grub_efi_uint8_t hw_type; -+ grub_efi_uint8_t hw_addr_len; -+ grub_efi_uint8_t hops; -+ grub_efi_uint32_t xid; -+ grub_efi_uint16_t seconds; -+ grub_efi_uint16_t reserved; -+ grub_efi_ipv4_address_t client_addr; -+ grub_efi_ipv4_address_t your_addr; -+ grub_efi_ipv4_address_t server_addr; -+ grub_efi_ipv4_address_t gateway_addr; -+ grub_efi_uint8_t client_hw_addr[16]; -+ grub_efi_char8_t server_name[64]; -+ grub_efi_char8_t boot_file_name[128]; -+} GRUB_PACKED; -+ -+typedef struct grub_efi_dhcp4_header grub_efi_dhcp4_header_t; -+ -+struct grub_efi_dhcp4_packet { -+ grub_efi_uint32_t size; -+ grub_efi_uint32_t length; -+ struct { -+ grub_efi_dhcp4_header_t header; -+ grub_efi_uint32_t magik; -+ grub_efi_uint8_t option[1]; -+ } dhcp4; -+} GRUB_PACKED; -+ -+typedef struct grub_efi_dhcp4_packet grub_efi_dhcp4_packet_t; -+ -+struct grub_efi_dhcp4_listen_point { -+ grub_efi_ipv4_address_t listen_address; -+ grub_efi_ipv4_address_t subnet_mask; -+ grub_efi_uint16_t listen_port; -+}; -+ -+typedef struct grub_efi_dhcp4_listen_point grub_efi_dhcp4_listen_point_t; -+ -+struct grub_efi_dhcp4_transmit_receive_token { -+ grub_efi_status_t status; -+ grub_efi_event_t completion_event; -+ grub_efi_ipv4_address_t remote_address; -+ grub_efi_uint16_t remote_port; -+ grub_efi_ipv4_address_t gateway_address; -+ grub_efi_uint32_t listen_point_count; -+ grub_efi_dhcp4_listen_point_t *listen_points; -+ grub_efi_uint32_t timeout_value; -+ grub_efi_dhcp4_packet_t *packet; -+ grub_efi_uint32_t response_count; -+ grub_efi_dhcp4_packet_t *response_list; -+}; -+ -+typedef struct grub_efi_dhcp4_transmit_receive_token grub_efi_dhcp4_transmit_receive_token_t; -+ -+enum grub_efi_dhcp4_event { -+ GRUB_EFI_DHCP4_SEND_DISCOVER = 0X01, -+ GRUB_EFI_DHCP4_RCVD_OFFER, -+ GRUB_EFI_DHCP4_SELECT_OFFER, -+ GRUB_EFI_DHCP4_SEND_REQUEST, -+ GRUB_EFI_DHCP4_RCVD_ACK, -+ GRUB_EFI_DHCP4_RCVD_NAK, -+ GRUB_EFI_DHCP4_SEND_DECLINE, -+ GRUB_EFI_DHCP4_BOUND_COMPLETED, -+ GRUB_EFI_DHCP4_ENTER_RENEWING, -+ GRUB_EFI_DHCP4_ENTER_REBINDING, -+ GRUB_EFI_DHCP4_ADDRESS_LOST, -+ GRUB_EFI_DHCP4_FAIL -+}; -+ -+typedef enum grub_efi_dhcp4_event grub_efi_dhcp4_event_t; -+ -+struct grub_efi_dhcp4_packet_option { -+ grub_efi_uint8_t op_code; -+ grub_efi_uint8_t length; -+ grub_efi_uint8_t data[1]; -+} GRUB_PACKED; -+ -+typedef struct grub_efi_dhcp4_packet_option grub_efi_dhcp4_packet_option_t; -+ -+struct grub_efi_dhcp4_config_data { -+ grub_efi_uint32_t discover_try_count; -+ grub_efi_uint32_t *discover_timeout; -+ grub_efi_uint32_t request_try_count; -+ grub_efi_uint32_t *request_timeout; -+ grub_efi_ipv4_address_t client_address; -+ grub_efi_status_t (*dhcp4_callback) ( -+ grub_efi_dhcp4_protocol_t *this, -+ void *context, -+ grub_efi_dhcp4_state_t current_state, -+ grub_efi_dhcp4_event_t dhcp4_event, -+ grub_efi_dhcp4_packet_t *packet, -+ grub_efi_dhcp4_packet_t **new_packet -+ ); -+ void *callback_context; -+ grub_efi_uint32_t option_count; -+ grub_efi_dhcp4_packet_option_t **option_list; -+}; -+ -+typedef struct grub_efi_dhcp4_config_data grub_efi_dhcp4_config_data_t; -+ -+struct grub_efi_dhcp4_mode_data { -+ grub_efi_dhcp4_state_t state; -+ grub_efi_dhcp4_config_data_t config_data; -+ grub_efi_ipv4_address_t client_address; -+ grub_efi_mac_address_t client_mac_address; -+ grub_efi_ipv4_address_t server_address; -+ grub_efi_ipv4_address_t router_address; -+ grub_efi_ipv4_address_t subnet_mask; -+ grub_efi_uint32_t lease_time; -+ grub_efi_dhcp4_packet_t *reply_packet; -+}; -+ -+typedef struct grub_efi_dhcp4_mode_data grub_efi_dhcp4_mode_data_t; -+ -+struct grub_efi_dhcp4_protocol { -+ grub_efi_status_t (*get_mode_data) (grub_efi_dhcp4_protocol_t *this, -+ grub_efi_dhcp4_mode_data_t *dhcp4_mode_data); -+ grub_efi_status_t (*configure) (grub_efi_dhcp4_protocol_t *this, -+ grub_efi_dhcp4_config_data_t *dhcp4_cfg_data); -+ grub_efi_status_t (*start) (grub_efi_dhcp4_protocol_t *this, -+ grub_efi_event_t completion_event); -+ grub_efi_status_t (*renew_rebind) (grub_efi_dhcp4_protocol_t *this, -+ grub_efi_boolean_t rebind_request, -+ grub_efi_event_t completion_event); -+ grub_efi_status_t (*release) (grub_efi_dhcp4_protocol_t *this); -+ grub_efi_status_t (*stop) (grub_efi_dhcp4_protocol_t *this); -+ grub_efi_status_t (*build) (grub_efi_dhcp4_protocol_t *this, -+ grub_efi_dhcp4_packet_t *seed_packet, -+ grub_efi_uint32_t delete_count, -+ grub_efi_uint8_t *delete_list, -+ grub_efi_uint32_t append_count, -+ grub_efi_dhcp4_packet_option_t *append_list[], -+ grub_efi_dhcp4_packet_t **new_packet); -+ grub_efi_status_t (*transmit_receive) (grub_efi_dhcp4_protocol_t *this, -+ grub_efi_dhcp4_transmit_receive_token_t *token); -+ grub_efi_status_t (*parse) (grub_efi_dhcp4_protocol_t *this, -+ grub_efi_dhcp4_packet_t *packet, -+ grub_efi_uint32_t *option_count, -+ grub_efi_dhcp4_packet_option_t *packet_option_list[]); -+}; -+ -+typedef struct grub_efi_dhcp6_protocol grub_efi_dhcp6_protocol_t; -+ -+struct grub_efi_dhcp6_retransmission { -+ grub_efi_uint32_t irt; -+ grub_efi_uint32_t mrc; -+ grub_efi_uint32_t mrt; -+ grub_efi_uint32_t mrd; -+}; -+ -+typedef struct grub_efi_dhcp6_retransmission grub_efi_dhcp6_retransmission_t; -+ -+enum grub_efi_dhcp6_event { -+ GRUB_EFI_DHCP6_SEND_SOLICIT, -+ GRUB_EFI_DHCP6_RCVD_ADVERTISE, -+ GRUB_EFI_DHCP6_SELECT_ADVERTISE, -+ GRUB_EFI_DHCP6_SEND_REQUEST, -+ GRUB_EFI_DHCP6_RCVD_REPLY, -+ GRUB_EFI_DHCP6_RCVD_RECONFIGURE, -+ GRUB_EFI_DHCP6_SEND_DECLINE, -+ GRUB_EFI_DHCP6_SEND_CONFIRM, -+ GRUB_EFI_DHCP6_SEND_RELEASE, -+ GRUB_EFI_DHCP6_SEND_RENEW, -+ GRUB_EFI_DHCP6_SEND_REBIND -+}; -+ -+typedef enum grub_efi_dhcp6_event grub_efi_dhcp6_event_t; -+ -+struct grub_efi_dhcp6_packet_option { -+ grub_efi_uint16_t op_code; -+ grub_efi_uint16_t op_len; -+ grub_efi_uint8_t data[1]; -+} GRUB_PACKED; -+ -+typedef struct grub_efi_dhcp6_packet_option grub_efi_dhcp6_packet_option_t; -+ -+struct grub_efi_dhcp6_header { -+ grub_efi_uint32_t transaction_id:24; -+ grub_efi_uint32_t message_type:8; -+} GRUB_PACKED; -+ -+typedef struct grub_efi_dhcp6_header grub_efi_dhcp6_header_t; -+ -+struct grub_efi_dhcp6_packet { -+ grub_efi_uint32_t size; -+ grub_efi_uint32_t length; -+ struct { -+ grub_efi_dhcp6_header_t header; -+ grub_efi_uint8_t option[1]; -+ } dhcp6; -+} GRUB_PACKED; -+ -+typedef struct grub_efi_dhcp6_packet grub_efi_dhcp6_packet_t; -+ -+struct grub_efi_dhcp6_ia_address { -+ grub_efi_ipv6_address_t ip_address; -+ grub_efi_uint32_t preferred_lifetime; -+ grub_efi_uint32_t valid_lifetime; -+}; -+ -+typedef struct grub_efi_dhcp6_ia_address grub_efi_dhcp6_ia_address_t; -+ -+enum grub_efi_dhcp6_state { -+ GRUB_EFI_DHCP6_INIT, -+ GRUB_EFI_DHCP6_SELECTING, -+ GRUB_EFI_DHCP6_REQUESTING, -+ GRUB_EFI_DHCP6_DECLINING, -+ GRUB_EFI_DHCP6_CONFIRMING, -+ GRUB_EFI_DHCP6_RELEASING, -+ GRUB_EFI_DHCP6_BOUND, -+ GRUB_EFI_DHCP6_RENEWING, -+ GRUB_EFI_DHCP6_REBINDING -+}; -+ -+typedef enum grub_efi_dhcp6_state grub_efi_dhcp6_state_t; -+ -+#define GRUB_EFI_DHCP6_IA_TYPE_NA 3 -+#define GRUB_EFI_DHCP6_IA_TYPE_TA 4 -+ -+struct grub_efi_dhcp6_ia_descriptor { -+ grub_efi_uint16_t type; -+ grub_efi_uint32_t ia_id; -+}; -+ -+typedef struct grub_efi_dhcp6_ia_descriptor grub_efi_dhcp6_ia_descriptor_t; -+ -+struct grub_efi_dhcp6_ia { -+ grub_efi_dhcp6_ia_descriptor_t descriptor; -+ grub_efi_dhcp6_state_t state; -+ grub_efi_dhcp6_packet_t *reply_packet; -+ grub_efi_uint32_t ia_address_count; -+ grub_efi_dhcp6_ia_address_t ia_address[1]; -+}; -+ -+typedef struct grub_efi_dhcp6_ia grub_efi_dhcp6_ia_t; -+ -+struct grub_efi_dhcp6_duid { -+ grub_efi_uint16_t length; -+ grub_efi_uint8_t duid[1]; -+}; -+ -+typedef struct grub_efi_dhcp6_duid grub_efi_dhcp6_duid_t; -+ -+struct grub_efi_dhcp6_mode_data { -+ grub_efi_dhcp6_duid_t *client_id; -+ grub_efi_dhcp6_ia_t *ia; -+}; -+ -+typedef struct grub_efi_dhcp6_mode_data grub_efi_dhcp6_mode_data_t; -+ -+struct grub_efi_dhcp6_config_data { -+ grub_efi_status_t (*dhcp6_callback) (grub_efi_dhcp6_protocol_t this, -+ void *context, -+ grub_efi_dhcp6_state_t current_state, -+ grub_efi_dhcp6_event_t dhcp6_event, -+ grub_efi_dhcp6_packet_t *packet, -+ grub_efi_dhcp6_packet_t **new_packet); -+ void *callback_context; -+ grub_efi_uint32_t option_count; -+ grub_efi_dhcp6_packet_option_t **option_list; -+ grub_efi_dhcp6_ia_descriptor_t ia_descriptor; -+ grub_efi_event_t ia_info_event; -+ grub_efi_boolean_t reconfigure_accept; -+ grub_efi_boolean_t rapid_commit; -+ grub_efi_dhcp6_retransmission_t *solicit_retransmission; -+}; -+ -+typedef struct grub_efi_dhcp6_config_data grub_efi_dhcp6_config_data_t; -+ -+struct grub_efi_dhcp6_protocol { -+ grub_efi_status_t (*get_mode_data) (grub_efi_dhcp6_protocol_t *this, -+ grub_efi_dhcp6_mode_data_t *dhcp6_mode_data, -+ grub_efi_dhcp6_config_data_t *dhcp6_config_data); -+ grub_efi_status_t (*configure) (grub_efi_dhcp6_protocol_t *this, -+ grub_efi_dhcp6_config_data_t *dhcp6_cfg_data); -+ grub_efi_status_t (*start) (grub_efi_dhcp6_protocol_t *this); -+ grub_efi_status_t (*info_request) (grub_efi_dhcp6_protocol_t *this, -+ grub_efi_boolean_t send_client_id, -+ grub_efi_dhcp6_packet_option_t *option_request, -+ grub_efi_uint32_t option_count, -+ grub_efi_dhcp6_packet_option_t *option_list[], -+ grub_efi_dhcp6_retransmission_t *retransmission, -+ grub_efi_event_t timeout_event, -+ grub_efi_status_t (*reply_callback) (grub_efi_dhcp6_protocol_t *this, -+ void *context, -+ grub_efi_dhcp6_packet_t *packet), -+ void *callback_context); -+ grub_efi_status_t (*renew_rebind) (grub_efi_dhcp6_protocol_t *this, -+ grub_efi_boolean_t rebind_request); -+ grub_efi_status_t (*decline) (grub_efi_dhcp6_protocol_t *this, -+ grub_efi_uint32_t address_count, -+ grub_efi_ipv6_address_t *addresses); -+ grub_efi_status_t (*release) (grub_efi_dhcp6_protocol_t *this, -+ grub_efi_uint32_t address_count, -+ grub_efi_ipv6_address_t *addresses); -+ grub_efi_status_t (*stop) (grub_efi_dhcp6_protocol_t *this); -+ grub_efi_status_t (*parse) (grub_efi_dhcp6_protocol_t *this, -+ grub_efi_dhcp6_packet_t *packet, -+ grub_efi_uint32_t *option_count, -+ grub_efi_dhcp6_packet_option_t *packet_option_list[]); -+}; -+ -+#endif /* ! GRUB_EFI_DHCP_HEADER */ -diff --git a/include/grub/efi/http.h b/include/grub/efi/http.h -new file mode 100644 -index 00000000000..c5e9a89f505 ---- /dev/null -+++ b/include/grub/efi/http.h -@@ -0,0 +1,215 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_EFI_HTTP_HEADER -+#define GRUB_EFI_HTTP_HEADER 1 -+ -+#include -+#include -+#include -+ -+#define GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \ -+ { 0xbdc8e6af, 0xd9bc, 0x4379, \ -+ { 0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \ -+ } -+ -+#define GRUB_EFI_HTTP_PROTOCOL_GUID \ -+ { 0x7A59B29B, 0x910B, 0x4171, \ -+ { 0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B } \ -+ } -+ -+#define EFIHTTP_WAIT_TIME 10000 // 10000ms = 10s -+#define EFIHTTP_RX_BUF_LEN 10240 -+ -+//****************************************** -+// Protocol Interface Structure -+//****************************************** -+struct grub_efi_http; -+ -+//****************************************** -+// EFI_HTTP_VERSION -+//****************************************** -+typedef enum { -+ GRUB_EFI_HTTPVERSION10, -+ GRUB_EFI_HTTPVERSION11, -+ GRUB_EFI_HTTPVERSIONUNSUPPORTED -+} grub_efi_http_version_t; -+ -+//****************************************** -+// EFI_HTTPv4_ACCESS_POINT -+//****************************************** -+typedef struct { -+ grub_efi_boolean_t use_default_address; -+ grub_efi_ipv4_address_t local_address; -+ grub_efi_ipv4_address_t local_subnet; -+ grub_efi_uint16_t local_port; -+} grub_efi_httpv4_access_point_t; -+ -+//****************************************** -+// EFI_HTTPv6_ACCESS_POINT -+//****************************************** -+typedef struct { -+ grub_efi_ipv6_address_t local_address; -+ grub_efi_uint16_t local_port; -+} grub_efi_httpv6_access_point_t; -+ -+//****************************************** -+// EFI_HTTP_CONFIG_DATA -+//****************************************** -+typedef struct { -+ grub_efi_http_version_t http_version; -+ grub_efi_uint32_t timeout_millisec; -+ grub_efi_boolean_t local_address_is_ipv6; -+ union { -+ grub_efi_httpv4_access_point_t *ipv4_node; -+ grub_efi_httpv6_access_point_t *ipv6_node; -+ } access_point; -+} grub_efi_http_config_data_t; -+ -+//****************************************** -+// EFI_HTTP_METHOD -+//****************************************** -+typedef enum { -+ GRUB_EFI_HTTPMETHODGET, -+ GRUB_EFI_HTTPMETHODPOST, -+ GRUB_EFI_HTTPMETHODPATCH, -+ GRUB_EFI_HTTPMETHODOPTIONS, -+ GRUB_EFI_HTTPMETHODCONNECT, -+ GRUB_EFI_HTTPMETHODHEAD, -+ GRUB_EFI_HTTPMETHODPUT, -+ GRUB_EFI_HTTPMETHODDELETE, -+ GRUB_EFI_HTTPMETHODTRACE, -+} grub_efi_http_method_t; -+ -+//****************************************** -+// EFI_HTTP_REQUEST_DATA -+//****************************************** -+typedef struct { -+ grub_efi_http_method_t method; -+ grub_efi_char16_t *url; -+} grub_efi_http_request_data_t; -+ -+typedef enum { -+ GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS = 0, -+ GRUB_EFI_HTTP_STATUS_100_CONTINUE, -+ GRUB_EFI_HTTP_STATUS_101_SWITCHING_PROTOCOLS, -+ GRUB_EFI_HTTP_STATUS_200_OK, -+ GRUB_EFI_HTTP_STATUS_201_CREATED, -+ GRUB_EFI_HTTP_STATUS_202_ACCEPTED, -+ GRUB_EFI_HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION, -+ GRUB_EFI_HTTP_STATUS_204_NO_CONTENT, -+ GRUB_EFI_HTTP_STATUS_205_RESET_CONTENT, -+ GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT, -+ GRUB_EFI_HTTP_STATUS_300_MULTIPLE_CHIOCES, -+ GRUB_EFI_HTTP_STATUS_301_MOVED_PERMANENTLY, -+ GRUB_EFI_HTTP_STATUS_302_FOUND, -+ GRUB_EFI_HTTP_STATUS_303_SEE_OTHER, -+ GRUB_EFI_HTTP_STATUS_304_NOT_MODIFIED, -+ GRUB_EFI_HTTP_STATUS_305_USE_PROXY, -+ GRUB_EFI_HTTP_STATUS_307_TEMPORARY_REDIRECT, -+ GRUB_EFI_HTTP_STATUS_400_BAD_REQUEST, -+ GRUB_EFI_HTTP_STATUS_401_UNAUTHORIZED, -+ GRUB_EFI_HTTP_STATUS_402_PAYMENT_REQUIRED, -+ GRUB_EFI_HTTP_STATUS_403_FORBIDDEN, -+ GRUB_EFI_HTTP_STATUS_404_NOT_FOUND, -+ GRUB_EFI_HTTP_STATUS_405_METHOD_NOT_ALLOWED, -+ GRUB_EFI_HTTP_STATUS_406_NOT_ACCEPTABLE, -+ GRUB_EFI_HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED, -+ GRUB_EFI_HTTP_STATUS_408_REQUEST_TIME_OUT, -+ GRUB_EFI_HTTP_STATUS_409_CONFLICT, -+ GRUB_EFI_HTTP_STATUS_410_GONE, -+ GRUB_EFI_HTTP_STATUS_411_LENGTH_REQUIRED, -+ GRUB_EFI_HTTP_STATUS_412_PRECONDITION_FAILED, -+ GRUB_EFI_HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE, -+ GRUB_EFI_HTTP_STATUS_414_REQUEST_URI_TOO_LARGE, -+ GRUB_EFI_HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE, -+ GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED, -+ GRUB_EFI_HTTP_STATUS_417_EXPECTATION_FAILED, -+ GRUB_EFI_HTTP_STATUS_500_INTERNAL_SERVER_ERROR, -+ GRUB_EFI_HTTP_STATUS_501_NOT_IMPLEMENTED, -+ GRUB_EFI_HTTP_STATUS_502_BAD_GATEWAY, -+ GRUB_EFI_HTTP_STATUS_503_SERVICE_UNAVAILABLE, -+ GRUB_EFI_HTTP_STATUS_504_GATEWAY_TIME_OUT, -+ GRUB_EFI_HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED -+} grub_efi_http_status_code_t; -+ -+//****************************************** -+// EFI_HTTP_RESPONSE_DATA -+//****************************************** -+typedef struct { -+ grub_efi_http_status_code_t status_code; -+} grub_efi_http_response_data_t; -+ -+//****************************************** -+// EFI_HTTP_HEADER -+//****************************************** -+typedef struct { -+ grub_efi_char8_t *field_name; -+ grub_efi_char8_t *field_value; -+} grub_efi_http_header_t; -+ -+//****************************************** -+// EFI_HTTP_MESSAGE -+//****************************************** -+typedef struct { -+ union { -+ grub_efi_http_request_data_t *request; -+ grub_efi_http_response_data_t *response; -+ } data; -+ grub_efi_uint32_t header_count; -+ grub_efi_http_header_t *headers; -+ grub_efi_uint32_t body_length; -+ void *body; -+} grub_efi_http_message_t; -+ -+//****************************************** -+// EFI_HTTP_TOKEN -+//****************************************** -+typedef struct { -+ grub_efi_event_t event; -+ grub_efi_status_t status; -+ grub_efi_http_message_t *message; -+} grub_efi_http_token_t; -+ -+struct grub_efi_http { -+ grub_efi_status_t -+ (*get_mode_data) (struct grub_efi_http *this, -+ grub_efi_http_config_data_t *http_config_data); -+ -+ grub_efi_status_t -+ (*configure) (struct grub_efi_http *this, -+ grub_efi_http_config_data_t *http_config_data); -+ -+ grub_efi_status_t -+ (*request) (struct grub_efi_http *this, -+ grub_efi_http_token_t *token); -+ -+ grub_efi_status_t -+ (*cancel) (struct grub_efi_http *this, -+ grub_efi_http_token_t *token); -+ -+ grub_efi_status_t -+ (*response) (struct grub_efi_http *this, -+ grub_efi_http_token_t *token); -+ -+ grub_efi_status_t -+ (*poll) (struct grub_efi_http *this); -+}; -+typedef struct grub_efi_http grub_efi_http_t; -+ -+#endif /* !GRUB_EFI_HTTP_HEADER */ -diff --git a/include/grub/net/efi.h b/include/grub/net/efi.h -new file mode 100644 -index 00000000000..de90d223e8e ---- /dev/null -+++ b/include/grub/net/efi.h -@@ -0,0 +1,144 @@ -+#ifndef GRUB_NET_EFI_HEADER -+#define GRUB_NET_EFI_HEADER 1 -+ -+#include -+#include -+#include -+#include -+ -+typedef struct grub_efi_net_interface grub_efi_net_interface_t; -+typedef struct grub_efi_net_ip_config grub_efi_net_ip_config_t; -+typedef union grub_efi_net_ip_address grub_efi_net_ip_address_t; -+typedef struct grub_efi_net_ip_manual_address grub_efi_net_ip_manual_address_t; -+ -+struct grub_efi_net_interface -+{ -+ char *name; -+ int prefer_ip6; -+ struct grub_efi_net_device *dev; -+ struct grub_efi_net_io *io; -+ grub_efi_net_ip_config_t *ip_config; -+ int io_type; -+ struct grub_efi_net_interface *next; -+}; -+ -+#define efi_net_interface_get_hw_address(inf) inf->ip_config->get_hw_address (inf->dev) -+#define efi_net_interface_get_address(inf) inf->ip_config->get_address (inf->dev) -+#define efi_net_interface_get_route_table(inf) inf->ip_config->get_route_table (inf->dev) -+#define efi_net_interface_set_address(inf, addr, with_subnet) inf->ip_config->set_address (inf->dev, addr, with_subnet) -+#define efi_net_interface_set_gateway(inf, addr) inf->ip_config->set_gateway (inf->dev, addr) -+#define efi_net_interface_set_dns(inf, addr) inf->ip_config->set_dns (inf->dev, addr) -+ -+struct grub_efi_net_ip_config -+{ -+ char * (*get_hw_address) (struct grub_efi_net_device *dev); -+ char * (*get_address) (struct grub_efi_net_device *dev); -+ char ** (*get_route_table) (struct grub_efi_net_device *dev); -+ grub_efi_net_interface_t * (*best_interface) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); -+ int (*set_address) (struct grub_efi_net_device *dev, grub_efi_net_ip_manual_address_t *net_ip, int with_subnet); -+ int (*set_gateway) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); -+ int (*set_dns) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *dns); -+}; -+ -+union grub_efi_net_ip_address -+{ -+ grub_efi_ipv4_address_t ip4; -+ grub_efi_ipv6_address_t ip6; -+}; -+ -+struct grub_efi_net_ip_manual_address -+{ -+ int is_ip6; -+ union -+ { -+ grub_efi_ip4_config2_manual_address_t ip4; -+ grub_efi_ip6_config_manual_address_t ip6; -+ }; -+}; -+ -+struct grub_efi_net_device -+{ -+ grub_efi_handle_t handle; -+ grub_efi_ip4_config2_protocol_t *ip4_config; -+ grub_efi_ip6_config_protocol_t *ip6_config; -+ grub_efi_handle_t http_handle; -+ grub_efi_http_t *http; -+ grub_efi_handle_t ip4_pxe_handle; -+ grub_efi_pxe_t *ip4_pxe; -+ grub_efi_handle_t ip6_pxe_handle; -+ grub_efi_pxe_t *ip6_pxe; -+ grub_efi_handle_t dhcp4_handle; -+ grub_efi_dhcp4_protocol_t *dhcp4; -+ grub_efi_handle_t dhcp6_handle; -+ grub_efi_dhcp6_protocol_t *dhcp6; -+ char *card_name; -+ grub_efi_net_interface_t *net_interfaces; -+ struct grub_efi_net_device *next; -+}; -+ -+struct grub_efi_net_io -+{ -+ void (*configure) (struct grub_efi_net_device *dev, int prefer_ip6); -+ grub_err_t (*open) (struct grub_efi_net_device *dev, -+ int prefer_ip6, -+ grub_file_t file, -+ const char *filename, -+ int type); -+ grub_ssize_t (*read) (struct grub_efi_net_device *dev, -+ int prefer_ip6, -+ grub_file_t file, -+ char *buf, -+ grub_size_t len); -+ grub_err_t (*close) (struct grub_efi_net_device *dev, -+ int prefer_ip6, -+ grub_file_t file); -+}; -+ -+extern struct grub_efi_net_device *net_devices; -+ -+extern struct grub_efi_net_io io_http; -+extern struct grub_efi_net_io io_pxe; -+ -+extern grub_efi_net_ip_config_t *efi_net_ip4_config; -+extern grub_efi_net_ip_config_t *efi_net_ip6_config; -+ -+char * -+grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address); -+ -+char * -+grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address); -+ -+char * -+grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address); -+ -+int -+grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest); -+ -+int -+grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest); -+ -+char * -+grub_efi_ip6_interface_name (struct grub_efi_net_device *dev); -+ -+char * -+grub_efi_ip4_interface_name (struct grub_efi_net_device *dev); -+ -+grub_efi_net_interface_t * -+grub_efi_net_create_interface (struct grub_efi_net_device *dev, -+ const char *interface_name, -+ grub_efi_net_ip_manual_address_t *net_ip, -+ int has_subnet); -+ -+int grub_efi_net_fs_init (void); -+void grub_efi_net_fs_fini (void); -+int grub_efi_net_boot_from_https (void); -+int grub_efi_net_boot_from_opa (void); -+ -+extern grub_command_func_t grub_efi_net_list_routes; -+extern grub_command_func_t grub_efi_net_list_cards; -+extern grub_command_func_t grub_efi_net_list_addrs; -+extern grub_command_func_t grub_efi_net_add_addr; -+extern grub_command_func_t grub_efi_net_bootp; -+extern grub_command_func_t grub_efi_net_bootp6; -+ -+#endif /* ! GRUB_NET_EFI_HEADER */ diff --git a/SOURCES/0096-AUDIT-0-http-boot-tracker-bug.patch b/SOURCES/0096-AUDIT-0-http-boot-tracker-bug.patch deleted file mode 100644 index ef3e67b..0000000 --- a/SOURCES/0096-AUDIT-0-http-boot-tracker-bug.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Krahmer -Date: Tue, 28 Nov 2017 17:24:38 +0800 -Subject: [PATCH] AUDIT-0: http boot tracker bug - -Fixing a memory leak in case of error, and a integer overflow, leading to a -heap overflow due to overly large chunk sizes. - -We need to check against some maximum value, otherwise values like 0xffffffff -will eventually lead in the allocation functions to small sized buffers, since -the len is rounded up to the next reasonable alignment. The following memcpy -will then smash the heap, leading to RCE. - -This is no big issue for pure http boot, since its going to execute an -untrusted kernel anyway, but it will break trusted boot scenarios, where only -signed code is allowed to be executed. - -Signed-off-by: Michael Chang ---- - grub-core/net/efi/net.c | 4 +++- - grub-core/net/http.c | 5 ++++- - 2 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c -index 86bce6535d3..4bb308026ce 100644 ---- a/grub-core/net/efi/net.c -+++ b/grub-core/net/efi/net.c -@@ -645,8 +645,10 @@ grub_efihttp_chunk_read (grub_file_t file, char *buf, - - rd = efi_net_interface (read, file, chunk, sz); - -- if (rd <= 0) -+ if (rd <= 0) { -+ grub_free (chunk); - return rd; -+ } - - if (buf) - { -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 12a2632ea55..b52b558d631 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -31,7 +31,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); - - enum - { -- HTTP_PORT = 80 -+ HTTP_PORT = 80, -+ HTTP_MAX_CHUNK_SIZE = 0x80000000 - }; - - -@@ -78,6 +79,8 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) - if (data->in_chunk_len == 2) - { - data->chunk_rem = grub_strtoul (ptr, 0, 16); -+ if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE) -+ return GRUB_ERR_NET_PACKET_TOO_BIG; - grub_errno = GRUB_ERR_NONE; - if (data->chunk_rem == 0) - { diff --git a/SOURCES/0096-Add-more-dprintf-and-nerf-dprintf-in-script.c.patch b/SOURCES/0096-Add-more-dprintf-and-nerf-dprintf-in-script.c.patch new file mode 100644 index 0000000..72c8d30 --- /dev/null +++ b/SOURCES/0096-Add-more-dprintf-and-nerf-dprintf-in-script.c.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 11 Sep 2018 15:58:29 -0400 +Subject: [PATCH] Add more dprintf, and nerf dprintf in script.c + +Signed-off-by: Peter Jones +--- + grub-core/disk/diskfilter.c | 3 +++ + grub-core/disk/efi/efidisk.c | 1 + + grub-core/kern/device.c | 1 + + grub-core/script/script.c | 5 +++++ + 4 files changed, 10 insertions(+) + +diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c +index 0320115662..7cdffe3ebd 100644 +--- a/grub-core/disk/diskfilter.c ++++ b/grub-core/disk/diskfilter.c +@@ -188,6 +188,8 @@ scan_disk (const char *name, int accept_diskfilter) + grub_disk_t disk; + static int scan_depth = 0; + ++ grub_dprintf ("diskfilter", "scanning %s\n", name); ++ + if (!accept_diskfilter && is_valid_diskfilter_name (name)) + return 0; + +@@ -1212,6 +1214,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, + the same. */ + if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size) + return GRUB_ERR_NONE; ++ grub_dprintf ("diskfilter", "checking %s\n", disk->name); + pv->disk = grub_disk_open (disk->name); + if (!pv->disk) + return grub_errno; +diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c +index f077b5f553..fe8ba6e6c9 100644 +--- a/grub-core/disk/efi/efidisk.c ++++ b/grub-core/disk/efi/efidisk.c +@@ -855,6 +855,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) + return 0; + } + ++ grub_dprintf ("efidisk", "getting disk for %s\n", device_name); + parent = grub_disk_open (device_name); + grub_free (dup_dp); + +diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c +index 73b8ecc0c0..f58b58c89d 100644 +--- a/grub-core/kern/device.c ++++ b/grub-core/kern/device.c +@@ -34,6 +34,7 @@ grub_device_open (const char *name) + { + grub_device_t dev = 0; + ++ grub_dprintf ("device", "opening device %s\n", name); + if (! name) + { + name = grub_env_get ("root"); +diff --git a/grub-core/script/script.c b/grub-core/script/script.c +index ec4d4337c6..844e8343ca 100644 +--- a/grub-core/script/script.c ++++ b/grub-core/script/script.c +@@ -22,6 +22,11 @@ + #include + #include + ++#ifdef grub_dprintf ++#undef grub_dprintf ++#endif ++#define grub_dprintf(no, fmt, ...) ++ + /* It is not possible to deallocate the memory when a syntax error was + found. Because of that it is required to keep track of all memory + allocations. The memory is freed in case of an error, or assigned diff --git a/SOURCES/0097-arm-arm64-loader-Better-memory-allocation-and-error-.patch b/SOURCES/0097-arm-arm64-loader-Better-memory-allocation-and-error-.patch new file mode 100644 index 0000000..57d937c --- /dev/null +++ b/SOURCES/0097-arm-arm64-loader-Better-memory-allocation-and-error-.patch @@ -0,0 +1,279 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 11 Jul 2019 14:38:57 +0200 +Subject: [PATCH] arm/arm64 loader: Better memory allocation and error + messages. + +On mustang, our memory map looks like: + +Type Physical start - end #Pages Size Attributes +reserved 0000004000000000-00000040001fffff 00000200 2MiB UC WC WT WB +conv-mem 0000004000200000-0000004393ffffff 00393e00 14654MiB UC WC WT WB +ldr-code 0000004394000000-00000043f7ffffff 00064000 1600MiB UC WC WT WB +BS-data 00000043f8000000-00000043f801ffff 00000020 128KiB UC WC WT WB +conv-mem 00000043f8020000-00000043fa15bfff 0000213c 34032KiB UC WC WT WB +ldr-code 00000043fa15c000-00000043fa2a1fff 00000146 1304KiB UC WC WT WB +ldr-data 00000043fa2a2000-00000043fa3e8fff 00000147 1308KiB UC WC WT WB +conv-mem 00000043fa3e9000-00000043fa3e9fff 00000001 4KiB UC WC WT WB +ldr-data 00000043fa3ea000-00000043fa3eafff 00000001 4KiB UC WC WT WB +ldr-code 00000043fa3eb000-00000043fa4affff 000000c5 788KiB UC WC WT WB +BS-code 00000043fa4b0000-00000043fa59ffff 000000f0 960KiB UC WC WT WB +RT-code 00000043fa5a0000-00000043fa5affff 00000010 64KiB RT UC WC WT WB +RT-data 00000043fa5b0000-00000043fa5bffff 00000010 64KiB RT UC WC WT WB +RT-code 00000043fa5c0000-00000043fa5cffff 00000010 64KiB RT UC WC WT WB +ldr-data 00000043fa5d0000-00000043fa5d0fff 00000001 4KiB UC WC WT WB +BS-code 00000043fa5d1000-00000043fa5ddfff 0000000d 52KiB UC WC WT WB +reserved 00000043fa5de000-00000043fa60ffff 00000032 200KiB UC WC WT WB +ACPI-rec 00000043fa610000-00000043fa6affff 000000a0 640KiB UC WC WT WB +ACPI-nvs 00000043fa6b0000-00000043fa6bffff 00000010 64KiB UC WC WT WB +ACPI-rec 00000043fa6c0000-00000043fa70ffff 00000050 320KiB UC WC WT WB +RT-code 00000043fa710000-00000043fa72ffff 00000020 128KiB RT UC WC WT WB +RT-data 00000043fa730000-00000043fa78ffff 00000060 384KiB RT UC WC WT WB +RT-code 00000043fa790000-00000043fa79ffff 00000010 64KiB RT UC WC WT WB +RT-data 00000043fa7a0000-00000043fa99ffff 00000200 2MiB RT UC WC WT WB +RT-code 00000043fa9a0000-00000043fa9affff 00000010 64KiB RT UC WC WT WB +RT-data 00000043fa9b0000-00000043fa9cffff 00000020 128KiB RT UC WC WT WB +BS-code 00000043fa9d0000-00000043fa9d9fff 0000000a 40KiB UC WC WT WB +reserved 00000043fa9da000-00000043fa9dbfff 00000002 8KiB UC WC WT WB +conv-mem 00000043fa9dc000-00000043fc29dfff 000018c2 25352KiB UC WC WT WB +BS-data 00000043fc29e000-00000043fc78afff 000004ed 5044KiB UC WC WT WB +conv-mem 00000043fc78b000-00000043fca01fff 00000277 2524KiB UC WC WT WB +BS-data 00000043fca02000-00000043fcea3fff 000004a2 4744KiB UC WC WT WB +conv-mem 00000043fcea4000-00000043fcea4fff 00000001 4KiB UC WC WT WB +BS-data 00000043fcea5000-00000043fd192fff 000002ee 3000KiB UC WC WT WB +conv-mem 00000043fd193000-00000043fd2b0fff 0000011e 1144KiB UC WC WT WB +BS-data 00000043fd2b1000-00000043ff80ffff 0000255f 38268KiB UC WC WT WB +BS-code 00000043ff810000-00000043ff99ffff 00000190 1600KiB UC WC WT WB +RT-code 00000043ff9a0000-00000043ff9affff 00000010 64KiB RT UC WC WT WB +conv-mem 00000043ff9b0000-00000043ff9bffff 00000010 64KiB UC WC WT WB +RT-data 00000043ff9c0000-00000043ff9effff 00000030 192KiB RT UC WC WT WB +conv-mem 00000043ff9f0000-00000043ffa05fff 00000016 88KiB UC WC WT WB +BS-data 00000043ffa06000-00000043ffffffff 000005fa 6120KiB UC WC WT WB +MMIO 0000000010510000-0000000010510fff 00000001 4KiB RT +MMIO 0000000010548000-0000000010549fff 00000002 8KiB RT +MMIO 0000000017000000-0000000017001fff 00000002 8KiB RT +MMIO 000000001c025000-000000001c025fff 00000001 4KiB RT + +This patch adds a requirement when we're trying to find the base of ram, that +the memory we choose is actually /allocatable/ conventional memory, not merely +write-combining. On this machine that means we wind up with an allocation +around 0x4392XXXXXX, which is a reasonable address. + +This also changes grub_efi_allocate_pages_real() so that if 0 is allocated, it +tries to allocate again starting with the same max address it did the first +time, rather than interposing GRUB_EFI_MAX_USABLE_ADDRESS there, so that any +per-platform constraints on its given address are maintained. + +Signed-off-by: Peter Jones +--- + grub-core/kern/efi/mm.c | 33 +++++++++++++++----- + grub-core/loader/arm64/linux.c | 68 +++++++++++++++++++++++++++++++----------- + 2 files changed, 76 insertions(+), 25 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index f6aef0ef64..85ad4b4494 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -154,6 +154,7 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + { + grub_efi_status_t status; + grub_efi_boot_services_t *b; ++ grub_efi_physical_address_t ret = address; + + /* Limit the memory access to less than 4GB for 32-bit platforms. */ + if (address > GRUB_EFI_MAX_USABLE_ADDRESS) +@@ -170,19 +171,22 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + } + + b = grub_efi_system_table->boot_services; +- status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); ++ status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); + if (status != GRUB_EFI_SUCCESS) + { ++ grub_dprintf ("efi", ++ "allocate_pages(%d, %d, 0x%0lx, 0x%016lx) = 0x%016lx\n", ++ alloctype, memtype, pages, address, status); + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + return NULL; + } + +- if (address == 0) ++ if (ret == 0) + { + /* Uggh, the address 0 was allocated... This is too annoying, + so reallocate another one. */ +- address = GRUB_EFI_MAX_USABLE_ADDRESS; +- status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); ++ ret = address; ++ status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); + grub_efi_free_pages (0, pages); + if (status != GRUB_EFI_SUCCESS) + { +@@ -191,9 +195,9 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + } + } + +- grub_efi_store_alloc (address, pages); ++ grub_efi_store_alloc (ret, pages); + +- return (void *) ((grub_addr_t) address); ++ return (void *) ((grub_addr_t) ret); + } + + void * +@@ -713,8 +717,21 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) + for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS; + (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) +- if (desc->attribute & GRUB_EFI_MEMORY_WB) +- *base_addr = grub_min (*base_addr, desc->physical_start); ++ { ++ if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY && ++ (desc->attribute & GRUB_EFI_MEMORY_WB)) ++ { ++ *base_addr = grub_min (*base_addr, desc->physical_start); ++ grub_dprintf ("efi", "setting base_addr=0x%016lx\n", *base_addr); ++ } ++ else ++ { ++ grub_dprintf ("efi", "ignoring address 0x%016lx\n", desc->physical_start); ++ } ++ } ++ ++ if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS) ++ grub_dprintf ("efi", "base_addr 0x%016lx is probably wrong.\n", *base_addr); + + grub_free(memory_map); + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 04994d5c67..70a0075ec5 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -71,20 +71,25 @@ finalize_params_linux (void) + { + grub_efi_loaded_image_t *loaded_image = NULL; + int node, retval, len; +- ++ grub_err_t err = GRUB_ERR_NONE; + void *fdt; + + fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); +- + if (!fdt) +- goto failure; ++ { ++ err = grub_error(GRUB_ERR_BAD_OS, "failed to load FDT"); ++ goto failure; ++ } + + node = grub_fdt_find_subnode (fdt, 0, "chosen"); + if (node < 0) + node = grub_fdt_add_subnode (fdt, 0, "chosen"); + + if (node < 1) +- goto failure; ++ { ++ err = grub_error(grub_errno, "failed to load chosen fdt node."); ++ goto failure; ++ } + + /* Set initrd info */ + if (initrd_start && initrd_end > initrd_start) +@@ -95,15 +100,26 @@ finalize_params_linux (void) + retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", + initrd_start); + if (retval) +- goto failure; ++ { ++ err = grub_error(retval, "Failed to set linux,initrd-start property"); ++ goto failure; ++ } ++ + retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", + initrd_end); + if (retval) +- goto failure; ++ { ++ err = grub_error(retval, "Failed to set linux,initrd-end property"); ++ goto failure; ++ } + } + +- if (grub_fdt_install() != GRUB_ERR_NONE) +- goto failure; ++ retval = grub_fdt_install(); ++ if (retval != GRUB_ERR_NONE) ++ { ++ err = grub_error(retval, "Failed to install fdt"); ++ goto failure; ++ } + + grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n", + fdt); +@@ -111,14 +127,20 @@ finalize_params_linux (void) + /* Convert command line to UCS-2 */ + loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (!loaded_image) +- goto failure; ++ { ++ err = grub_error(grub_errno, "Failed to install fdt"); ++ goto failure; ++ } + + loaded_image->load_options_size = len = + (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); + loaded_image->load_options = + grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); + if (!loaded_image->load_options) +- return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); ++ { ++ err = grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); ++ goto failure; ++ } + + loaded_image->load_options_size = + 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, +@@ -128,7 +150,7 @@ finalize_params_linux (void) + + failure: + grub_fdt_unload(); +- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); ++ return err; + } + + static void +@@ -212,16 +234,28 @@ grub_linux_unload (void) + static void * + allocate_initrd_mem (int initrd_pages) + { +- grub_addr_t max_addr; ++ grub_addr_t max_addr = 0; ++ grub_err_t err; ++ void *ret; + +- if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE) +- return NULL; ++ err = grub_efi_get_ram_base (&max_addr); ++ if (err != GRUB_ERR_NONE) ++ { ++ grub_error (err, "grub_efi_get_ram_base() failed"); ++ return NULL; ++ } ++ ++ grub_dprintf ("linux", "max_addr: 0x%016lx, INITRD_MAX_ADDRESS_OFFSET: 0x%016llx\n", ++ max_addr, INITRD_MAX_ADDRESS_OFFSET); + + max_addr += INITRD_MAX_ADDRESS_OFFSET - 1; ++ grub_dprintf ("linux", "calling grub_efi_allocate_pages_real (0x%016lx, 0x%08x, EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA)", max_addr, initrd_pages); + +- return grub_efi_allocate_pages_real (max_addr, initrd_pages, +- GRUB_EFI_ALLOCATE_MAX_ADDRESS, +- GRUB_EFI_LOADER_DATA); ++ ret = grub_efi_allocate_pages_real (max_addr, initrd_pages, ++ GRUB_EFI_ALLOCATE_MAX_ADDRESS, ++ GRUB_EFI_LOADER_DATA); ++ grub_dprintf ("linux", "got 0x%016llx\n", (unsigned long long)ret); ++ return ret; + } + + static grub_err_t diff --git a/SOURCES/0097-grub-editenv-Add-incr-command-to-increment-integer-v.patch b/SOURCES/0097-grub-editenv-Add-incr-command-to-increment-integer-v.patch deleted file mode 100644 index f8de42a..0000000 --- a/SOURCES/0097-grub-editenv-Add-incr-command-to-increment-integer-v.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Mon, 4 Jun 2018 19:49:47 +0200 -Subject: [PATCH] grub-editenv: Add "incr" command to increment integer value - env. variables - -To be able to automatically detect if the last boot was successful, -We want to keep count of succesful / failed boots in some integer -environment variable. - -This commit adds a grub-editenvt "incr" command to increment such -integer value env. variables by 1 for use from various boot scripts. - -Signed-off-by: Hans de Goede ---- - util/grub-editenv.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 50 insertions(+) - -diff --git a/util/grub-editenv.c b/util/grub-editenv.c -index db6f187cc63..948eec8a114 100644 ---- a/util/grub-editenv.c -+++ b/util/grub-editenv.c -@@ -53,6 +53,9 @@ static struct argp_option options[] = { - /* TRANSLATORS: "unset" is a keyword. It's a summary of "unset" subcommand. */ - {N_("unset [NAME ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE, - N_("Delete variables."), 0}, -+ /* TRANSLATORS: "incr" is a keyword. It's a summary of "incr" subcommand. */ -+ {N_("incr [NAME ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE, -+ N_("Increase value of integer variables."), 0}, - - {0, 0, 0, OPTION_DOC, N_("Options:"), -1}, - {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, -@@ -253,6 +256,51 @@ unset_variables (const char *name, int argc, char *argv[]) - grub_envblk_close (envblk); - } - -+struct get_int_value_params { -+ char *varname; -+ int value; -+}; -+ -+static int -+get_int_value (const char *varname, const char *value, void *hook_data) -+{ -+ struct get_int_value_params *params = hook_data; -+ -+ if (strcmp (varname, params->varname) == 0) { -+ params->value = strtol (value, NULL, 10); -+ return 1; -+ } -+ return 0; -+} -+ -+static void -+incr_variables (const char *name, int argc, char *argv[]) -+{ -+ grub_envblk_t envblk; -+ char buf[16]; -+ -+ envblk = open_envblk_file (name); -+ while (argc) -+ { -+ struct get_int_value_params params = { -+ .varname = argv[0], -+ .value = 0, /* Consider unset variables 0 */ -+ }; -+ -+ grub_envblk_iterate (envblk, ¶ms, get_int_value); -+ snprintf(buf, sizeof(buf), "%d", params.value + 1); -+ -+ if (! grub_envblk_set (envblk, argv[0], buf)) -+ grub_util_error ("%s", _("environment block too small")); -+ -+ argc--; -+ argv++; -+ } -+ -+ write_envblk (name, envblk); -+ grub_envblk_close (envblk); -+} -+ - int - main (int argc, char *argv[]) - { -@@ -292,6 +340,8 @@ main (int argc, char *argv[]) - set_variables (filename, argc - curindex, argv + curindex); - else if (strcmp (command, "unset") == 0) - unset_variables (filename, argc - curindex, argv + curindex); -+ else if (strcmp (command, "incr") == 0) -+ incr_variables (filename, argc - curindex, argv + curindex); - else - { - char *program = xstrdup(program_name); diff --git a/SOURCES/0098-Add-auto-hide-menu-support.patch b/SOURCES/0098-Add-auto-hide-menu-support.patch deleted file mode 100644 index efb76c4..0000000 --- a/SOURCES/0098-Add-auto-hide-menu-support.patch +++ /dev/null @@ -1,189 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Wed, 6 Jun 2018 08:44:11 +0200 -Subject: [PATCH] Add auto-hide menu support - -On single-os systems we do not want to show the menu, unless something -went wrong with the previous boot, in which case the user may need the -menu to debug/fix the problem. - -This commit adds a new grub.d/00_menu_auto_hide file which emits a -config snippet implementing this. I've chosen to do this in a separate -grub.d file because chances of this going upstream are small and this way -it will be easier to rebase. - -Since auto-hiding the menu requires detecting the previous boot was ok, -we get fastboot support (where we don't check for a key at all) for free -so this commit also adds support for this. - -The new config-file code uses the following variables: - -menu_auto_hide Set this to "1" to activate the new auto-hide feature - Set this to "2" to auto-hide the menu even when multiple - operating systems are installed. Note the menu will still - auto show after booting an other os as that won't set - boot_success. -menu_show_once Set this to "1" to force showing the menu once. -boot_success The OS sets this to "1" to indicate a successful boot. -boot_indeterminate The OS increments this integer when rebooting after e.g. - installing updates or a selinux relabel. -fastboot If set to "1" and the conditions for auto-hiding the menu - are met, the menu is not shown and all checks for keypresses - are skipped, booting the default immediately. - -30_os-prober.in changes somewhat inspired by: -https://git.launchpad.net/~ubuntu-core-dev/grub/+git/ubuntu/tree/debian/patches/quick_boot.patch - -Signed-off-by: Hans de Goede ---- -Changes in v2: --Drop shutdown_success tests, there is no meaningful way for systemd to set - this flag (by the time it knows all filesystems are unmounted or read-only --Drop fwsetup_once support, systemd already supports booting directly into - the fwsetup by doing "systemctl reboot --firmware" ---- - Makefile.util.def | 6 +++++ - util/grub.d/01_menu_auto_hide.in | 48 ++++++++++++++++++++++++++++++++++++++++ - util/grub.d/30_os-prober.in | 18 +++++++++++++++ - 3 files changed, 72 insertions(+) - create mode 100644 util/grub.d/01_menu_auto_hide.in - -diff --git a/Makefile.util.def b/Makefile.util.def -index 41906486a71..04551e095bd 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -458,6 +458,12 @@ script = { - installdir = grubconf; - }; - -+script = { -+ name = '01_menu_auto_hide'; -+ common = util/grub.d/01_menu_auto_hide.in; -+ installdir = grubconf; -+}; -+ - script = { - name = '01_users'; - common = util/grub.d/01_users.in; -diff --git a/util/grub.d/01_menu_auto_hide.in b/util/grub.d/01_menu_auto_hide.in -new file mode 100644 -index 00000000000..ad175870a54 ---- /dev/null -+++ b/util/grub.d/01_menu_auto_hide.in -@@ -0,0 +1,48 @@ -+#! /bin/sh -+ -+# Disable / skip generating menu-auto-hide config parts on serial terminals -+for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do -+ case "$x" in -+ serial*) -+ exit 0 -+ ;; -+ esac -+done -+ -+cat << EOF -+if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then -+ set last_boot_ok=1 -+else -+ set last_boot_ok=0 -+fi -+ -+# Reset boot_indeterminate after a successful boot -+if [ "\${boot_success}" = "1" ] ; then -+ set boot_indeterminate=0 -+# Avoid boot_indeterminate causing the menu to be hidden more then once -+elif [ "\${boot_indeterminate}" = "1" ]; then -+ set boot_indeterminate=2 -+fi -+set boot_success=0 -+save_env boot_success boot_indeterminate -+ -+if [ x\$feature_timeout_style = xy ] ; then -+ if [ "\${menu_show_once}" ]; then -+ unset menu_show_once -+ save_env menu_show_once -+ set timeout_style=menu -+ set timeout=60 -+ elif [ "\${menu_auto_hide}" -a "\${last_boot_ok}" = "1" ]; then -+ set orig_timeout_style=\${timeout_style} -+ set orig_timeout=\${timeout} -+ if [ "\${fastboot}" = "1" ]; then -+ # timeout_style=menu + timeout=0 avoids the countdown code keypress check -+ set timeout_style=menu -+ set timeout=0 -+ else -+ set timeout_style=hidden -+ set timeout=1 -+ fi -+ fi -+fi -+EOF -diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in -index 4b27bd20153..3c9431cfcfb 100644 ---- a/util/grub.d/30_os-prober.in -+++ b/util/grub.d/30_os-prober.in -@@ -42,6 +42,7 @@ if [ -z "${OSPROBED}" ] ; then - fi - - osx_entry() { -+ found_other_os=1 - # TRANSLATORS: it refers on the OS residing on device %s - onstr="$(gettext_printf "(on %s)" "${DEVICE}")" - hints="" -@@ -102,6 +103,7 @@ for OS in ${OSPROBED} ; do - - case ${BOOT} in - chain) -+ found_other_os=1 - - onstr="$(gettext_printf "(on %s)" "${DEVICE}")" - cat << EOF -@@ -132,6 +134,7 @@ EOF - EOF - ;; - efi) -+ found_other_os=1 - - EFIPATH=${DEVICE#*@} - DEVICE=${DEVICE%@*} -@@ -176,6 +179,7 @@ EOF - LINITRD="${LINITRD#/boot}" - fi - -+ found_other_os=1 - onstr="$(gettext_printf "(on %s)" "${DEVICE}")" - recovery_params="$(echo "${LPARAMS}" | grep single)" || true - counter=1 -@@ -257,6 +261,7 @@ EOF - done - ;; - hurd) -+ found_other_os=1 - onstr="$(gettext_printf "(on %s)" "${DEVICE}")" - cat << EOF - menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' { -@@ -283,6 +288,7 @@ EOF - EOF - ;; - minix) -+ found_other_os=1 - cat << EOF - menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" { - EOF -@@ -299,3 +305,15 @@ EOF - ;; - esac - done -+ -+# We override the results of the menu_auto_hide code here, this is a bit ugly, -+# but grub-mkconfig writes out the file linearly, so this is the only way -+if [ "${found_other_os}" = "1" ]; then -+ cat << EOF -+# Other OS found, undo autohiding of menu unless menu_auto_hide=2 -+if [ "\${orig_timeout_style}" -a "\${menu_auto_hide}" != "2" ]; then -+ set timeout_style=\${orig_timeout_style} -+ set timeout=\${orig_timeout} -+fi -+EOF -+fi diff --git a/SOURCES/0098-Try-to-pick-better-locations-for-kernel-and-initrd.patch b/SOURCES/0098-Try-to-pick-better-locations-for-kernel-and-initrd.patch new file mode 100644 index 0000000..4f42ea5 --- /dev/null +++ b/SOURCES/0098-Try-to-pick-better-locations-for-kernel-and-initrd.patch @@ -0,0 +1,211 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 11 Jul 2019 17:17:02 +0200 +Subject: [PATCH] Try to pick better locations for kernel and initrd + +- Don't limit allocations on 64-bit platforms to < 0x[37f]fffffff if + we're using the "large" code model ; use __UINTPTR_MAX__. +- Get the comparison right to check the address we've allocated. +- Fix the allocation for the command line as well. + +*But*, when we did this some systems started failing badly; coudln't +parse partition tables, etc. What's going on here is the disk controller +is silently failing DMAs to addresses above 4GB, so we're trying to parse +uninitialized (or HW zeroed) ram when looking for the partition table, +etc. + +So to limit this, we make grub_malloc() pick addresses below 4GB on +x86_64, but the direct EFI page allocation functions can get addresses +above that. + +Additionally, we now try to locate kernel+initrd+cmdline+etc below +0x7fffffff, and if they're too big to fit any memory window there, then +we try a higher address. + +Signed-off-by: Peter Jones +[david.abdurachmanov: fix macro for riscv64] +Signed-off-by: David Abdurachmanov +Signed-off-by: Robbie Harwood +--- + grub-core/kern/efi/mm.c | 8 ++++---- + grub-core/loader/i386/efi/linux.c | 24 +++++++++++++++++------- + include/grub/arm/efi/memory.h | 1 + + include/grub/arm64/efi/memory.h | 1 + + include/grub/i386/efi/memory.h | 1 + + include/grub/ia64/efi/memory.h | 1 + + include/grub/riscv64/efi/memory.h | 1 + + include/grub/x86_64/efi/memory.h | 4 +++- + 8 files changed, 29 insertions(+), 12 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 85ad4b4494..e84961d078 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -122,7 +122,7 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max, + grub_efi_boot_services_t *b; + grub_efi_physical_address_t address = max; + +- if (max > 0xffffffff) ++ if (max > GRUB_EFI_MAX_USABLE_ADDRESS) + return 0; + + b = grub_efi_system_table->boot_services; +@@ -480,7 +480,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + { + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY + #if 1 +- && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS ++ && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS + #endif + && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 + && desc->num_pages != 0) +@@ -498,9 +498,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + #if 1 + if (BYTES_TO_PAGES (filtered_desc->physical_start) + + filtered_desc->num_pages +- > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)) ++ > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)) + filtered_desc->num_pages +- = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS) ++ = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS) + - BYTES_TO_PAGES (filtered_desc->physical_start)); + #endif + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 3017d0f3e5..33e981e76e 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -106,7 +107,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + size += ALIGN_UP (grub_file_size (files[i]), 4); + } + +- initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size)); ++ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size)); ++ if (!initrd_mem) ++ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size)); + if (!initrd_mem) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd")); +@@ -202,8 +205,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- params = grub_efi_allocate_pages_max (0x3fffffff, ++ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, + BYTES_TO_PAGES(sizeof(*params))); ++ if (!params) ++ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, ++ BYTES_TO_PAGES(sizeof(*params))); + if (! params) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); +@@ -273,8 +279,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + #endif + + grub_dprintf ("linux", "setting up cmdline\n"); +- linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff, +- BYTES_TO_PAGES(lh->cmdline_size + 1)); ++ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, ++ BYTES_TO_PAGES(lh->cmdline_size + 1)); ++ if (!linux_cmdline) ++ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, ++ BYTES_TO_PAGES(lh->cmdline_size + 1)); + if (!linux_cmdline) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline")); +@@ -301,11 +310,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + kernel_mem = grub_efi_allocate_pages_max(lh->pref_address, + BYTES_TO_PAGES(lh->init_size)); +- + if (!kernel_mem) +- kernel_mem = grub_efi_allocate_pages_max(0x3fffffff, ++ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, ++ BYTES_TO_PAGES(lh->init_size)); ++ if (!kernel_mem) ++ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, + BYTES_TO_PAGES(lh->init_size)); +- + if (!kernel_mem) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); +diff --git a/include/grub/arm/efi/memory.h b/include/grub/arm/efi/memory.h +index 2c64918e3f..a4c2ec8350 100644 +--- a/include/grub/arm/efi/memory.h ++++ b/include/grub/arm/efi/memory.h +@@ -2,5 +2,6 @@ + #include + + #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS + + #endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/arm64/efi/memory.h b/include/grub/arm64/efi/memory.h +index c6cb324171..acb61dca44 100644 +--- a/include/grub/arm64/efi/memory.h ++++ b/include/grub/arm64/efi/memory.h +@@ -2,5 +2,6 @@ + #include + + #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS + + #endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/i386/efi/memory.h b/include/grub/i386/efi/memory.h +index 2c64918e3f..a4c2ec8350 100644 +--- a/include/grub/i386/efi/memory.h ++++ b/include/grub/i386/efi/memory.h +@@ -2,5 +2,6 @@ + #include + + #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS + + #endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/ia64/efi/memory.h b/include/grub/ia64/efi/memory.h +index 2c64918e3f..a4c2ec8350 100644 +--- a/include/grub/ia64/efi/memory.h ++++ b/include/grub/ia64/efi/memory.h +@@ -2,5 +2,6 @@ + #include + + #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS + + #endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/riscv64/efi/memory.h b/include/grub/riscv64/efi/memory.h +index c6cb324171..acb61dca44 100644 +--- a/include/grub/riscv64/efi/memory.h ++++ b/include/grub/riscv64/efi/memory.h +@@ -2,5 +2,6 @@ + #include + + #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS + + #endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/efi/memory.h +index 46e9145a30..e81cfb3221 100644 +--- a/include/grub/x86_64/efi/memory.h ++++ b/include/grub/x86_64/efi/memory.h +@@ -2,9 +2,11 @@ + #include + + #if defined (__code_model_large__) +-#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff ++#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__ ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff + #else + #define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS + #endif + + #endif /* ! GRUB_MEMORY_CPU_HEADER */ diff --git a/SOURCES/0099-Add-grub-set-bootflag-utility.patch b/SOURCES/0099-Add-grub-set-bootflag-utility.patch deleted file mode 100644 index f5ff7d3..0000000 --- a/SOURCES/0099-Add-grub-set-bootflag-utility.patch +++ /dev/null @@ -1,291 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Tue, 12 Jun 2018 13:25:16 +0200 -Subject: [PATCH] Add grub-set-bootflag utility - -This commit adds a new grub-set-bootflag utility, which can be used -to set known bootflags in the grubenv: boot_success or menu_show_once. - -grub-set-bootflag is different from grub-editenv in 2 ways: - -1) It is intended to be executed by regular users so must be installed -as suid root. As such it is written to not use any existing grubenv -related code for easy auditing. - -It can't be executed through pkexec because we want to call it under gdm -and pkexec does not work under gdm due the gdm user having /sbin/nologin -as shell. - -2) Since it can be executed by regular users it only allows setting -(assigning a value of 1 to) bootflags which it knows about. Currently -those are just boot_success and menu_show_once. - -This commit also adds a couple of example systemd and files which show -how this can be used to set boot_success from a user-session: - -docs/grub-boot-success.service -docs/grub-boot-success.timer - -The 2 grub-boot-success.systemd files should be placed in /lib/systemd/user -and a symlink to grub-boot-success.timer should be added to -/lib/systemd/user/timers.target.wants. - -Signed-off-by: Hans de Goede ---- - Makefile.util.def | 7 ++ - util/grub-set-bootflag.c | 160 +++++++++++++++++++++++++++++++++++++++++ - conf/Makefile.extra-dist | 3 + - docs/grub-boot-success.service | 6 ++ - docs/grub-boot-success.timer | 6 ++ - util/grub-set-bootflag.1 | 20 ++++++ - 6 files changed, 202 insertions(+) - create mode 100644 util/grub-set-bootflag.c - create mode 100644 docs/grub-boot-success.service - create mode 100644 docs/grub-boot-success.timer - create mode 100644 util/grub-set-bootflag.1 - -diff --git a/Makefile.util.def b/Makefile.util.def -index 04551e095bd..c6375933faa 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -1445,3 +1445,10 @@ program = { - ldadd = grub-core/lib/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - }; -+ -+program = { -+ name = grub-set-bootflag; -+ installdir = sbin; -+ mansection = 1; -+ common = util/grub-set-bootflag.c; -+}; -diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c -new file mode 100644 -index 00000000000..bb198f02351 ---- /dev/null -+++ b/util/grub-set-bootflag.c -@@ -0,0 +1,160 @@ -+/* grub-set-bootflag.c - tool to set boot-flags in the grubenv. */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2018 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+/* -+ * NOTE this gets run by users as root (through pkexec), so this does not -+ * use any grub library / util functions to allow for easy auditing. -+ * The grub headers are only included to get certain defines. -+ */ -+ -+#include /* For *_DIR_NAME defines */ -+#include -+#include /* For GRUB_ENVBLK_DEFCFG define */ -+#include -+#include -+#include -+#include -+ -+#define GRUBENV "/" GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME "/" GRUB_ENVBLK_DEFCFG -+#define GRUBENV_SIZE 1024 -+ -+const char *bootflags[] = { -+ "boot_success", -+ "menu_show_once", -+ NULL -+}; -+ -+static void usage(void) -+{ -+ int i; -+ -+ fprintf (stderr, "Usage: 'grub-set-bootflag ', where is one of:\n"); -+ for (i = 0; bootflags[i]; i++) -+ fprintf (stderr, " %s\n", bootflags[i]); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ /* NOTE buf must be at least the longest bootflag length + 4 bytes */ -+ char env[GRUBENV_SIZE + 1], buf[64], *s; -+ const char *bootflag; -+ int i, len, ret; -+ FILE *f; -+ -+ if (argc != 2) -+ { -+ usage(); -+ return 1; -+ } -+ -+ for (i = 0; bootflags[i]; i++) -+ if (!strcmp (argv[1], bootflags[i])) -+ break; -+ if (!bootflags[i]) -+ { -+ fprintf (stderr, "Invalid bootflag: '%s'\n", argv[1]); -+ usage(); -+ return 1; -+ } -+ -+ bootflag = bootflags[i]; -+ len = strlen (bootflag); -+ -+ f = fopen (GRUBENV, "r"); -+ if (!f) -+ { -+ perror ("Error opening " GRUBENV " for reading"); -+ return 1; -+ } -+ -+ ret = fread (env, 1, GRUBENV_SIZE, f); -+ fclose (f); -+ if (ret != GRUBENV_SIZE) -+ { -+ errno = EINVAL; -+ perror ("Error reading from " GRUBENV); -+ return 1; -+ } -+ -+ /* 0 terminate env */ -+ env[GRUBENV_SIZE] = 0; -+ -+ if (strncmp (env, GRUB_ENVBLK_SIGNATURE, strlen (GRUB_ENVBLK_SIGNATURE))) -+ { -+ fprintf (stderr, "Error invalid environment block\n"); -+ return 1; -+ } -+ -+ /* Find a pre-existing definition of the bootflag */ -+ s = strstr (env, bootflag); -+ while (s && s[len] != '=') -+ s = strstr (s + len, bootflag); -+ -+ if (s && ((s[len + 1] != '0' && s[len + 1] != '1') || s[len + 2] != '\n')) -+ { -+ fprintf (stderr, "Pre-existing bootflag '%s' has unexpected value\n", bootflag); -+ return 1; -+ } -+ -+ /* No pre-existing bootflag? -> find free space */ -+ if (!s) -+ { -+ for (i = 0; i < (len + 3); i++) -+ buf[i] = '#'; -+ buf[i] = 0; -+ s = strstr (env, buf); -+ } -+ -+ if (!s) -+ { -+ fprintf (stderr, "No space in grubenv to store bootflag '%s'\n", bootflag); -+ return 1; -+ } -+ -+ /* The grubenv is not 0 terminated, so memcpy the name + '=' , '1', '\n' */ -+ snprintf(buf, sizeof(buf), "%s=1\n", bootflag); -+ memcpy(s, buf, len + 3); -+ -+ /* "r+", don't truncate so that the diskspace stays reserved */ -+ f = fopen (GRUBENV, "r+"); -+ if (!f) -+ { -+ perror ("Error opening " GRUBENV " for writing"); -+ return 1; -+ } -+ -+ ret = fwrite (env, 1, GRUBENV_SIZE, f); -+ if (ret != GRUBENV_SIZE) -+ { -+ perror ("Error writing to " GRUBENV); -+ return 1; -+ } -+ -+ ret = fflush (f); -+ if (ret) -+ { -+ perror ("Error flushing " GRUBENV); -+ return 1; -+ } -+ -+ fsync (fileno (f)); -+ fclose (f); -+ -+ return 0; -+} -diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist -index b909f2c073a..ea58362b555 100644 ---- a/conf/Makefile.extra-dist -+++ b/conf/Makefile.extra-dist -@@ -14,6 +14,9 @@ EXTRA_DIST += util/import_unicode.py - EXTRA_DIST += docs/autoiso.cfg - EXTRA_DIST += docs/grub.cfg - EXTRA_DIST += docs/osdetect.cfg -+EXTRA_DIST += docs/org.gnu.grub.policy -+EXTRA_DIST += docs/grub-boot-success.service -+EXTRA_DIST += docs/grub-boot-success.timer - - EXTRA_DIST += conf/i386-cygwin-img-ld.sc - -diff --git a/docs/grub-boot-success.service b/docs/grub-boot-success.service -new file mode 100644 -index 00000000000..80e79584c91 ---- /dev/null -+++ b/docs/grub-boot-success.service -@@ -0,0 +1,6 @@ -+[Unit] -+Description=Mark boot as successful -+ -+[Service] -+Type=oneshot -+ExecStart=/usr/sbin/grub2-set-bootflag boot_success -diff --git a/docs/grub-boot-success.timer b/docs/grub-boot-success.timer -new file mode 100644 -index 00000000000..5d8fcba21aa ---- /dev/null -+++ b/docs/grub-boot-success.timer -@@ -0,0 +1,6 @@ -+[Unit] -+Description=Mark boot as successful after the user session has run 2 minutes -+ConditionUser=!@system -+ -+[Timer] -+OnActiveSec=2min -diff --git a/util/grub-set-bootflag.1 b/util/grub-set-bootflag.1 -new file mode 100644 -index 00000000000..57801da22a0 ---- /dev/null -+++ b/util/grub-set-bootflag.1 -@@ -0,0 +1,20 @@ -+.TH GRUB-SET-BOOTFLAG 1 "Tue Jun 12 2018" -+.SH NAME -+\fBgrub-set-bootflag\fR \(em Set a bootflag in the GRUB environment block. -+ -+.SH SYNOPSIS -+\fBgrub-set-bootflag\fR <\fIBOOTFLAG\fR> -+ -+.SH DESCRIPTION -+\fBgrub-set-bootflag\fR is a command line to set bootflags in GRUB's -+stored environment. -+ -+.SH COMMANDS -+.TP -+\fBBOOTFLAG\fR -+.RS 7 -+Bootflag to set, one of \fIboot_success\fR or \fIshow_menu_once\fR. -+.RE -+ -+.SH SEE ALSO -+.BR "info grub" diff --git a/SOURCES/0099-Attempt-to-fix-up-all-the-places-Wsign-compare-error.patch b/SOURCES/0099-Attempt-to-fix-up-all-the-places-Wsign-compare-error.patch new file mode 100644 index 0000000..77db523 --- /dev/null +++ b/SOURCES/0099-Attempt-to-fix-up-all-the-places-Wsign-compare-error.patch @@ -0,0 +1,199 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 11 Jul 2019 18:03:25 +0200 +Subject: [PATCH] Attempt to fix up all the places -Wsign-compare=error finds. + +Signed-off-by: Peter Jones +--- + grub-core/kern/emu/misc.c | 2 +- + grub-core/lib/reed_solomon.c | 4 ++-- + grub-core/osdep/linux/blocklist.c | 2 +- + grub-core/osdep/linux/getroot.c | 2 +- + grub-core/osdep/linux/hostdisk.c | 2 +- + util/grub-fstest.c | 2 +- + util/grub-menulst2cfg.c | 2 +- + util/grub-mkfont.c | 13 +++++++------ + util/grub-probe.c | 2 +- + util/setup.c | 2 +- + 10 files changed, 17 insertions(+), 16 deletions(-) + +diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c +index 0ff13bcaf8..d278c2921f 100644 +--- a/grub-core/kern/emu/misc.c ++++ b/grub-core/kern/emu/misc.c +@@ -185,7 +185,7 @@ grub_util_get_image_size (const char *path) + sz = ftello (f); + if (sz < 0) + grub_util_error (_("cannot open `%s': %s"), path, strerror (errno)); +- if (sz != (size_t) sz) ++ if (sz > (off_t)(GRUB_SIZE_MAX >> 1)) + grub_util_error (_("file `%s' is too big"), path); + ret = (size_t) sz; + +diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c +index 467305b46a..79037c093f 100644 +--- a/grub-core/lib/reed_solomon.c ++++ b/grub-core/lib/reed_solomon.c +@@ -157,7 +157,7 @@ static void + rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) + { + gf_single_t *rs_polynomial; +- int i, j; ++ unsigned int i, j; + gf_single_t *m; + m = xcalloc (s + rs, sizeof (gf_single_t)); + grub_memcpy (m, data, s * sizeof (gf_single_t)); +@@ -324,7 +324,7 @@ static void + encode_block (gf_single_t *ptr, grub_size_t s, + gf_single_t *rptr, grub_size_t rs) + { +- int i, j; ++ unsigned int i, j; + for (i = 0; i < SECTOR_SIZE; i++) + { + grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; +diff --git a/grub-core/osdep/linux/blocklist.c b/grub-core/osdep/linux/blocklist.c +index c77d6085cc..42a315031f 100644 +--- a/grub-core/osdep/linux/blocklist.c ++++ b/grub-core/osdep/linux/blocklist.c +@@ -109,7 +109,7 @@ grub_install_get_blocklist (grub_device_t root_dev, + else + { + struct fiemap *fie2; +- int i; ++ unsigned int i; + fie2 = xmalloc (sizeof (*fie2) + + fie1.fm_mapped_extents + * sizeof (fie1.fm_extents[1])); +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 28790307e0..9f730b3518 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -236,7 +236,7 @@ grub_find_root_devices_from_btrfs (const char *dir) + { + int fd; + struct btrfs_ioctl_fs_info_args fsi; +- int i, j = 0; ++ unsigned int i, j = 0; + char **ret; + + fd = open (dir, 0); +diff --git a/grub-core/osdep/linux/hostdisk.c b/grub-core/osdep/linux/hostdisk.c +index da62f924e3..7bc99ac1c1 100644 +--- a/grub-core/osdep/linux/hostdisk.c ++++ b/grub-core/osdep/linux/hostdisk.c +@@ -83,7 +83,7 @@ grub_util_get_fd_size_os (grub_util_fd_t fd, const char *name, unsigned *log_sec + if (sector_size & (sector_size - 1) || !sector_size) + return -1; + for (log_sector_size = 0; +- (1 << log_sector_size) < sector_size; ++ (1U << log_sector_size) < sector_size; + log_sector_size++); + + if (log_secsize) +diff --git a/util/grub-fstest.c b/util/grub-fstest.c +index 8386564200..bfcef852d8 100644 +--- a/util/grub-fstest.c ++++ b/util/grub-fstest.c +@@ -323,7 +323,7 @@ cmd_cmp (char *src, char *dest) + read_file (src, cmp_hook, ff); + + { +- grub_uint64_t pre; ++ long long pre; + pre = ftell (ff); + fseek (ff, 0, SEEK_END); + if (pre != ftell (ff)) +diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c +index a39f869394..358d604210 100644 +--- a/util/grub-menulst2cfg.c ++++ b/util/grub-menulst2cfg.c +@@ -34,7 +34,7 @@ main (int argc, char **argv) + char *buf = NULL; + size_t bufsize = 0; + char *suffix = xstrdup (""); +- int suffixlen = 0; ++ size_t suffixlen = 0; + const char *out_fname = 0; + + grub_util_host_init (&argc, &argv); +diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c +index 0fe45a6103..3e09240b99 100644 +--- a/util/grub-mkfont.c ++++ b/util/grub-mkfont.c +@@ -138,7 +138,8 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, + int width, height; + int cuttop, cutbottom, cutleft, cutright; + grub_uint8_t *data; +- int mask, i, j, bitmap_size; ++ int mask, i, bitmap_size; ++ unsigned int j; + FT_GlyphSlot glyph; + int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME; + FT_Error err; +@@ -183,7 +184,7 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, + cuttop = cutbottom = cutleft = cutright = 0; + else + { +- for (cuttop = 0; cuttop < glyph->bitmap.rows; cuttop++) ++ for (cuttop = 0; cuttop < (long)glyph->bitmap.rows; cuttop++) + { + for (j = 0; j < glyph->bitmap.width; j++) + if (glyph->bitmap.buffer[j / 8 + cuttop * glyph->bitmap.pitch] +@@ -203,10 +204,10 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, + break; + } + cutbottom = glyph->bitmap.rows - 1 - cutbottom; +- if (cutbottom + cuttop >= glyph->bitmap.rows) ++ if (cutbottom + cuttop >= (long)glyph->bitmap.rows) + cutbottom = 0; + +- for (cutleft = 0; cutleft < glyph->bitmap.width; cutleft++) ++ for (cutleft = 0; cutleft < (long)glyph->bitmap.width; cutleft++) + { + for (j = 0; j < glyph->bitmap.rows; j++) + if (glyph->bitmap.buffer[cutleft / 8 + j * glyph->bitmap.pitch] +@@ -225,7 +226,7 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, + break; + } + cutright = glyph->bitmap.width - 1 - cutright; +- if (cutright + cutleft >= glyph->bitmap.width) ++ if (cutright + cutleft >= (long)glyph->bitmap.width) + cutright = 0; + } + +@@ -262,7 +263,7 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, + + mask = 0; + data = &glyph_info->bitmap[0] - 1; +- for (j = cuttop; j < height + cuttop; j++) ++ for (j = cuttop; j < (long)height + cuttop; j++) + for (i = cutleft; i < width + cutleft; i++) + add_pixel (&data, &mask, + glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] & +diff --git a/util/grub-probe.c b/util/grub-probe.c +index c08e46bbb4..c6fac732b4 100644 +--- a/util/grub-probe.c ++++ b/util/grub-probe.c +@@ -798,7 +798,7 @@ argp_parser (int key, char *arg, struct argp_state *state) + + case 't': + { +- int i; ++ unsigned int i; + + for (i = PRINT_FS; i < ARRAY_SIZE (targets); i++) + if (strcmp (arg, targets[i]) == 0) +diff --git a/util/setup.c b/util/setup.c +index da5f2c07f5..8b22bb8cca 100644 +--- a/util/setup.c ++++ b/util/setup.c +@@ -406,7 +406,7 @@ SETUP (const char *dir, + int is_ldm; + grub_err_t err; + grub_disk_addr_t *sectors; +- int i; ++ unsigned int i; + grub_fs_t fs; + unsigned int nsec, maxsec; + diff --git a/SOURCES/0100-Don-t-use-Wno-sign-compare-Wno-conversion-Wno-error-.patch b/SOURCES/0100-Don-t-use-Wno-sign-compare-Wno-conversion-Wno-error-.patch new file mode 100644 index 0000000..03b4bbf --- /dev/null +++ b/SOURCES/0100-Don-t-use-Wno-sign-compare-Wno-conversion-Wno-error-.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 11 Jul 2019 18:20:37 +0200 +Subject: [PATCH] Don't use -Wno-sign-compare -Wno-conversion -Wno-error, do + use -Wextra. + +Signed-off-by: Peter Jones +--- + configure.ac | 14 +++++++++++--- + conf/Makefile.common | 2 +- + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 7b4e1854d3..490353713a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1452,11 +1452,11 @@ fi + # Set them to their new values for the tests below. + CC="$TARGET_CC" + if test x"$platform" = xemu ; then +-CFLAGS="$TARGET_CFLAGS -Wno-error" ++CFLAGS="$TARGET_CFLAGS" + elif test "x$TARGET_APPLE_LINKER" = x1 ; then +-CFLAGS="$TARGET_CFLAGS -nostdlib -static -Wno-error" ++CFLAGS="$TARGET_CFLAGS -nostdlib -static" + else +-CFLAGS="$TARGET_CFLAGS -nostdlib -Wno-error" ++CFLAGS="$TARGET_CFLAGS -nostdlib" + fi + CPPFLAGS="$TARGET_CPPFLAGS" + +@@ -1990,6 +1990,14 @@ if test x"$enable_werror" != xno ; then + HOST_CFLAGS="$HOST_CFLAGS -Werror" + fi + ++AC_ARG_ENABLE([wextra], ++ [AS_HELP_STRING([--disable-wextra], ++ [do not use -Wextra when building GRUB])]) ++if test x"$enable_wextra" != xno ; then ++ TARGET_CFLAGS="$TARGET_CFLAGS -Wextra" ++ HOST_CFLAGS="$HOST_CFLAGS -Wextra" ++fi ++ + TARGET_CPP="$TARGET_CC -E" + TARGET_CCAS=$TARGET_CC + +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 2ff9b39357..35e14ff017 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -66,7 +66,7 @@ grubconfdir = $(sysconfdir)/grub.d + platformdir = $(pkglibdir)/$(target_cpu)-$(platform) + starfielddir = $(pkgdatadir)/themes/starfield + +-CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion ++CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code + CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib + + CFLAGS_POSIX = -fno-builtin diff --git a/SOURCES/0100-docs-Add-grub-boot-indeterminate.service-example.patch b/SOURCES/0100-docs-Add-grub-boot-indeterminate.service-example.patch deleted file mode 100644 index 44f6ad3..0000000 --- a/SOURCES/0100-docs-Add-grub-boot-indeterminate.service-example.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Tue, 19 Jun 2018 15:20:54 +0200 -Subject: [PATCH] docs: Add grub-boot-indeterminate.service example - -This is an example service file, for use from -/lib/systemd/system/system-update.target.wants -to increment the boot_indeterminate variable when -doing offline updates. - -Signed-off-by: Hans de Goede ---- - docs/grub-boot-indeterminate.service | 11 +++++++++++ - 1 file changed, 11 insertions(+) - create mode 100644 docs/grub-boot-indeterminate.service - -diff --git a/docs/grub-boot-indeterminate.service b/docs/grub-boot-indeterminate.service -new file mode 100644 -index 00000000000..6c8dcb186b6 ---- /dev/null -+++ b/docs/grub-boot-indeterminate.service -@@ -0,0 +1,11 @@ -+[Unit] -+Description=Mark boot as indeterminate -+DefaultDependencies=false -+Requires=sysinit.target -+After=sysinit.target -+Wants=system-update-pre.target -+Before=system-update-pre.target -+ -+[Service] -+Type=oneshot -+ExecStart=/usr/bin/grub2-editenv - incr boot_indeterminate diff --git a/SOURCES/0101-gentpl-add-disable-support.patch b/SOURCES/0101-gentpl-add-disable-support.patch deleted file mode 100644 index 2c3c998..0000000 --- a/SOURCES/0101-gentpl-add-disable-support.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 11 Jul 2018 13:43:15 -0400 -Subject: [PATCH] gentpl: add 'disable = ' support - -Signed-off-by: Peter Jones ---- - gentpl.py | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/gentpl.py b/gentpl.py -index 2cba0bbbd6f..628e8bec1d7 100644 ---- a/gentpl.py -+++ b/gentpl.py -@@ -592,11 +592,21 @@ def platform_conditional(platform, closure): - # }; - # - def foreach_enabled_platform(defn, closure): -+ enabled = False -+ disabled = False - if 'enable' in defn: -+ enabled = True - for platform in GRUB_PLATFORMS: - if platform_tagged(defn, platform, "enable"): - platform_conditional(platform, closure) -- else: -+ -+ if 'disable' in defn: -+ disabled = True -+ for platform in GRUB_PLATFORMS: -+ if not platform_tagged(defn, platform, "disable"): -+ platform_conditional(platform, closure) -+ -+ if not enabled and not disabled: - for platform in GRUB_PLATFORMS: - platform_conditional(platform, closure) - -@@ -655,6 +665,8 @@ def first_time(defn, snippet): - def is_platform_independent(defn): - if 'enable' in defn: - return False -+ if 'disable' in defn: -+ return False - for suffix in [ "", "_nodist" ]: - template = platform_values(defn, GRUB_PLATFORMS[0], suffix) - for platform in GRUB_PLATFORMS[1:]: diff --git a/SOURCES/0101-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch b/SOURCES/0101-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch new file mode 100644 index 0000000..5a9c6f2 --- /dev/null +++ b/SOURCES/0101-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 12 Jul 2019 09:53:32 +0200 +Subject: [PATCH] x86-efi: Use bounce buffers for reading to addresses > 4GB + +Lots of machines apparently can't DMA correctly above 4GB during UEFI, +so use bounce buffers for the initramfs read. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 52 +++++++++++++++++++++++++++++++++------ + 1 file changed, 45 insertions(+), 7 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 33e981e76e..2f0336809e 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -35,11 +35,16 @@ static grub_dl_t my_mod; + static int loaded; + static void *kernel_mem; + static grub_uint64_t kernel_size; +-static grub_uint8_t *initrd_mem; ++static void *initrd_mem; + static grub_uint32_t handover_offset; + struct linux_kernel_params *params; + static char *linux_cmdline; + ++#define MIN(a, b) \ ++ ({ typeof (a) _a = (a); \ ++ typeof (b) _b = (b); \ ++ _a < _b ? _a : _b; }) ++ + #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) + + static grub_err_t +@@ -73,6 +78,44 @@ grub_linuxefi_unload (void) + return GRUB_ERR_NONE; + } + ++#define BOUNCE_BUFFER_MAX 0x10000000ull ++ ++static grub_ssize_t ++read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) ++{ ++ grub_ssize_t bufpos = 0; ++ static grub_size_t bbufsz = 0; ++ static char *bbuf = NULL; ++ ++ if (bbufsz == 0) ++ bbufsz = MIN(BOUNCE_BUFFER_MAX, len); ++ ++ while (!bbuf && bbufsz) ++ { ++ bbuf = grub_malloc(bbufsz); ++ if (!bbuf) ++ bbufsz >>= 1; ++ } ++ if (!bbuf) ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate bounce buffer")); ++ ++ while (bufpos < (long long)len) ++ { ++ grub_ssize_t sz; ++ ++ sz = grub_file_read (file, bbuf, MIN(bbufsz, len - bufpos)); ++ if (sz < 0) ++ return sz; ++ if (sz == 0) ++ break; ++ ++ grub_memcpy(bufp + bufpos, bbuf, sz); ++ bufpos += sz; ++ } ++ ++ return bufpos; ++} ++ + static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +@@ -126,7 +169,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + for (i = 0; i < nfiles; i++) + { + grub_ssize_t cursize = grub_file_size (files[i]); +- if (grub_file_read (files[i], ptr, cursize) != cursize) ++ if (read (files[i], ptr, cursize) != cursize) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), +@@ -152,11 +195,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + return grub_errno; + } + +-#define MIN(a, b) \ +- ({ typeof (a) _a = (a); \ +- typeof (b) _b = (b); \ +- _a < _b ? _a : _b; }) +- + static grub_err_t + grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) diff --git a/SOURCES/0102-gentpl-add-pc-firmware-type.patch b/SOURCES/0102-gentpl-add-pc-firmware-type.patch deleted file mode 100644 index 96dd2b8..0000000 --- a/SOURCES/0102-gentpl-add-pc-firmware-type.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 11 Jul 2019 11:04:24 +0200 -Subject: [PATCH] gentpl: add 'pc' firmware type - -Signed-off-by: Peter Jones ---- - gentpl.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/gentpl.py b/gentpl.py -index 628e8bec1d7..34a4eba2b42 100644 ---- a/gentpl.py -+++ b/gentpl.py -@@ -51,6 +51,7 @@ GROUPS["riscv32"] = [ "riscv32_efi" ] - GROUPS["riscv64"] = [ "riscv64_efi" ] - - # Groups based on firmware -+GROUPS["pc"] = [ "i386_pc" ] - GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", - "riscv32_efi", "riscv64_efi" ] - GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] diff --git a/SOURCES/0102-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch b/SOURCES/0102-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch new file mode 100644 index 0000000..9b10d68 --- /dev/null +++ b/SOURCES/0102-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 13 Sep 2018 14:42:34 -0400 +Subject: [PATCH] x86-efi: Re-arrange grub_cmd_linux() a little bit. + +This just helps the next patch be easier to read. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 75 +++++++++++++++++++++------------------ + 1 file changed, 41 insertions(+), 34 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 2f0336809e..5f48fa5561 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -243,32 +243,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, +- BYTES_TO_PAGES(sizeof(*params))); +- if (!params) +- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, +- BYTES_TO_PAGES(sizeof(*params))); +- if (! params) +- { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); +- goto fail; +- } ++ lh = (struct linux_i386_kernel_header *)kernel; ++ grub_dprintf ("linux", "original lh is at %p\n", kernel); + +- grub_dprintf ("linux", "params = %p\n", params); +- +- grub_memset (params, 0, sizeof(*params)); +- +- setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); +- grub_dprintf ("linux", "copying %lu bytes from %p to %p\n", +- MIN((grub_size_t)0x202+setup_header_end_offset, +- sizeof (*params)) - 0x1f1, +- (grub_uint8_t *)kernel + 0x1f1, +- (grub_uint8_t *)params + 0x1f1); +- grub_memcpy ((grub_uint8_t *)params + 0x1f1, +- (grub_uint8_t *)kernel + 0x1f1, +- MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1); +- lh = (struct linux_i386_kernel_header *)params; +- grub_dprintf ("linux", "lh is at %p\n", lh); + grub_dprintf ("linux", "checking lh->boot_flag\n"); + if (lh->boot_flag != grub_cpu_to_le16 (0xaa55)) + { +@@ -316,6 +293,34 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + ++ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, ++ BYTES_TO_PAGES(sizeof(*params))); ++ if (!params) ++ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, ++ BYTES_TO_PAGES(sizeof(*params))); ++ if (! params) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); ++ goto fail; ++ } ++ ++ grub_dprintf ("linux", "params = %p\n", params); ++ ++ grub_memset (params, 0, sizeof(*params)); ++ ++ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); ++ grub_dprintf ("linux", "copying %lu bytes from %p to %p\n", ++ MIN((grub_size_t)0x202+setup_header_end_offset, ++ sizeof (*params)) - 0x1f1, ++ (grub_uint8_t *)kernel + 0x1f1, ++ (grub_uint8_t *)params + 0x1f1); ++ grub_memcpy ((grub_uint8_t *)params + 0x1f1, ++ (grub_uint8_t *)kernel + 0x1f1, ++ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1); ++ ++ lh = (struct linux_i386_kernel_header *)params; ++ grub_dprintf ("linux", "new lh is at %p\n", lh); ++ + grub_dprintf ("linux", "setting up cmdline\n"); + linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, + BYTES_TO_PAGES(lh->cmdline_size + 1)); +@@ -341,8 +346,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "setting lh->cmd_line_ptr\n"); + lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline; + +- grub_dprintf ("linux", "computing handover offset\n"); + handover_offset = lh->handover_offset; ++ grub_dprintf("linux", "handover_offset: %08x\n", handover_offset); + + start = (lh->setup_sects + 1) * 512; + +@@ -359,26 +364,28 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); + goto fail; + } +- +- grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem); ++ grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); + + grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); +- loaded=1; ++ ++ loaded = 1; ++ + grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem); + lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem; + + grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start); + +- grub_dprintf ("linux", "setting lh->type_of_loader\n"); + lh->type_of_loader = 0x6; ++ grub_dprintf ("linux", "setting lh->type_of_loader = 0x%02x\n", ++ lh->type_of_loader); + +- grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n"); + params->ext_loader_type = 0; + params->ext_loader_ver = 2; +- grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n", +- kernel_mem, handover_offset); ++ grub_dprintf ("linux", ++ "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n", ++ params->ext_loader_type, params->ext_loader_ver); + +- fail: ++fail: + if (file) + grub_file_close (file); + diff --git a/SOURCES/0103-efinet-also-use-the-firmware-acceleration-for-http.patch b/SOURCES/0103-efinet-also-use-the-firmware-acceleration-for-http.patch deleted file mode 100644 index 915b5aa..0000000 --- a/SOURCES/0103-efinet-also-use-the-firmware-acceleration-for-http.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 30 Jul 2018 14:06:42 -0400 -Subject: [PATCH] efinet: also use the firmware acceleration for http - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/net.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c -index 4bb308026ce..6603cd83edc 100644 ---- a/grub-core/net/efi/net.c -+++ b/grub-core/net/efi/net.c -@@ -1324,7 +1324,9 @@ grub_efi_net_boot_from_https (void) - && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) - { - grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp; -- return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0; -+ grub_dprintf ("efinet", "url:%s\n", (const char *)uri_dp->uri); -+ return (grub_strncmp ((const char *)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0 || -+ grub_strncmp ((const char *)uri_dp->uri, "http://", sizeof ("http://") - 1) == 0); - } - - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) diff --git a/SOURCES/0103-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch b/SOURCES/0103-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch new file mode 100644 index 0000000..700c98b --- /dev/null +++ b/SOURCES/0103-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch @@ -0,0 +1,258 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 12 Sep 2018 16:03:55 -0400 +Subject: [PATCH] x86-efi: Make our own allocator for kernel stuff + +This helps enable allocations above 4GB. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 167 +++++++++++++++++++++----------------- + 1 file changed, 94 insertions(+), 73 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 5f48fa5561..3e4f7ef39f 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -47,6 +47,65 @@ static char *linux_cmdline; + + #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) + ++struct allocation_choice { ++ grub_efi_physical_address_t addr; ++ grub_efi_allocate_type_t alloc_type; ++}; ++ ++static struct allocation_choice max_addresses[] = ++ { ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { 0, 0 } ++ }; ++ ++static inline void ++kernel_free(void *addr, grub_efi_uintn_t size) ++{ ++ if (addr && size) ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)addr, ++ BYTES_TO_PAGES(size)); ++} ++ ++static void * ++kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) ++{ ++ void *addr = 0; ++ unsigned int i; ++ grub_efi_physical_address_t prev_max = 0; ++ ++ for (i = 0; max_addresses[i].addr != 0 && addr == 0; i++) ++ { ++ grub_uint64_t max = max_addresses[i].addr; ++ grub_efi_uintn_t pages; ++ ++ if (max == prev_max) ++ continue; ++ ++ pages = BYTES_TO_PAGES(size); ++ grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", ++ pages, (void *)max); ++ ++ prev_max = max; ++ addr = grub_efi_allocate_pages_real (max, pages, ++ max_addresses[i].alloc_type, ++ GRUB_EFI_LOADER_DATA); ++ if (addr) ++ grub_dprintf ("linux", "Allocated at %p\n", addr); ++ } ++ ++ while (grub_error_pop ()) ++ { ++ ; ++ } ++ ++ if (addr == NULL) ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "%s", errmsg); ++ ++ return addr; ++} ++ + static grub_err_t + grub_linuxefi_boot (void) + { +@@ -62,19 +121,12 @@ grub_linuxefi_unload (void) + { + grub_dl_unref (my_mod); + loaded = 0; +- if (initrd_mem) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, +- BYTES_TO_PAGES(params->ramdisk_size)); +- if (linux_cmdline) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) +- linux_cmdline, +- BYTES_TO_PAGES(params->cmdline_size + 1)); +- if (kernel_mem) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, +- BYTES_TO_PAGES(kernel_size)); +- if (params) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params, +- BYTES_TO_PAGES(16384)); ++ ++ kernel_free(initrd_mem, params->ramdisk_size); ++ kernel_free(linux_cmdline, params->cmdline_size + 1); ++ kernel_free(kernel_mem, kernel_size); ++ kernel_free(params, sizeof(*params)); ++ + return GRUB_ERR_NONE; + } + +@@ -150,19 +202,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + size += ALIGN_UP (grub_file_size (files[i]), 4); + } + +- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size)); +- if (!initrd_mem) +- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size)); +- if (!initrd_mem) +- { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd")); +- goto fail; +- } +- +- grub_dprintf ("linux", "initrd_mem = %lx\n", (unsigned long) initrd_mem); ++ initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); ++ if (initrd_mem == NULL) ++ goto fail; ++ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); + + params->ramdisk_size = size; +- params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem; ++ params->ramdisk_image = initrd_mem; + + ptr = initrd_mem; + +@@ -221,7 +267,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + filelen = grub_file_size (file); + + kernel = grub_malloc(filelen); +- + if (!kernel) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); +@@ -274,7 +319,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +-#if defined(__x86_64__) || defined(__aarch64__) ++#if defined(__x86_64__) + grub_dprintf ("linux", "checking lh->xloadflags\n"); + if (!(lh->xloadflags & LINUX_XLF_KERNEL_64)) + { +@@ -293,17 +338,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + +- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, +- BYTES_TO_PAGES(sizeof(*params))); ++ params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); + if (!params) +- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, +- BYTES_TO_PAGES(sizeof(*params))); +- if (! params) +- { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); +- goto fail; +- } +- ++ goto fail; + grub_dprintf ("linux", "params = %p\n", params); + + grub_memset (params, 0, sizeof(*params)); +@@ -322,19 +359,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "new lh is at %p\n", lh); + + grub_dprintf ("linux", "setting up cmdline\n"); +- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, +- BYTES_TO_PAGES(lh->cmdline_size + 1)); ++ linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); + if (!linux_cmdline) +- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, +- BYTES_TO_PAGES(lh->cmdline_size + 1)); +- if (!linux_cmdline) +- { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline")); +- goto fail; +- } +- +- grub_dprintf ("linux", "linux_cmdline = %lx\n", +- (unsigned long)linux_cmdline); ++ goto fail; ++ grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline); + + grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + grub_create_loader_cmdline (argc, argv, +@@ -343,27 +371,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + GRUB_VERIFY_KERNEL_CMDLINE); + + grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); +- grub_dprintf ("linux", "setting lh->cmd_line_ptr\n"); +- lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline; ++ grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", ++ linux_cmdline); ++ lh->cmd_line_ptr = linux_cmdline; + + handover_offset = lh->handover_offset; +- grub_dprintf("linux", "handover_offset: %08x\n", handover_offset); ++ grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset); + + start = (lh->setup_sects + 1) * 512; + +- kernel_mem = grub_efi_allocate_pages_max(lh->pref_address, +- BYTES_TO_PAGES(lh->init_size)); +- if (!kernel_mem) +- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, +- BYTES_TO_PAGES(lh->init_size)); +- if (!kernel_mem) +- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, +- BYTES_TO_PAGES(lh->init_size)); +- if (!kernel_mem) ++ grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); ++ if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) + { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); +- goto fail; ++ max_addresses[0].addr = lh->pref_address; ++ max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; + } ++ kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); ++ if (!kernel_mem) ++ goto fail; + grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); + + grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); +@@ -398,18 +423,14 @@ fail: + loaded = 0; + } + +- if (linux_cmdline && lh && !loaded) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) +- linux_cmdline, +- BYTES_TO_PAGES(lh->cmdline_size + 1)); ++ if (!loaded) ++ { ++ if (lh) ++ kernel_free (linux_cmdline, lh->cmdline_size + 1); + +- if (kernel_mem && !loaded) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, +- BYTES_TO_PAGES(kernel_size)); +- +- if (params && !loaded) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params, +- BYTES_TO_PAGES(16384)); ++ kernel_free (kernel_mem, kernel_size); ++ kernel_free (params, sizeof(*params)); ++ } + + return grub_errno; + } diff --git a/SOURCES/0104-efi-http-Make-root_url-reflect-the-protocol-hostname.patch b/SOURCES/0104-efi-http-Make-root_url-reflect-the-protocol-hostname.patch deleted file mode 100644 index 985a037..0000000 --- a/SOURCES/0104-efi-http-Make-root_url-reflect-the-protocol-hostname.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 30 Jul 2018 16:39:57 -0400 -Subject: [PATCH] efi/http: Make root_url reflect the protocol+hostname of our - boot url. - -This lets you write config files that don't know urls. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/http.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c -index 3f61fd2fa5b..243acbaa35b 100644 ---- a/grub-core/net/efi/http.c -+++ b/grub-core/net/efi/http.c -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - static void - http_configure (struct grub_efi_net_device *dev, int prefer_ip6) -@@ -351,6 +352,24 @@ grub_efihttp_open (struct grub_efi_net_device *dev, - grub_err_t err; - grub_off_t size; - char *buf; -+ char *root_url; -+ grub_efi_ipv6_address_t address; -+ const char *rest; -+ -+ if (grub_efi_string_to_ip6_address (file->device->net->server, &address, &rest) && *rest == 0) -+ root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", file->device->net->server); -+ else -+ root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", file->device->net->server); -+ if (root_url) -+ { -+ grub_env_unset ("root_url"); -+ grub_env_set ("root_url", root_url); -+ grub_free (root_url); -+ } -+ else -+ { -+ return grub_errno; -+ } - - err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); - if (err != GRUB_ERR_NONE) diff --git a/SOURCES/0104-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch b/SOURCES/0104-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch new file mode 100644 index 0000000..6ac11a1 --- /dev/null +++ b/SOURCES/0104-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 12 Sep 2018 16:12:27 -0400 +Subject: [PATCH] x86-efi: Allow initrd+params+cmdline allocations above 4GB. + +This enables everything except the kernel itself to be above 4GB. +Putting the kernel up there still doesn't work, because of the way +params->code32_start is used. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 67 +++++++++++++++++++++++++++++++++++---- + include/grub/i386/linux.h | 6 +++- + 2 files changed, 65 insertions(+), 8 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 3e4f7ef39f..6bc18d5aef 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -52,13 +52,22 @@ struct allocation_choice { + grub_efi_allocate_type_t alloc_type; + }; + +-static struct allocation_choice max_addresses[] = ++static struct allocation_choice max_addresses[4] = + { ++ /* the kernel overrides this one with pref_address and ++ * GRUB_EFI_ALLOCATE_ADDRESS */ + { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ /* this one is always below 4GB, which we still *prefer* even if the flag ++ * is set. */ + { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ /* If the flag in params is set, this one gets changed to be above 4GB. */ + { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + { 0, 0 } + }; ++static struct allocation_choice saved_addresses[4]; ++ ++#define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses)) ++#define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses)) + + static inline void + kernel_free(void *addr, grub_efi_uintn_t size) +@@ -80,6 +89,11 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) + grub_uint64_t max = max_addresses[i].addr; + grub_efi_uintn_t pages; + ++ /* ++ * When we're *not* loading the kernel, or >4GB allocations aren't ++ * supported, these entries are basically all the same, so don't re-try ++ * the same parameters. ++ */ + if (max == prev_max) + continue; + +@@ -168,6 +182,9 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) + return bufpos; + } + ++#define LOW_U32(val) ((grub_uint32_t)(((grub_addr_t)(val)) & 0xffffffffull)) ++#define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull)) ++ + static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +@@ -207,8 +224,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + goto fail; + grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); + +- params->ramdisk_size = size; +- params->ramdisk_image = initrd_mem; ++ params->ramdisk_size = LOW_U32(size); ++ params->ramdisk_image = LOW_U32(initrd_mem); ++#if defined(__x86_64__) ++ params->ext_ramdisk_size = HIGH_U32(size); ++ params->ext_ramdisk_image = HIGH_U32(initrd_mem); ++#endif + + ptr = initrd_mem; + +@@ -338,6 +359,18 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + ++#if defined(__x86_64__) ++ if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) ++ { ++ grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); ++ max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS; ++ } ++ else ++ { ++ grub_dprintf ("linux", "Loading kernel above 4GB is not supported\n"); ++ } ++#endif ++ + params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); + if (!params) + goto fail; +@@ -372,21 +405,40 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); + grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", +- linux_cmdline); +- lh->cmd_line_ptr = linux_cmdline; ++ LOW_U32(linux_cmdline)); ++ lh->cmd_line_ptr = LOW_U32(linux_cmdline); ++#if defined(__x86_64__) ++ if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull) ++ { ++ grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n", ++ HIGH_U32(linux_cmdline)); ++ params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline); ++ } ++#endif + + handover_offset = lh->handover_offset; + grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset); + + start = (lh->setup_sects + 1) * 512; + ++ /* ++ * AFAICS >4GB for kernel *cannot* work because of params->code32_start being ++ * 32-bit and getting called unconditionally in head_64.S from either entry ++ * point. ++ * ++ * so nerf that out here... ++ */ ++ save_addresses(); + grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); + if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) + { + max_addresses[0].addr = lh->pref_address; + max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; + } ++ max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); ++ restore_addresses(); + if (!kernel_mem) + goto fail; + grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); +@@ -395,8 +447,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + loaded = 1; + +- grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem); +- lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem; ++ grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n", ++ LOW_U32(kernel_mem)); ++ lh->code32_start = LOW_U32(kernel_mem); + + grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start); + +diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h +index 25ef52c04e..fac22476cc 100644 +--- a/include/grub/i386/linux.h ++++ b/include/grub/i386/linux.h +@@ -236,7 +236,11 @@ struct linux_kernel_params + grub_uint32_t ofw_cif_handler; /* b8 */ + grub_uint32_t ofw_idt; /* bc */ + +- grub_uint8_t padding7[0x1b8 - 0xc0]; ++ grub_uint32_t ext_ramdisk_image; /* 0xc0 */ ++ grub_uint32_t ext_ramdisk_size; /* 0xc4 */ ++ grub_uint32_t ext_cmd_line_ptr; /* 0xc8 */ ++ ++ grub_uint8_t padding7[0x1b8 - 0xcc]; + + union + { diff --git a/SOURCES/0105-Fix-getroot.c-s-trampolines.patch b/SOURCES/0105-Fix-getroot.c-s-trampolines.patch new file mode 100644 index 0000000..e744b77 --- /dev/null +++ b/SOURCES/0105-Fix-getroot.c-s-trampolines.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 28 Sep 2018 15:42:19 -0400 +Subject: [PATCH] Fix getroot.c's trampolines. + +This makes the stack executable on most of the grub utilities, which is +bad, and rpmdiff complains about it. + +Signed-off-by: Peter Jones +--- + grub-core/osdep/linux/getroot.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 9f730b3518..f0c503f43d 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -1264,22 +1264,20 @@ grub_util_get_grub_dev_os (const char *os_dev) + return grub_dev; + } + ++static void *mp = NULL; ++static void ++btrfs_mount_path_hook(const char *m) ++{ ++ mp = strdup (m); ++} + + char * + grub_util_get_btrfs_subvol (const char *path, char **mount_path) + { +- char *mp = NULL; +- + if (mount_path) + *mount_path = NULL; + +- auto void +- mount_path_hook (const char *m) +- { +- mp = strdup (m); +- } +- +- grub_find_root_btrfs_mount_path_hook = mount_path_hook; ++ grub_find_root_btrfs_mount_path_hook = btrfs_mount_path_hook; + grub_free (grub_find_root_devices_from_mountinfo (path, NULL)); + grub_find_root_btrfs_mount_path_hook = NULL; + diff --git a/SOURCES/0105-Make-it-so-we-can-tell-configure-which-cflags-utils-.patch b/SOURCES/0105-Make-it-so-we-can-tell-configure-which-cflags-utils-.patch deleted file mode 100644 index b65eafc..0000000 --- a/SOURCES/0105-Make-it-so-we-can-tell-configure-which-cflags-utils-.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 26 Jun 2018 17:16:06 -0400 -Subject: [PATCH] Make it so we can tell configure which cflags utils are built - with - -This lets us have kernel.img be built with TARGET_CFLAGS but grub-mkimage and -friends built with HOST_CFLAGS. That in turn lets us build with an ARM compiler -that only has hard-float ABI versions of crt*.o and libgcc*, but still use soft -float for grub.efi. - -Signed-off-by: Peter Jones ---- - configure.ac | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- - conf/Makefile.common | 23 ++++++++++++----------- - gentpl.py | 8 ++++---- - 3 files changed, 64 insertions(+), 16 deletions(-) - -diff --git a/configure.ac b/configure.ac -index b4455e4732d..3405348178a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -877,11 +877,23 @@ if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ) && test "x$p - TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow" - fi - -+# Should grub utils get the host CFLAGS, or the target CFLAGS? -+AC_ARG_WITH([utils], -+ AS_HELP_STRING([--with-utils=host|target|build], -+ [choose which flags to build utilities with. (default=target)]), -+ [have_with_utils=y], -+ [have_with_utils=n]) -+if test x"$have_with_utils" = xy ; then -+ with_utils="$withval" -+else -+ with_utils=target -+fi -+ - # GRUB doesn't use float or doubles at all. Yet some toolchains may decide - # that floats are a good fit to run instead of what's written in the code. - # Given that floating point unit is disabled (if present to begin with) - # when GRUB is running which may result in various hard crashes. --if test x"$platform" != xemu ; then -+if test x"$platform" != xemu -a x"$with_utils" == xtarget ; then - AC_CACHE_CHECK([for options to get soft-float], grub_cv_target_cc_soft_float, [ - grub_cv_target_cc_soft_float=no - if test "x$target_cpu" = xarm64; then -@@ -2018,6 +2030,41 @@ HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include" - TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include" - TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_builddir)/include" - -+case "$with_utils" in -+ host) -+ UTILS_CFLAGS=$HOST_CFLAGS -+ UTILS_CPPFLAGS=$HOST_CPPFLAGS -+ UTILS_CCASFLAGS=$HOST_CCASFLAGS -+ UTILS_LDFLAGS=$HOST_LDFLAGS -+ ;; -+ target) -+ UTILS_CFLAGS=$TARGET_CFLAGS -+ UTILS_CPPFLAGS=$TARGET_CPPFLAGS -+ UTILS_CCASFLAGS=$TARGET_CCASFLAGS -+ UTILS_LDFLAGS=$TARGET_LDFLAGS -+ ;; -+ build) -+ UTILS_CFLAGS=$BUILD_CFLAGS -+ UTILS_CPPFLAGS=$BUILD_CPPFLAGS -+ UTILS_CCASFLAGS=$BUILD_CCASFLAGS -+ UTILS_LDFLAGS=$BUILD_LDFLAGS -+ ;; -+ *) -+ AC_MSG_ERROR([--with-utils must be either host, target, or build]) -+ ;; -+esac -+AC_MSG_NOTICE([Using $with_utils flags for utilities.]) -+ -+unset CFLAGS -+unset CPPFLAGS -+unset CCASFLAGS -+unset LDFLAGS -+ -+AC_SUBST(UTILS_CFLAGS) -+AC_SUBST(UTILS_CPPFLAGS) -+AC_SUBST(UTILS_CCASFLAGS) -+AC_SUBST(UTILS_LDFLAGS) -+ - GRUB_TARGET_CPU="${target_cpu}" - GRUB_PLATFORM="${platform}" - -diff --git a/conf/Makefile.common b/conf/Makefile.common -index 5f0ef969857..2ff9b39357c 100644 ---- a/conf/Makefile.common -+++ b/conf/Makefile.common -@@ -40,24 +40,25 @@ CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 - CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) - STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -R .note.gnu.property -R .gnu.build.attributes - --CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding --LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d --CPPFLAGS_MODULE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) --CCASFLAGS_MODULE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) -+CFLAGS_MODULE = $(TARGET_CFLAGS) $(CFLAGS_PLATFORM) -ffreestanding -+LDFLAGS_MODULE = $(TARGET_LDFLAGS) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d -+CPPFLAGS_MODULE = $(TARGET_CPPFLAGS) $(CPPFLAGS_DEFAULT) $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -+CCASFLAGS_MODULE = $(TARGET_CCASFLAGS) $(CCASFLAGS_DEFAULT) $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) - - CFLAGS_IMAGE = $(CFLAGS_PLATFORM) -fno-builtin - LDFLAGS_IMAGE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S - CPPFLAGS_IMAGE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) - CCASFLAGS_IMAGE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) - --CFLAGS_PROGRAM = --LDFLAGS_PROGRAM = --CPPFLAGS_PROGRAM = --CCASFLAGS_PROGRAM = -+CFLAGS_PROGRAM = $(UTILS_CFLAGS) -+LDFLAGS_PROGRAM = $(UTILS_LDFLAGS) -+CPPFLAGS_PROGRAM = $(UTILS_CPPFLAGS) -+CCASFLAGS_PROGRAM = $(UTILS_CCASFLAGS) - --CFLAGS_LIBRARY = --CPPFLAGS_LIBRARY = --CCASFLAGS_LIBRARY = -+CFLAGS_LIBRARY = $(UTILS_CFLAGS) -+LDFLAGS_LIBRARY = $(UTILS_LDFLAGS) -+CPPFLAGS_LIBRARY = $(UTILS_CPPFLAGS) -+CCASFLAGS_LIBRARY = $(UTILS_CCASFLAGS) - - # Other variables - -diff --git a/gentpl.py b/gentpl.py -index 34a4eba2b42..59f62ef9522 100644 ---- a/gentpl.py -+++ b/gentpl.py -@@ -697,10 +697,10 @@ def module(defn, platform): - var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform) + " ## platform sources") - var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources") - var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform)) -- var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_MODULE) " + platform_cflags(defn, platform)) -- var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_MODULE) " + platform_ldflags(defn, platform)) -- var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform)) -- var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform)) -+ var_set(cname(defn) + "_CFLAGS", "$(CFLAGS_MODULE) " + platform_cflags(defn, platform)) -+ var_set(cname(defn) + "_LDFLAGS", "$(LDFLAGS_MODULE) " + platform_ldflags(defn, platform)) -+ var_set(cname(defn) + "_CPPFLAGS", "$(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform)) -+ var_set(cname(defn) + "_CCASFLAGS", "$(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform)) - var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF) " + platform_dependencies(defn, platform)) - - gvar_add("dist_noinst_DATA", extra_dist(defn)) diff --git a/SOURCES/0106-Do-not-allow-stack-trampolines-anywhere.patch b/SOURCES/0106-Do-not-allow-stack-trampolines-anywhere.patch new file mode 100644 index 0000000..658c7a4 --- /dev/null +++ b/SOURCES/0106-Do-not-allow-stack-trampolines-anywhere.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 12 Jul 2019 10:06:50 +0200 +Subject: [PATCH] Do not allow stack trampolines, anywhere. + +Signed-off-by: Peter Jones +--- + configure.ac | 3 +++ + conf/Makefile.common | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 490353713a..a02d40a05b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1998,6 +1998,9 @@ if test x"$enable_wextra" != xno ; then + HOST_CFLAGS="$HOST_CFLAGS -Wextra" + fi + ++TARGET_CFLAGS="$TARGET_CFLAGS -Werror=trampolines -fno-trampolines" ++HOST_CFLAGS="$HOST_CFLAGS -Werror=trampolines -fno-trampolines" ++ + TARGET_CPP="$TARGET_CC -E" + TARGET_CCAS=$TARGET_CC + +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 35e14ff017..0647c53b91 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -66,7 +66,7 @@ grubconfdir = $(sysconfdir)/grub.d + platformdir = $(pkglibdir)/$(target_cpu)-$(platform) + starfielddir = $(pkgdatadir)/themes/starfield + +-CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code ++CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Werror=trampolines -fno-trampolines + CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib + + CFLAGS_POSIX = -fno-builtin diff --git a/SOURCES/0106-module-verifier-make-it-possible-to-run-checkers-on-.patch b/SOURCES/0106-module-verifier-make-it-possible-to-run-checkers-on-.patch deleted file mode 100644 index e31b38f..0000000 --- a/SOURCES/0106-module-verifier-make-it-possible-to-run-checkers-on-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 1 Aug 2018 10:24:52 -0400 -Subject: [PATCH] module-verifier: make it possible to run checkers on - grub-module-verifierxx.c - -This makes it so you can treat grub-module-verifierxx.c as a file you can -build directly, so syntax checkers like vim's "syntastic" plugin, which uses -"gcc -x c -fsyntax-only" to build it, will work. - -One still has to do whatever setup is required to make it pick the right -include dirs, which -W options we use, etc., but this makes it so you can do -the checking on the file you're editing, rather than on a different file. - -v2: fix the typo in the #else clause in util/grub-module-verifierXX.c - -Signed-off-by: Peter Jones ---- - util/grub-module-verifier32.c | 2 ++ - util/grub-module-verifier64.c | 2 ++ - util/grub-module-verifierXX.c | 9 +++++++++ - 3 files changed, 13 insertions(+) - -diff --git a/util/grub-module-verifier32.c b/util/grub-module-verifier32.c -index 257229f8f08..ba7d41aafea 100644 ---- a/util/grub-module-verifier32.c -+++ b/util/grub-module-verifier32.c -@@ -1,2 +1,4 @@ - #define MODULEVERIFIER_ELF32 1 -+#ifndef GRUB_MODULE_VERIFIERXX - #include "grub-module-verifierXX.c" -+#endif -diff --git a/util/grub-module-verifier64.c b/util/grub-module-verifier64.c -index 4db6b4bedd1..fc23ef800b3 100644 ---- a/util/grub-module-verifier64.c -+++ b/util/grub-module-verifier64.c -@@ -1,2 +1,4 @@ - #define MODULEVERIFIER_ELF64 1 -+#ifndef GRUB_MODULE_VERIFIERXX - #include "grub-module-verifierXX.c" -+#endif -diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c -index ceb24309aec..a98e2f9b1ac 100644 ---- a/util/grub-module-verifierXX.c -+++ b/util/grub-module-verifierXX.c -@@ -1,3 +1,12 @@ -+#define GRUB_MODULE_VERIFIERXX -+#if !defined(MODULEVERIFIER_ELF32) && !defined(MODULEVERIFIER_ELF64) -+#if __SIZEOF_POINTER__ == 8 -+#include "grub-module-verifier64.c" -+#else -+#include "grub-module-verifier32.c" -+#endif -+#endif -+ - #include - - #include diff --git a/SOURCES/0107-Reimplement-boot_counter.patch b/SOURCES/0107-Reimplement-boot_counter.patch new file mode 100644 index 0000000..d018de4 --- /dev/null +++ b/SOURCES/0107-Reimplement-boot_counter.patch @@ -0,0 +1,196 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 4 Oct 2018 14:22:09 -0400 +Subject: [PATCH] Reimplement boot_counter + +This adds "increment" and "decrement" commands, and uses them to maintain our +variables in 01_fallback_counter. It also simplifies the counter logic, so +that there are no nested tests that conflict with each other. + +Apparently, this *really* wasn't tested well enough. + +Resolves: rhbz#1614637 +Signed-off-by: Peter Jones +[lorbus: add comments and revert logic changes in 01_fallback_counting] +Signed-off-by: Christian Glombek +--- + Makefile.util.def | 6 +++ + grub-core/Makefile.core.def | 5 ++ + grub-core/commands/increment.c | 105 ++++++++++++++++++++++++++++++++++++ + util/grub.d/01_fallback_counting.in | 22 ++++++++ + 4 files changed, 138 insertions(+) + create mode 100644 grub-core/commands/increment.c + create mode 100644 util/grub.d/01_fallback_counting.in + +diff --git a/Makefile.util.def b/Makefile.util.def +index d066652e9b..e10fe766d1 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -458,6 +458,12 @@ script = { + installdir = grubconf; + }; + ++script = { ++ name = '01_fallback_counting'; ++ common = util/grub.d/01_fallback_counting.in; ++ installdir = grubconf; ++}; ++ + script = { + name = '01_menu_auto_hide'; + common = util/grub.d/01_menu_auto_hide.in; +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 4f203533f5..ea4d59f51b 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -398,6 +398,11 @@ kernel = { + extra_dist = kern/mips/cache_flush.S; + }; + ++module = { ++ name = increment; ++ common = commands/increment.c; ++}; ++ + program = { + name = grub-emu; + mansection = 1; +diff --git a/grub-core/commands/increment.c b/grub-core/commands/increment.c +new file mode 100644 +index 0000000000..79cf137656 +--- /dev/null ++++ b/grub-core/commands/increment.c +@@ -0,0 +1,105 @@ ++/* increment.c - Commands to increment and decrement variables. */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++typedef enum { ++ INCREMENT, ++ DECREMENT, ++} operation; ++ ++static grub_err_t ++incr_decr(operation op, int argc, char **args) ++{ ++ const char *old; ++ char *new; ++ long value; ++ ++ if (argc < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no variable specified")); ++ if (argc > 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("too many arguments")); ++ ++ old = grub_env_get (*args); ++ if (!old) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("No such variable \"%s\""), ++ *args); ++ ++ value = grub_strtol (old, NULL, 0); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ ++ switch (op) ++ { ++ case INCREMENT: ++ value += 1; ++ break; ++ case DECREMENT: ++ value -= 1; ++ break; ++ } ++ ++ new = grub_xasprintf ("%ld", value); ++ if (!new) ++ return grub_errno; ++ ++ grub_env_set (*args, new); ++ grub_free (new); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_incr(struct grub_command *cmd UNUSED, ++ int argc, char **args) ++{ ++ return incr_decr(INCREMENT, argc, args); ++} ++ ++static grub_err_t ++grub_cmd_decr(struct grub_command *cmd UNUSED, ++ int argc, char **args) ++{ ++ return incr_decr(DECREMENT, argc, args); ++} ++ ++static grub_command_t cmd_incr, cmd_decr; ++ ++GRUB_MOD_INIT(increment) ++{ ++ cmd_incr = grub_register_command ("increment", grub_cmd_incr, N_("VARIABLE"), ++ N_("increment VARIABLE")); ++ cmd_decr = grub_register_command ("decrement", grub_cmd_decr, N_("VARIABLE"), ++ N_("decrement VARIABLE")); ++} ++ ++GRUB_MOD_FINI(increment) ++{ ++ grub_unregister_command (cmd_incr); ++ grub_unregister_command (cmd_decr); ++} +diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/01_fallback_counting.in +new file mode 100644 +index 0000000000..be0e770ea8 +--- /dev/null ++++ b/util/grub.d/01_fallback_counting.in +@@ -0,0 +1,22 @@ ++#! /bin/sh -e ++ ++# Boot Counting ++# The boot_counter env var can be used to count down boot attempts after an ++# OSTree upgrade and choose the rollback deployment when 0 is reached. Both ++# boot_counter and boot_success need to be (re-)set from userspace. ++cat << EOF ++insmod increment ++# Check if boot_counter exists and boot_success=0 to activate this behaviour. ++if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then ++ # if countdown has ended, choose to boot rollback deployment (default=1 on ++ # OSTree-based systems) ++ if [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then ++ set default=1 ++ set boot_counter=-1 ++ # otherwise decrement boot_counter ++ else ++ decrement boot_counter ++ fi ++ save_env boot_counter ++fi ++EOF diff --git a/SOURCES/0107-Rework-how-the-fdt-command-builds.patch b/SOURCES/0107-Rework-how-the-fdt-command-builds.patch deleted file mode 100644 index 71328da..0000000 --- a/SOURCES/0107-Rework-how-the-fdt-command-builds.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 11 Jul 2019 13:01:41 +0200 -Subject: [PATCH] Rework how the fdt command builds. - -Trying to avoid all variants of: -cat syminfo.lst | sort | gawk -f ../../grub-core/genmoddep.awk > moddep.lst || (rm -f moddep.lst; exit 1) -grub_fdt_install in linux is not defined -grub_fdt_load in linux is not defined -grub_fdt_unload in linux is not defined -grub_fdt_install in xen_boot is not defined -grub_fdt_load in xen_boot is not defined -grub_fdt_unload in xen_boot is not defined - -Signed-off-by: Peter Jones ---- - grub-core/Makefile.core.def | 5 ++--- - grub-core/lib/fdt.c | 2 -- - grub-core/loader/efi/fdt.c | 2 ++ - include/grub/fdt.h | 4 ++++ - grub-core/Makefile.am | 1 + - 5 files changed, 9 insertions(+), 5 deletions(-) - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index c40170f2dd2..84a3d89de9a 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -177,7 +177,6 @@ kernel = { - arm_coreboot = kern/arm/coreboot/init.c; - arm_coreboot = kern/arm/coreboot/timer.c; - arm_coreboot = kern/arm/coreboot/coreboot.S; -- arm_coreboot = lib/fdt.c; - arm_coreboot = bus/fdt.c; - arm_coreboot = term/ps2.c; - arm_coreboot = term/arm/pl050.c; -@@ -351,6 +350,8 @@ kernel = { - riscv64 = kern/riscv/cache_flush.S; - riscv64 = kern/riscv/dl.c; - -+ fdt = lib/fdt.c; -+ - emu = disk/host.c; - emu = kern/emu/cache_s.S; - emu = kern/emu/hostdisk.c; -@@ -1825,7 +1826,6 @@ module = { - riscv32 = loader/riscv/linux.c; - riscv64 = loader/riscv/linux.c; - emu = loader/emu/linux.c; -- fdt = lib/fdt.c; - - common = loader/linux.c; - common = lib/cmdline.c; -@@ -1836,7 +1836,6 @@ module = { - module = { - name = fdt; - efi = loader/efi/fdt.c; -- common = lib/fdt.c; - enable = fdt; - }; - -diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c -index 0d371c5633e..37e04bd69e7 100644 ---- a/grub-core/lib/fdt.c -+++ b/grub-core/lib/fdt.c -@@ -21,8 +21,6 @@ - #include - #include - --GRUB_MOD_LICENSE ("GPLv3+"); -- - #define FDT_SUPPORTED_VERSION 17 - - #define FDT_BEGIN_NODE 0x00000001 -diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c -index c86f283d756..c572415d38a 100644 ---- a/grub-core/loader/efi/fdt.c -+++ b/grub-core/loader/efi/fdt.c -@@ -27,6 +27,8 @@ - #include - #include - -+GRUB_MOD_LICENSE ("GPLv3+"); -+ - static void *loaded_fdt; - static void *fdt; - -diff --git a/include/grub/fdt.h b/include/grub/fdt.h -index e609c7e4111..22b7c5463fc 100644 ---- a/include/grub/fdt.h -+++ b/include/grub/fdt.h -@@ -19,6 +19,8 @@ - #ifndef GRUB_FDT_HEADER - #define GRUB_FDT_HEADER 1 - -+#if defined(__arm__) || defined(__aarch64__) -+ - #include - #include - -@@ -144,4 +146,6 @@ int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const ch - grub_fdt_set_prop ((fdt), (nodeoffset), "reg", reg_64, 16); \ - }) - -+#endif /* defined(__arm__) || defined(__aarch64__) */ -+ - #endif /* ! GRUB_FDT_HEADER */ -diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index f512573c0da..dd49939aaa9 100644 ---- a/grub-core/Makefile.am -+++ b/grub-core/Makefile.am -@@ -76,6 +76,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h -+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/file.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h - KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h diff --git a/SOURCES/0108-Disable-non-wordsize-allocations-on-arm.patch b/SOURCES/0108-Disable-non-wordsize-allocations-on-arm.patch deleted file mode 100644 index f614c9e..0000000 --- a/SOURCES/0108-Disable-non-wordsize-allocations-on-arm.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 2 Aug 2018 10:56:38 -0400 -Subject: [PATCH] Disable non-wordsize allocations on arm - -Signed-off-by: Peter Jones ---- - configure.ac | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/configure.ac b/configure.ac -index 3405348178a..152e7dba652 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1288,6 +1288,26 @@ if test "x$target_cpu" = xarm; then - done - ]) - -+ AC_CACHE_CHECK([for options to disable movt and movw relocations], -+ grub_cv_target_cc_mword_relocations, -+ [grub_cv_target_cc_mword_relocations=no -+ for cand in "-mword-relocations" ; do -+ if test x"$grub_cv_target_cc_mword_relocations" != xno ; then -+ break -+ fi -+ CFLAGS="$TARGET_CFLAGS $cand -Werror" -+ CPPFLAGS="$TARGET_CPPFLAGS" -+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], -+ [grub_cv_target_cc_mword_relocations="$cand"], -+ []) -+ done -+ ]) -+ if test x"$grub_cv_target_cc_mword_relocations" = xno ; then -+ AC_MSG_ERROR(["your compiler doesn't support disabling movw/movt relocations"]) -+ else -+ TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mword_relocations" -+ fi -+ - if test x"$grub_cv_target_cc_mno_movt" != xno ; then - # A trick so that clang doesn't see it on link stage - TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_mno_movt" diff --git a/SOURCES/0108-Fix-menu-entry-selection-based-on-ID-and-title.patch b/SOURCES/0108-Fix-menu-entry-selection-based-on-ID-and-title.patch new file mode 100644 index 0000000..af74901 --- /dev/null +++ b/SOURCES/0108-Fix-menu-entry-selection-based-on-ID-and-title.patch @@ -0,0 +1,233 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 19 Oct 2018 10:57:52 -0400 +Subject: [PATCH] Fix menu entry selection based on ID and title + +Currently if grub_strtoul(saved_entry_value, NULL, 0) does not return an +error, we assume the value it has produced is a correct index into our +menu entry list, and do not try to interpret the value as the "id" or +"title" . In cases where "id" or "title" start with a numeral, this +makes them impossible to use as selection criteria. + +This patch splits the search into three phases - matching id, matching +title, and only once those have been exhausted, trying to interpret the +ID as a numeral. In that case, we also require that the entire string +is numeric, not merely a string with leading numeric characters. + +Resolves: rhbz#1640979 + +Signed-off-by: Peter Jones +[javierm: fix menu entry selection based on title] +Signed-off-by: Javier Martinez Canillas +--- + grub-core/normal/menu.c | 141 ++++++++++++++++++++++++------------------------ + 1 file changed, 71 insertions(+), 70 deletions(-) + +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index d7a222e681..4a02aadb01 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -164,12 +164,12 @@ grub_menu_set_timeout (int timeout) + } + + static int +-menuentry_eq (const char *id, const char *spec) ++menuentry_eq (const char *id, const char *spec, int limit) + { + const char *ptr1, *ptr2; + ptr1 = id; + ptr2 = spec; +- while (1) ++ while (limit == -1 || ptr1 - id <= limit) + { + if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0) + return ptr2 - spec; +@@ -178,7 +178,11 @@ menuentry_eq (const char *id, const char *spec) + if (*ptr2 == '>') + ptr2++; + if (*ptr1 != *ptr2) +- return 0; ++ { ++ if (limit > -1 && ptr1 - id == limit && !*ptr1 && grub_isspace(*ptr2)) ++ return ptr1 -id -1; ++ return 0; ++ } + if (*ptr1 == 0) + return ptr1 - id; + ptr1++; +@@ -187,6 +191,58 @@ menuentry_eq (const char *id, const char *spec) + return 0; + } + ++static int ++get_entry_number_helper(grub_menu_t menu, ++ const char * const val, const char ** const tail) ++{ ++ /* See if the variable matches the title of a menu entry. */ ++ int entry = -1; ++ grub_menu_entry_t e; ++ int i; ++ ++ for (i = 0, e = menu->entry_list; e; i++) ++ { ++ int l = 0; ++ while (val[l] && !grub_isspace(val[l])) ++ l++; ++ ++ if (menuentry_eq (e->id, val, l)) ++ { ++ if (tail) ++ *tail = val + l; ++ return i; ++ } ++ e = e->next; ++ } ++ ++ for (i = 0, e = menu->entry_list; e; i++) ++ { ++ ++ if (menuentry_eq (e->title, val, -1)) ++ { ++ if (tail) ++ *tail = NULL; ++ return i; ++ } ++ e = e->next; ++ } ++ ++ if (tail) ++ *tail = NULL; ++ ++ entry = (int) grub_strtoul (val, tail, 0); ++ if (grub_errno == GRUB_ERR_BAD_NUMBER || ++ (*tail && **tail && !grub_isspace(**tail))) ++ { ++ entry = -1; ++ if (tail) ++ *tail = NULL; ++ grub_errno = GRUB_ERR_NONE; ++ } ++ ++ return entry; ++} ++ + /* Get the first entry number from the value of the environment variable NAME, + which is a space-separated list of non-negative integers. The entry number + which is returned is stripped from the value of NAME. If no entry number +@@ -196,7 +252,6 @@ get_and_remove_first_entry_number (grub_menu_t menu, const char *name) + { + const char *val, *tail; + int entry; +- int sz = 0; + + val = grub_env_get (name); + if (! val) +@@ -204,50 +259,24 @@ get_and_remove_first_entry_number (grub_menu_t menu, const char *name) + + grub_error_push (); + +- entry = (int) grub_strtoul (val, &tail, 0); ++ entry = get_entry_number_helper(menu, val, &tail); ++ if (!(*tail == 0 || grub_isspace(*tail))) ++ entry = -1; + +- if (grub_errno == GRUB_ERR_BAD_NUMBER) ++ if (entry >= 0) + { +- /* See if the variable matches the title of a menu entry. */ +- grub_menu_entry_t e = menu->entry_list; +- int i; +- +- for (i = 0; e; i++) +- { +- sz = menuentry_eq (e->title, val); +- if (sz < 1) +- sz = menuentry_eq (e->id, val); +- +- if (sz >= 1) +- { +- entry = i; +- break; +- } +- e = e->next; +- } +- +- if (sz > 0) +- grub_errno = GRUB_ERR_NONE; +- +- if (! e) +- entry = -1; +- } +- +- if (grub_errno == GRUB_ERR_NONE) +- { +- if (sz > 0) +- tail += sz; +- + /* Skip whitespace to find the next entry. */ + while (*tail && grub_isspace (*tail)) + tail++; +- grub_env_set (name, tail); ++ if (*tail) ++ grub_env_set (name, tail); ++ else ++ grub_env_unset (name); + } + else + { + grub_env_unset (name); + grub_errno = GRUB_ERR_NONE; +- entry = -1; + } + + grub_error_pop (); +@@ -524,6 +553,7 @@ static int + get_entry_number (grub_menu_t menu, const char *name) + { + const char *val; ++ const char *tail; + int entry; + + val = grub_env_get (name); +@@ -531,38 +561,9 @@ get_entry_number (grub_menu_t menu, const char *name) + return -1; + + grub_error_push (); +- +- entry = (int) grub_strtoul (val, 0, 0); +- +- if (grub_errno == GRUB_ERR_BAD_NUMBER) +- { +- /* See if the variable matches the title of a menu entry. */ +- grub_menu_entry_t e = menu->entry_list; +- int i; +- +- grub_errno = GRUB_ERR_NONE; +- +- for (i = 0; e; i++) +- { +- if (menuentry_eq (e->title, val) +- || menuentry_eq (e->id, val)) +- { +- entry = i; +- break; +- } +- e = e->next; +- } +- +- if (! e) +- entry = -1; +- } +- +- if (grub_errno != GRUB_ERR_NONE) +- { +- grub_errno = GRUB_ERR_NONE; +- entry = -1; +- } +- ++ entry = get_entry_number_helper(menu, val, &tail); ++ if (tail && *tail != '\0') ++ entry = -1; + grub_error_pop (); + + return entry; diff --git a/SOURCES/0109-Make-the-menu-entry-users-option-argument-to-be-opti.patch b/SOURCES/0109-Make-the-menu-entry-users-option-argument-to-be-opti.patch new file mode 100644 index 0000000..68779eb --- /dev/null +++ b/SOURCES/0109-Make-the-menu-entry-users-option-argument-to-be-opti.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 26 Nov 2018 10:06:42 +0100 +Subject: [PATCH] Make the menu entry users option argument to be optional + +The --users option is used to restrict the access to specific menu entries +only to a set of users. But the option requires an argument to either be a +constant or a variable that has been set. So for example the following: + + menuentry "May be run by superusers or users in $users" --users $users { + linux /vmlinuz + } + +Would fail if $users is not defined and grub would discard the menu entry. +Instead, allow the --users option to have an optional argument and ignore +the option if the argument was not set. + +Related: rhbz#1652434 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/commands/menuentry.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c +index b194123eb6..b175a1b43b 100644 +--- a/grub-core/commands/menuentry.c ++++ b/grub-core/commands/menuentry.c +@@ -29,7 +29,7 @@ static const struct grub_arg_option options[] = + { + {"class", 1, GRUB_ARG_OPTION_REPEATABLE, + N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING}, +- {"users", 2, 0, ++ {"users", 2, GRUB_ARG_OPTION_OPTIONAL, + N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"), + ARG_TYPE_STRING}, + {"hotkey", 3, 0, +@@ -281,7 +281,7 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) + if (! ctxt->state[3].set && ! ctxt->script) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition"); + +- if (ctxt->state[1].set) ++ if (ctxt->state[1].set && ctxt->state[1].arg) + users = ctxt->state[1].arg; + else if (ctxt->state[5].set) + users = NULL; diff --git a/SOURCES/0109-Prepend-prefix-when-HTTP-path-is-relative.patch b/SOURCES/0109-Prepend-prefix-when-HTTP-path-is-relative.patch deleted file mode 100644 index fc861d9..0000000 --- a/SOURCES/0109-Prepend-prefix-when-HTTP-path-is-relative.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Stephen Benjamin -Date: Thu, 16 Aug 2018 16:58:51 -0400 -Subject: [PATCH] Prepend prefix when HTTP path is relative - -This sets a couple of variables. With the url http://www.example.com/foo/bar : -http_path: /foo/bar -http_url: http://www.example.com/foo/bar - -Signed-off-by: Peter Jones ---- - grub-core/kern/main.c | 10 +++++- - grub-core/net/efi/http.c | 82 ++++++++++++++++++++++++++++++++++++------------ - 2 files changed, 71 insertions(+), 21 deletions(-) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index 48058d983ce..4ec3f5e4d33 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -131,11 +131,19 @@ grub_set_prefix_and_root (void) - if (fwdevice && fwpath) - { - char *fw_path; -+ char separator[3] = ")"; - -- fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath); -+ grub_dprintf ("fw_path", "\n"); -+ grub_dprintf ("fw_path", "fwdevice:\"%s\" fwpath:\"%s\"\n", fwdevice, fwpath); -+ -+ if (!grub_strncmp(fwdevice, "http", 4) && fwpath[0] != '/') -+ grub_strcpy(separator, ")/"); -+ -+ fw_path = grub_xasprintf ("(%s%s%s", fwdevice, separator, fwpath); - if (fw_path) - { - grub_env_set ("fw_path", fw_path); -+ grub_dprintf ("fw_path", "fw_path:\"%s\"\n", fw_path); - grub_free (fw_path); - } - } -diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c -index 243acbaa35b..de351b2cd03 100644 ---- a/grub-core/net/efi/http.c -+++ b/grub-core/net/efi/http.c -@@ -9,10 +9,52 @@ - static void - http_configure (struct grub_efi_net_device *dev, int prefer_ip6) - { -+ grub_efi_ipv6_address_t address; - grub_efi_http_config_data_t http_config; - grub_efi_httpv4_access_point_t httpv4_node; - grub_efi_httpv6_access_point_t httpv6_node; - grub_efi_status_t status; -+ int https; -+ char *http_url; -+ const char *rest, *http_server, *http_path = NULL; -+ -+ http_server = grub_env_get ("root"); -+ https = (grub_strncmp (http_server, "https", 5) == 0) ? 1 : 0; -+ -+ /* extract http server + port */ -+ if (http_server) -+ { -+ http_server = grub_strchr (http_server, ','); -+ if (http_server) -+ http_server++; -+ } -+ -+ /* fw_path is like (http,192.168.1.1:8000)/httpboot, extract path part */ -+ http_path = grub_env_get ("fw_path"); -+ if (http_path) -+ { -+ http_path = grub_strchr (http_path, ')'); -+ if (http_path) -+ { -+ http_path++; -+ grub_env_unset ("http_path"); -+ grub_env_set ("http_path", http_path); -+ } -+ } -+ -+ if (http_server && http_path) -+ { -+ if (grub_efi_string_to_ip6_address (http_server, &address, &rest) && *rest == 0) -+ http_url = grub_xasprintf ("%s://[%s]%s", https ? "https" : "http", http_server, http_path); -+ else -+ http_url = grub_xasprintf ("%s://%s%s", https ? "https" : "http", http_server, http_path); -+ if (http_url) -+ { -+ grub_env_unset ("http_url"); -+ grub_env_set ("http_url", http_url); -+ grub_free (http_url); -+ } -+ } - - grub_efi_http_t *http = dev->http; - -@@ -352,32 +394,32 @@ grub_efihttp_open (struct grub_efi_net_device *dev, - grub_err_t err; - grub_off_t size; - char *buf; -- char *root_url; -- grub_efi_ipv6_address_t address; -- const char *rest; -+ char *file_name = NULL; -+ const char *http_path; - -- if (grub_efi_string_to_ip6_address (file->device->net->server, &address, &rest) && *rest == 0) -- root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", file->device->net->server); -- else -- root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", file->device->net->server); -- if (root_url) -- { -- grub_env_unset ("root_url"); -- grub_env_set ("root_url", root_url); -- grub_free (root_url); -- } -- else -- { -+ /* If path is relative, prepend http_path */ -+ http_path = grub_env_get ("http_path"); -+ if (http_path && file->device->net->name[0] != '/') { -+ file_name = grub_xasprintf ("%s/%s", http_path, file->device->net->name); -+ if (!file_name) - return grub_errno; -- } -+ } - -- err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); -+ err = efihttp_request (dev->http, file->device->net->server, -+ file_name ? file_name : file->device->net->name, type, 1, 0); - if (err != GRUB_ERR_NONE) -- return err; -+ { -+ grub_free (file_name); -+ return err; -+ } - -- err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size); -+ err = efihttp_request (dev->http, file->device->net->server, -+ file_name ? file_name : file->device->net->name, type, 0, &size); -+ grub_free (file_name); - if (err != GRUB_ERR_NONE) -- return err; -+ { -+ return err; -+ } - - buf = grub_malloc (size); - efihttp_read (dev, buf, size); diff --git a/SOURCES/0110-Add-efi-export-env-and-efi-load-env-commands.patch b/SOURCES/0110-Add-efi-export-env-and-efi-load-env-commands.patch new file mode 100644 index 0000000..33d2724 --- /dev/null +++ b/SOURCES/0110-Add-efi-export-env-and-efi-load-env-commands.patch @@ -0,0 +1,346 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 16 Jan 2019 13:21:46 -0500 +Subject: [PATCH] Add efi-export-env and efi-load-env commands + +This adds "efi-export-env VARIABLE" and "efi-load-env", which manipulate the +environment block stored in the EFI variable +GRUB_ENV-91376aff-cba6-42be-949d-06fde81128e8. + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 6 ++ + grub-core/commands/efi/env.c | 168 +++++++++++++++++++++++++++++++++++++++++++ + grub-core/kern/efi/efi.c | 3 + + grub-core/kern/efi/init.c | 5 -- + grub-core/lib/envblk.c | 43 +++++++++++ + util/grub-set-bootflag.c | 1 + + include/grub/efi/efi.h | 5 ++ + include/grub/lib/envblk.h | 3 + + 8 files changed, 229 insertions(+), 5 deletions(-) + create mode 100644 grub-core/commands/efi/env.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index ea4d59f51b..dc9fea6f44 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -820,6 +820,12 @@ module = { + enable = efi; + }; + ++module = { ++ name = efienv; ++ common = commands/efi/env.c; ++ enable = efi; ++}; ++ + module = { + name = efifwsetup; + efi = commands/efi/efifwsetup.c; +diff --git a/grub-core/commands/efi/env.c b/grub-core/commands/efi/env.c +new file mode 100644 +index 0000000000..cbd13e03e8 +--- /dev/null ++++ b/grub-core/commands/efi/env.c +@@ -0,0 +1,168 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2012 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static const grub_efi_guid_t grub_env_guid = GRUB_EFI_GRUB_VARIABLE_GUID; ++ ++static grub_err_t ++grub_efi_export_env(grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ const char *value; ++ char *old_value; ++ struct grub_envblk envblk_s = { NULL, 0 }; ++ grub_envblk_t envblk = &envblk_s; ++ grub_err_t err; ++ int changed = 1; ++ grub_efi_status_t status; ++ ++ grub_dprintf ("efienv", "argc:%d\n", argc); ++ for (int i = 0; i < argc; i++) ++ grub_dprintf ("efienv", "argv[%d]: %s\n", i, argv[i]); ++ ++ if (argc != 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable name expected")); ++ ++ grub_efi_get_variable ("GRUB_ENV", &grub_env_guid, &envblk_s.size, ++ (void **) &envblk_s.buf); ++ if (!envblk_s.buf || envblk_s.size < 1) ++ { ++ char *buf = grub_malloc (1025); ++ if (!buf) ++ return grub_errno; ++ ++ grub_memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); ++ grub_memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', ++ DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); ++ buf[1024] = '\0'; ++ ++ envblk_s.buf = buf; ++ envblk_s.size = 1024; ++ } ++ else ++ { ++ char *buf = grub_realloc (envblk_s.buf, envblk_s.size + 1); ++ if (!buf) ++ return grub_errno; ++ ++ envblk_s.buf = buf; ++ envblk_s.buf[envblk_s.size] = '\0'; ++ } ++ ++ err = grub_envblk_get(envblk, argv[0], &old_value); ++ if (err != GRUB_ERR_NONE) ++ { ++ grub_dprintf ("efienv", "grub_envblk_get returned %d\n", err); ++ return err; ++ } ++ ++ value = grub_env_get(argv[0]); ++ if ((!value && !old_value) || ++ (value && old_value && !grub_strcmp(old_value, value))) ++ changed = 0; ++ ++ if (old_value) ++ grub_free(old_value); ++ ++ if (changed == 0) ++ { ++ grub_dprintf ("efienv", "No changes necessary\n"); ++ return 0; ++ } ++ ++ if (value) ++ { ++ grub_dprintf ("efienv", "setting \"%s\" to \"%s\"\n", argv[0], value); ++ grub_envblk_set(envblk, argv[0], value); ++ } ++ else ++ { ++ grub_dprintf ("efienv", "deleting \"%s\" from envblk\n", argv[0]); ++ grub_envblk_delete(envblk, argv[0]); ++ } ++ ++ grub_dprintf ("efienv", "envblk is %lu bytes:\n\"%s\"\n", envblk_s.size, envblk_s.buf); ++ ++ grub_dprintf ("efienv", "removing GRUB_ENV\n"); ++ status = grub_efi_set_variable ("GRUB_ENV", &grub_env_guid, NULL, 0); ++ if (status != GRUB_EFI_SUCCESS) ++ grub_dprintf ("efienv", "removal returned %ld\n", status); ++ ++ grub_dprintf ("efienv", "setting GRUB_ENV\n"); ++ status = grub_efi_set_variable ("GRUB_ENV", &grub_env_guid, ++ envblk_s.buf, envblk_s.size); ++ if (status != GRUB_EFI_SUCCESS) ++ grub_dprintf ("efienv", "setting GRUB_ENV returned %ld\n", status); ++ ++ return 0; ++} ++ ++static int ++set_var (const char *name, const char *value, ++ void *whitelist __attribute__((__unused__))) ++{ ++ grub_env_set (name, value); ++ return 0; ++} ++ ++static grub_err_t ++grub_efi_load_env(grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[] __attribute__((__unused__))) ++{ ++ struct grub_envblk envblk_s = { NULL, 0 }; ++ grub_envblk_t envblk = &envblk_s; ++ ++ grub_efi_get_variable ("GRUB_ENV", &grub_env_guid, &envblk_s.size, ++ (void **) &envblk_s.buf); ++ if (!envblk_s.buf || envblk_s.size < 1) ++ return 0; ++ ++ if (argc > 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unexpected argument")); ++ ++ grub_envblk_iterate (envblk, NULL, set_var); ++ grub_free (envblk_s.buf); ++} ++ ++static grub_command_t export_cmd, loadenv_cmd; ++ ++GRUB_MOD_INIT(lsefi) ++{ ++ export_cmd = grub_register_command ("efi-export-env", grub_efi_export_env, ++ N_("VARIABLE_NAME"), N_("Export environment variable to UEFI.")); ++ loadenv_cmd = grub_register_command ("efi-load-env", grub_efi_load_env, ++ NULL, N_("Load the grub environment from UEFI.")); ++} ++ ++GRUB_MOD_FINI(lsefi) ++{ ++ grub_unregister_command (export_cmd); ++ grub_unregister_command (loadenv_cmd); ++} +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 2a446f5031..14bc10eb56 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -225,6 +225,9 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, + if (status == GRUB_EFI_SUCCESS) + return GRUB_ERR_NONE; + ++ if (status == GRUB_EFI_NOT_FOUND && datasize == 0) ++ return GRUB_ERR_NONE; ++ + return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var); + } + +diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c +index 2d12e6188f..0574d8d621 100644 +--- a/grub-core/kern/efi/init.c ++++ b/grub-core/kern/efi/init.c +@@ -85,11 +85,6 @@ stack_protector_init (void) + + grub_addr_t grub_modbase; + +-#define GRUB_EFI_GRUB_VARIABLE_GUID \ +- { 0x91376aff, 0xcba6, 0x42be, \ +- { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \ +- } +- + /* Helper for grub_efi_env_init */ + static int + set_var (const char *name, const char *value, +diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c +index 2e4e78b132..874506da16 100644 +--- a/grub-core/lib/envblk.c ++++ b/grub-core/lib/envblk.c +@@ -223,6 +223,49 @@ grub_envblk_delete (grub_envblk_t envblk, const char *name) + } + } + ++struct get_var_state { ++ const char * const name; ++ char * value; ++ int found; ++}; ++ ++static int ++get_var (const char * const name, const char * const value, void *statep) ++{ ++ struct get_var_state *state = (struct get_var_state *)statep; ++ ++ if (!grub_strcmp(state->name, name)) ++ { ++ state->found = 1; ++ state->value = grub_strdup(value); ++ if (!state->value) ++ grub_errno = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++grub_err_t ++grub_envblk_get (grub_envblk_t envblk, const char * const name, char ** const value) ++{ ++ struct get_var_state state = { ++ .name = name, ++ .value = NULL, ++ .found = 0, ++ }; ++ ++ grub_envblk_iterate(envblk, (void *)&state, get_var); ++ ++ *value = state.value; ++ ++ if (state.found && !state.value) ++ return grub_errno; ++ ++ return GRUB_ERR_NONE; ++} ++ + void + grub_envblk_iterate (grub_envblk_t envblk, + void *hook_data, +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index d506f7e75b..a6ccc11383 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -25,6 +25,7 @@ + + #include /* For *_DIR_NAME defines */ + #include ++#include + #include /* For GRUB_ENVBLK_DEFCFG define */ + #include + #include +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 2e0691454b..8dfc89a33b 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -24,6 +24,11 @@ + #include + #include + ++#define GRUB_EFI_GRUB_VARIABLE_GUID \ ++ { 0x91376aff, 0xcba6, 0x42be, \ ++ { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \ ++ } ++ + /* Variables. */ + extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); + extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); +diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h +index c3e6559217..ab969af246 100644 +--- a/include/grub/lib/envblk.h ++++ b/include/grub/lib/envblk.h +@@ -22,6 +22,8 @@ + #define GRUB_ENVBLK_SIGNATURE "# GRUB Environment Block\n" + #define GRUB_ENVBLK_DEFCFG "grubenv" + ++#define DEFAULT_ENVBLK_SIZE 1024 ++ + #ifndef ASM_FILE + + struct grub_envblk +@@ -33,6 +35,7 @@ typedef struct grub_envblk *grub_envblk_t; + + grub_envblk_t grub_envblk_open (char *buf, grub_size_t size); + int grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value); ++grub_err_t grub_envblk_get (grub_envblk_t envblk, const char * const name, char ** const value); + void grub_envblk_delete (grub_envblk_t envblk, const char *name); + void grub_envblk_iterate (grub_envblk_t envblk, + void *hook_data, diff --git a/SOURCES/0110-Make-grub_error-more-verbose.patch b/SOURCES/0110-Make-grub_error-more-verbose.patch deleted file mode 100644 index 2492e9f..0000000 --- a/SOURCES/0110-Make-grub_error-more-verbose.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 27 Aug 2018 13:14:06 -0400 -Subject: [PATCH] Make grub_error() more verbose - -Signed-off-by: Peter Jones ---- - grub-core/kern/err.c | 13 +++++++++++-- - include/grub/err.h | 8 ++++++-- - 2 files changed, 17 insertions(+), 4 deletions(-) - -diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c -index 53c734de70e..aebfe0cf839 100644 ---- a/grub-core/kern/err.c -+++ b/grub-core/kern/err.c -@@ -33,15 +33,24 @@ static struct grub_error_saved grub_error_stack_items[GRUB_ERROR_STACK_SIZE]; - static int grub_error_stack_pos; - static int grub_error_stack_assert; - -+#ifdef grub_error -+#undef grub_error -+#endif -+ - grub_err_t --grub_error (grub_err_t n, const char *fmt, ...) -+grub_error (grub_err_t n, const char *file, const int line, const char *fmt, ...) - { - va_list ap; -+ int m; - - grub_errno = n; - -+ m = grub_snprintf (grub_errmsg, sizeof (grub_errmsg), "%s:%d:", file, line); -+ if (m < 0) -+ m = 0; -+ - va_start (ap, fmt); -- grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), _(fmt), ap); -+ grub_vsnprintf (grub_errmsg + m, sizeof (grub_errmsg) - m, _(fmt), ap); - va_end (ap); - - return n; -diff --git a/include/grub/err.h b/include/grub/err.h -index b08d5d0de4c..c0f90ef07c8 100644 ---- a/include/grub/err.h -+++ b/include/grub/err.h -@@ -85,8 +85,12 @@ struct grub_error_saved - extern grub_err_t EXPORT_VAR(grub_errno); - extern char EXPORT_VAR(grub_errmsg)[GRUB_MAX_ERRMSG]; - --grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *fmt, ...) -- __attribute__ ((format (GNU_PRINTF, 2, 3))); -+grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *file, const int line, const char *fmt, ...) -+ __attribute__ ((format (GNU_PRINTF, 4, 5))); -+ -+#define grub_error(n, fmt, ...) grub_error (n, __FILE__, __LINE__, fmt, ##__VA_ARGS__) -+ -+ - void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn)); - void EXPORT_FUNC(grub_error_push) (void); - int EXPORT_FUNC(grub_error_pop) (void); diff --git a/SOURCES/0111-Make-it-possible-to-subtract-conditions-from-debug.patch b/SOURCES/0111-Make-it-possible-to-subtract-conditions-from-debug.patch new file mode 100644 index 0000000..15305f8 --- /dev/null +++ b/SOURCES/0111-Make-it-possible-to-subtract-conditions-from-debug.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 17 Jan 2019 13:10:39 -0500 +Subject: [PATCH] Make it possible to subtract conditions from debug= + +This makes it so you can do set debug to "all,-scripting,-lexer" and get the +obvious outcome. Any negation present will take preference over that +conditional, so "all,-scripting,scripting" is the same thing as +"all,-scripting". + +Signed-off-by: Peter Jones +--- + grub-core/kern/misc.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index 9a2fae6398..578bf51a5f 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -164,12 +164,24 @@ int + grub_debug_enabled (const char * condition) + { + const char *debug; ++ char *negcond; ++ int negated = 0; + + debug = grub_env_get ("debug"); + if (!debug) + return 0; + +- if (grub_strword (debug, "all") || grub_strword (debug, condition)) ++ negcond = grub_zalloc (grub_strlen (condition) + 2); ++ if (negcond) ++ { ++ grub_strcpy (negcond, "-"); ++ grub_strcpy (negcond+1, condition); ++ negated = grub_strword (debug, negcond); ++ grub_free (negcond); ++ } ++ ++ if (!negated && ++ (grub_strword (debug, "all") || grub_strword (debug, condition))) + return 1; + + return 0; diff --git a/SOURCES/0111-Make-reset-an-alias-for-the-reboot-command.patch b/SOURCES/0111-Make-reset-an-alias-for-the-reboot-command.patch deleted file mode 100644 index c86acf1..0000000 --- a/SOURCES/0111-Make-reset-an-alias-for-the-reboot-command.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 31 Aug 2018 16:42:03 -0400 -Subject: [PATCH] Make "reset" an alias for the "reboot" command. - -I'm really tired of half the tools I get to use having one and the other half -having the other. - -Signed-off-by: Peter Jones ---- - grub-core/commands/reboot.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/grub-core/commands/reboot.c b/grub-core/commands/reboot.c -index 46d364c99a9..f5cc2283636 100644 ---- a/grub-core/commands/reboot.c -+++ b/grub-core/commands/reboot.c -@@ -32,15 +32,18 @@ grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)), - grub_reboot (); - } - --static grub_command_t cmd; -+static grub_command_t reboot_cmd, reset_cmd; - - GRUB_MOD_INIT(reboot) - { -- cmd = grub_register_command ("reboot", grub_cmd_reboot, -- 0, N_("Reboot the computer.")); -+ reboot_cmd = grub_register_command ("reboot", grub_cmd_reboot, -+ 0, N_("Reboot the computer.")); -+ reset_cmd = grub_register_command ("reset", grub_cmd_reboot, -+ 0, N_("Reboot the computer.")); - } - - GRUB_MOD_FINI(reboot) - { -- grub_unregister_command (cmd); -+ grub_unregister_command (reboot_cmd); -+ grub_unregister_command (reset_cmd); - } diff --git a/SOURCES/0112-Add-a-version-command.patch b/SOURCES/0112-Add-a-version-command.patch deleted file mode 100644 index 30c8224..0000000 --- a/SOURCES/0112-Add-a-version-command.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 11 Sep 2018 14:20:37 -0400 -Subject: [PATCH] Add a "version" command. - -This adds a command that shows you info about grub's version, the grub target -platform, the compiler version, and if you built with ---with-rpm-version=, the rpm package version. - -Signed-off-by: Peter Jones ---- - configure.ac | 13 ++++++++++ - grub-core/Makefile.core.def | 5 ++++ - grub-core/commands/version.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ - config.h.in | 1 + - 4 files changed, 75 insertions(+) - create mode 100644 grub-core/commands/version.c - -diff --git a/configure.ac b/configure.ac -index 152e7dba652..cfdac6bed5a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -312,6 +312,19 @@ AC_SUBST(target_cpu) - AC_SUBST(platform) - - # Define default variables -+have_with_rpm_version=n -+AC_ARG_WITH([rpm_version], -+ AS_HELP_STRING([--with-rpm-version=VERSION], -+ [set the rpm package version [[guessed]]]), -+ [have_with_rpm_version=y], -+ [have_with_rpm_version=n]) -+if test x$have_with_rpm_version = xy; then -+ rpm_version="$with_rpm_version" -+else -+ rpm_version="" -+fi -+GRUB_RPM_VERSION="$rpm_version" -+AC_SUBST(GRUB_RPM_VERSION) - - have_with_bootdir=n - AC_ARG_WITH([bootdir], -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 84a3d89de9a..498ca11762a 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -579,6 +579,11 @@ image = { - enable = mips_loongson; - }; - -+module = { -+ name = version; -+ common = commands/version.c; -+}; -+ - module = { - name = disk; - common = lib/disk.c; -diff --git a/grub-core/commands/version.c b/grub-core/commands/version.c -new file mode 100644 -index 00000000000..f0966a518f7 ---- /dev/null -+++ b/grub-core/commands/version.c -@@ -0,0 +1,56 @@ -+/* version.c - Command to print the grub version and build info. */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static grub_err_t -+grub_cmd_version (grub_command_t cmd UNUSED, int argc, char **args UNUSED) -+{ -+ if (argc != 0) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("no arguments expected")); -+ -+ grub_printf (_("GNU GRUB version %s\n"), PACKAGE_VERSION); -+ grub_printf (_("Platform %s-%s\n"), GRUB_TARGET_CPU, GRUB_PLATFORM); -+ if (grub_strlen(GRUB_RPM_VERSION) != 0) -+ grub_printf (_("RPM package version %s\n"), GRUB_RPM_VERSION); -+ grub_printf (_("Compiler version %s\n"), __VERSION__); -+ -+ return 0; -+} -+ -+static grub_command_t cmd; -+ -+GRUB_MOD_INIT(version) -+{ -+ cmd = grub_register_command ("version", grub_cmd_version, NULL, -+ N_("Print version and build information.")); -+} -+ -+GRUB_MOD_FINI(version) -+{ -+ grub_unregister_command (cmd); -+} -diff --git a/config.h.in b/config.h.in -index 9e8f9911b18..c7e316f0f1f 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -59,6 +59,7 @@ - - #define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" - #define GRUB_PLATFORM "@GRUB_PLATFORM@" -+#define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" - - #define RE_ENABLE_I18N 1 - diff --git a/SOURCES/0112-Export-all-variables-from-the-initial-context-when-c.patch b/SOURCES/0112-Export-all-variables-from-the-initial-context-when-c.patch new file mode 100644 index 0000000..214fa4f --- /dev/null +++ b/SOURCES/0112-Export-all-variables-from-the-initial-context-when-c.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 22 Jan 2019 15:40:25 +0100 +Subject: [PATCH] Export all variables from the initial context when creating a + submenu + +When a submenu is created, only the exported variables are copied to the +new menu context. But we want the variables to be global, so export lets +export all variables to the new created submenu. + +Also, don't unset the default variable when a new submenu is created. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/normal/context.c | 2 +- + grub-core/normal/menu.c | 2 -- + 2 files changed, 1 insertion(+), 3 deletions(-) + +diff --git a/grub-core/normal/context.c b/grub-core/normal/context.c +index ee53d4a68e..87edd254c4 100644 +--- a/grub-core/normal/context.c ++++ b/grub-core/normal/context.c +@@ -99,7 +99,7 @@ grub_env_new_context (int export_all) + grub_err_t + grub_env_context_open (void) + { +- return grub_env_new_context (0); ++ return grub_env_new_context (1); + } + + int grub_extractor_level = 0; +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index 4a02aadb01..fe2e77a43e 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -375,8 +375,6 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) + + if (ptr && ptr[0] && ptr[1]) + grub_env_set ("default", ptr + 1); +- else +- grub_env_unset ("default"); + + grub_script_execute_new_scope (entry->sourcecode, entry->argc, entry->args); + diff --git a/SOURCES/0113-Add-more-dprintf-and-nerf-dprintf-in-script.c.patch b/SOURCES/0113-Add-more-dprintf-and-nerf-dprintf-in-script.c.patch deleted file mode 100644 index 9afb315..0000000 --- a/SOURCES/0113-Add-more-dprintf-and-nerf-dprintf-in-script.c.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 11 Sep 2018 15:58:29 -0400 -Subject: [PATCH] Add more dprintf, and nerf dprintf in script.c - -Signed-off-by: Peter Jones ---- - grub-core/disk/diskfilter.c | 3 +++ - grub-core/disk/efi/efidisk.c | 1 + - grub-core/kern/device.c | 1 + - grub-core/script/script.c | 5 +++++ - 4 files changed, 10 insertions(+) - -diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c -index 0320115662f..7cdffe3ebd5 100644 ---- a/grub-core/disk/diskfilter.c -+++ b/grub-core/disk/diskfilter.c -@@ -188,6 +188,8 @@ scan_disk (const char *name, int accept_diskfilter) - grub_disk_t disk; - static int scan_depth = 0; - -+ grub_dprintf ("diskfilter", "scanning %s\n", name); -+ - if (!accept_diskfilter && is_valid_diskfilter_name (name)) - return 0; - -@@ -1212,6 +1214,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, - the same. */ - if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size) - return GRUB_ERR_NONE; -+ grub_dprintf ("diskfilter", "checking %s\n", disk->name); - pv->disk = grub_disk_open (disk->name); - if (!pv->disk) - return grub_errno; -diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c -index f077b5f5535..fe8ba6e6c93 100644 ---- a/grub-core/disk/efi/efidisk.c -+++ b/grub-core/disk/efi/efidisk.c -@@ -855,6 +855,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) - return 0; - } - -+ grub_dprintf ("efidisk", "getting disk for %s\n", device_name); - parent = grub_disk_open (device_name); - grub_free (dup_dp); - -diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c -index 73b8ecc0c09..f58b58c89d5 100644 ---- a/grub-core/kern/device.c -+++ b/grub-core/kern/device.c -@@ -34,6 +34,7 @@ grub_device_open (const char *name) - { - grub_device_t dev = 0; - -+ grub_dprintf ("device", "opening device %s\n", name); - if (! name) - { - name = grub_env_get ("root"); -diff --git a/grub-core/script/script.c b/grub-core/script/script.c -index ec4d4337c66..844e8343ca7 100644 ---- a/grub-core/script/script.c -+++ b/grub-core/script/script.c -@@ -22,6 +22,11 @@ - #include - #include - -+#ifdef grub_dprintf -+#undef grub_dprintf -+#endif -+#define grub_dprintf(no, fmt, ...) -+ - /* It is not possible to deallocate the memory when a syntax error was - found. Because of that it is required to keep track of all memory - allocations. The memory is freed in case of an error, or assigned diff --git a/SOURCES/0113-grub.d-Split-out-boot-success-reset-from-menu-auto-h.patch b/SOURCES/0113-grub.d-Split-out-boot-success-reset-from-menu-auto-h.patch new file mode 100644 index 0000000..43e8d16 --- /dev/null +++ b/SOURCES/0113-grub.d-Split-out-boot-success-reset-from-menu-auto-h.patch @@ -0,0 +1,168 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christian Glombek +Date: Tue, 2 Apr 2019 16:22:21 +0200 +Subject: [PATCH] grub.d: Split out boot success reset from menu auto hide + script + +Also rename fallback and menu auto hide script to be executed +before and after boot success reset script. +In menu auto hide script, rename last_boot_ok var to menu_hide_ok + +Signed-off-by: Christian Glombek +Signed-off-by: Robbie Harwood +--- + Makefile.util.def | 14 ++++++++---- + ...allback_counting.in => 08_fallback_counting.in} | 14 ++++++------ + util/grub.d/10_reset_boot_success.in | 25 ++++++++++++++++++++++ + .../{01_menu_auto_hide.in => 12_menu_auto_hide.in} | 23 +++++--------------- + 4 files changed, 48 insertions(+), 28 deletions(-) + rename util/grub.d/{01_fallback_counting.in => 08_fallback_counting.in} (65%) + create mode 100644 util/grub.d/10_reset_boot_success.in + rename util/grub.d/{01_menu_auto_hide.in => 12_menu_auto_hide.in} (58%) + +diff --git a/Makefile.util.def b/Makefile.util.def +index e10fe766d1..b4ce5383b7 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -459,14 +459,14 @@ script = { + }; + + script = { +- name = '01_fallback_counting'; +- common = util/grub.d/01_fallback_counting.in; ++ name = '08_fallback_counting'; ++ common = util/grub.d/08_fallback_counting.in; + installdir = grubconf; + }; + + script = { +- name = '01_menu_auto_hide'; +- common = util/grub.d/01_menu_auto_hide.in; ++ name = '12_menu_auto_hide'; ++ common = util/grub.d/12_menu_auto_hide.in; + installdir = grubconf; + }; + +@@ -518,6 +518,12 @@ script = { + condition = COND_HOST_LINUX; + }; + ++script = { ++ name = '10_reset_boot_success'; ++ common = util/grub.d/10_reset_boot_success.in; ++ installdir = grubconf; ++}; ++ + script = { + name = '10_xnu'; + common = util/grub.d/10_xnu.in; +diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/08_fallback_counting.in +similarity index 65% +rename from util/grub.d/01_fallback_counting.in +rename to util/grub.d/08_fallback_counting.in +index be0e770ea8..2e2c3ff7d3 100644 +--- a/util/grub.d/01_fallback_counting.in ++++ b/util/grub.d/08_fallback_counting.in +@@ -1,15 +1,17 @@ + #! /bin/sh -e +- +-# Boot Counting ++# Fallback Countdown ++# ++# This snippet depends on 10_reset_boot_success and needs to be kept in sync. ++# + # The boot_counter env var can be used to count down boot attempts after an +-# OSTree upgrade and choose the rollback deployment when 0 is reached. Both +-# boot_counter and boot_success need to be (re-)set from userspace. ++# OSTree upgrade and choose the rollback deployment when 0 is reached. ++# Both boot_counter=X and boot_success=1 need to be set from userspace. + cat << EOF + insmod increment + # Check if boot_counter exists and boot_success=0 to activate this behaviour. + if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then +- # if countdown has ended, choose to boot rollback deployment (default=1 on +- # OSTree-based systems) ++ # if countdown has ended, choose to boot rollback deployment, ++ # i.e. default=1 on OSTree-based systems. + if [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then + set default=1 + set boot_counter=-1 +diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in +new file mode 100644 +index 0000000000..6c88d933dd +--- /dev/null ++++ b/util/grub.d/10_reset_boot_success.in +@@ -0,0 +1,25 @@ ++#! /bin/sh -e ++# Reset Boot Success ++# ++# The 08_fallback_counting and 12_menu_auto_hide snippets rely on this one ++# and need to be kept in sync. ++# ++# The boot_success var needs to be set to 1 from userspace to mark a boot successful. ++cat << EOF ++insmod increment ++# Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry ++if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then ++ set menu_hide_ok=1 ++else ++ set menu_hide_ok=0 ++fi ++# Reset boot_indeterminate after a successful boot, increment otherwise ++if [ "\${boot_success}" = "1" ] ; then ++ set boot_indeterminate=0 ++else ++ increment boot_indeterminate ++fi ++# Reset boot_success for current boot ++set boot_success=0 ++save_env boot_success boot_indeterminate ++EOF +diff --git a/util/grub.d/01_menu_auto_hide.in b/util/grub.d/12_menu_auto_hide.in +similarity index 58% +rename from util/grub.d/01_menu_auto_hide.in +rename to util/grub.d/12_menu_auto_hide.in +index ad175870a5..6a7c0fa0d4 100644 +--- a/util/grub.d/01_menu_auto_hide.in ++++ b/util/grub.d/12_menu_auto_hide.in +@@ -1,5 +1,8 @@ + #! /bin/sh +- ++# Menu Auto Hide ++# ++# This snippet depends on 10_reset_boot_success and needs to be kept in sync. ++# + # Disable / skip generating menu-auto-hide config parts on serial terminals + for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do + case "$x" in +@@ -10,29 +13,13 @@ for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do + done + + cat << EOF +-if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then +- set last_boot_ok=1 +-else +- set last_boot_ok=0 +-fi +- +-# Reset boot_indeterminate after a successful boot +-if [ "\${boot_success}" = "1" ] ; then +- set boot_indeterminate=0 +-# Avoid boot_indeterminate causing the menu to be hidden more then once +-elif [ "\${boot_indeterminate}" = "1" ]; then +- set boot_indeterminate=2 +-fi +-set boot_success=0 +-save_env boot_success boot_indeterminate +- + if [ x\$feature_timeout_style = xy ] ; then + if [ "\${menu_show_once}" ]; then + unset menu_show_once + save_env menu_show_once + set timeout_style=menu + set timeout=60 +- elif [ "\${menu_auto_hide}" -a "\${last_boot_ok}" = "1" ]; then ++ elif [ "\${menu_auto_hide}" -a "\${menu_hide_ok}" = "1" ]; then + set orig_timeout_style=\${timeout_style} + set orig_timeout=\${timeout} + if [ "\${fastboot}" = "1" ]; then diff --git a/SOURCES/0114-Don-t-assume-that-boot-commands-will-only-return-on-.patch b/SOURCES/0114-Don-t-assume-that-boot-commands-will-only-return-on-.patch new file mode 100644 index 0000000..df36517 --- /dev/null +++ b/SOURCES/0114-Don-t-assume-that-boot-commands-will-only-return-on-.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 9 Apr 2019 13:12:40 +0200 +Subject: [PATCH] Don't assume that boot commands will only return on fail + +While it's true that for most loaders the boot command never returns, it +may be the case that it does. For example the GRUB emulator boot command +calls to systemctl kexec which in turn does an asynchonous call to kexec. + +So in this case GRUB will wrongly assume that the boot command fails and +print a "Failed to boot both default and fallback entries" even when the +kexec call later succeeds. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/normal/menu.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index fe2e77a43e..ec0c92bade 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -285,7 +285,7 @@ get_and_remove_first_entry_number (grub_menu_t menu, const char *name) + } + + /* Run a menu entry. */ +-static void ++static grub_err_t + grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) + { + grub_err_t err = GRUB_ERR_NONE; +@@ -302,7 +302,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; +- return; ++ return grub_errno; + } + + errs_before = grub_err_printed_errors; +@@ -315,7 +315,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) + grub_env_context_open (); + menu = grub_zalloc (sizeof (*menu)); + if (! menu) +- return; ++ return grub_errno; + grub_env_set_menu (menu); + if (auto_boot) + grub_env_set ("timeout", "0"); +@@ -385,7 +385,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) + + if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) + /* Implicit execution of boot, only if something is loaded. */ +- grub_command_execute ("boot", 0, 0); ++ err = grub_command_execute ("boot", 0, 0); + + if (errs_before != grub_err_printed_errors) + grub_wait_after_message (); +@@ -408,6 +408,8 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) + else + grub_env_unset ("default"); + grub_env_unset ("timeout"); ++ ++ return err; + } + + /* Execute ENTRY from the menu MENU, falling back to entries specified +@@ -422,10 +424,13 @@ grub_menu_execute_with_fallback (grub_menu_t menu, + void *callback_data) + { + int fallback_entry; ++ grub_err_t err; + + callback->notify_booting (entry, callback_data); + +- grub_menu_execute_entry (entry, 1); ++ err = grub_menu_execute_entry (entry, 1); ++ if (err == GRUB_ERR_NONE) ++ return; + + /* Deal with fallback entries. */ + while ((fallback_entry = get_and_remove_first_entry_number (menu, "fallback")) +@@ -436,11 +441,9 @@ grub_menu_execute_with_fallback (grub_menu_t menu, + + entry = grub_menu_get_entry (menu, fallback_entry); + callback->notify_fallback (entry, callback_data); +- grub_menu_execute_entry (entry, 1); +- /* If the function call to execute the entry returns at all, then this is +- taken to indicate a boot failure. For menu entries that do something +- other than actually boot an operating system, this could assume +- incorrectly that something failed. */ ++ err = grub_menu_execute_entry (entry, 1); ++ if (err == GRUB_ERR_NONE) ++ return; + } + + if (!autobooted) diff --git a/SOURCES/0114-arm-arm64-loader-Better-memory-allocation-and-error-.patch b/SOURCES/0114-arm-arm64-loader-Better-memory-allocation-and-error-.patch deleted file mode 100644 index 1fdc552..0000000 --- a/SOURCES/0114-arm-arm64-loader-Better-memory-allocation-and-error-.patch +++ /dev/null @@ -1,279 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 11 Jul 2019 14:38:57 +0200 -Subject: [PATCH] arm/arm64 loader: Better memory allocation and error - messages. - -On mustang, our memory map looks like: - -Type Physical start - end #Pages Size Attributes -reserved 0000004000000000-00000040001fffff 00000200 2MiB UC WC WT WB -conv-mem 0000004000200000-0000004393ffffff 00393e00 14654MiB UC WC WT WB -ldr-code 0000004394000000-00000043f7ffffff 00064000 1600MiB UC WC WT WB -BS-data 00000043f8000000-00000043f801ffff 00000020 128KiB UC WC WT WB -conv-mem 00000043f8020000-00000043fa15bfff 0000213c 34032KiB UC WC WT WB -ldr-code 00000043fa15c000-00000043fa2a1fff 00000146 1304KiB UC WC WT WB -ldr-data 00000043fa2a2000-00000043fa3e8fff 00000147 1308KiB UC WC WT WB -conv-mem 00000043fa3e9000-00000043fa3e9fff 00000001 4KiB UC WC WT WB -ldr-data 00000043fa3ea000-00000043fa3eafff 00000001 4KiB UC WC WT WB -ldr-code 00000043fa3eb000-00000043fa4affff 000000c5 788KiB UC WC WT WB -BS-code 00000043fa4b0000-00000043fa59ffff 000000f0 960KiB UC WC WT WB -RT-code 00000043fa5a0000-00000043fa5affff 00000010 64KiB RT UC WC WT WB -RT-data 00000043fa5b0000-00000043fa5bffff 00000010 64KiB RT UC WC WT WB -RT-code 00000043fa5c0000-00000043fa5cffff 00000010 64KiB RT UC WC WT WB -ldr-data 00000043fa5d0000-00000043fa5d0fff 00000001 4KiB UC WC WT WB -BS-code 00000043fa5d1000-00000043fa5ddfff 0000000d 52KiB UC WC WT WB -reserved 00000043fa5de000-00000043fa60ffff 00000032 200KiB UC WC WT WB -ACPI-rec 00000043fa610000-00000043fa6affff 000000a0 640KiB UC WC WT WB -ACPI-nvs 00000043fa6b0000-00000043fa6bffff 00000010 64KiB UC WC WT WB -ACPI-rec 00000043fa6c0000-00000043fa70ffff 00000050 320KiB UC WC WT WB -RT-code 00000043fa710000-00000043fa72ffff 00000020 128KiB RT UC WC WT WB -RT-data 00000043fa730000-00000043fa78ffff 00000060 384KiB RT UC WC WT WB -RT-code 00000043fa790000-00000043fa79ffff 00000010 64KiB RT UC WC WT WB -RT-data 00000043fa7a0000-00000043fa99ffff 00000200 2MiB RT UC WC WT WB -RT-code 00000043fa9a0000-00000043fa9affff 00000010 64KiB RT UC WC WT WB -RT-data 00000043fa9b0000-00000043fa9cffff 00000020 128KiB RT UC WC WT WB -BS-code 00000043fa9d0000-00000043fa9d9fff 0000000a 40KiB UC WC WT WB -reserved 00000043fa9da000-00000043fa9dbfff 00000002 8KiB UC WC WT WB -conv-mem 00000043fa9dc000-00000043fc29dfff 000018c2 25352KiB UC WC WT WB -BS-data 00000043fc29e000-00000043fc78afff 000004ed 5044KiB UC WC WT WB -conv-mem 00000043fc78b000-00000043fca01fff 00000277 2524KiB UC WC WT WB -BS-data 00000043fca02000-00000043fcea3fff 000004a2 4744KiB UC WC WT WB -conv-mem 00000043fcea4000-00000043fcea4fff 00000001 4KiB UC WC WT WB -BS-data 00000043fcea5000-00000043fd192fff 000002ee 3000KiB UC WC WT WB -conv-mem 00000043fd193000-00000043fd2b0fff 0000011e 1144KiB UC WC WT WB -BS-data 00000043fd2b1000-00000043ff80ffff 0000255f 38268KiB UC WC WT WB -BS-code 00000043ff810000-00000043ff99ffff 00000190 1600KiB UC WC WT WB -RT-code 00000043ff9a0000-00000043ff9affff 00000010 64KiB RT UC WC WT WB -conv-mem 00000043ff9b0000-00000043ff9bffff 00000010 64KiB UC WC WT WB -RT-data 00000043ff9c0000-00000043ff9effff 00000030 192KiB RT UC WC WT WB -conv-mem 00000043ff9f0000-00000043ffa05fff 00000016 88KiB UC WC WT WB -BS-data 00000043ffa06000-00000043ffffffff 000005fa 6120KiB UC WC WT WB -MMIO 0000000010510000-0000000010510fff 00000001 4KiB RT -MMIO 0000000010548000-0000000010549fff 00000002 8KiB RT -MMIO 0000000017000000-0000000017001fff 00000002 8KiB RT -MMIO 000000001c025000-000000001c025fff 00000001 4KiB RT - -This patch adds a requirement when we're trying to find the base of ram, that -the memory we choose is actually /allocatable/ conventional memory, not merely -write-combining. On this machine that means we wind up with an allocation -around 0x4392XXXXXX, which is a reasonable address. - -This also changes grub_efi_allocate_pages_real() so that if 0 is allocated, it -tries to allocate again starting with the same max address it did the first -time, rather than interposing GRUB_EFI_MAX_USABLE_ADDRESS there, so that any -per-platform constraints on its given address are maintained. - -Signed-off-by: Peter Jones ---- - grub-core/kern/efi/mm.c | 33 +++++++++++++++----- - grub-core/loader/arm64/linux.c | 68 +++++++++++++++++++++++++++++++----------- - 2 files changed, 76 insertions(+), 25 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index f6aef0ef649..85ad4b4494c 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -154,6 +154,7 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, - { - grub_efi_status_t status; - grub_efi_boot_services_t *b; -+ grub_efi_physical_address_t ret = address; - - /* Limit the memory access to less than 4GB for 32-bit platforms. */ - if (address > GRUB_EFI_MAX_USABLE_ADDRESS) -@@ -170,19 +171,22 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, - } - - b = grub_efi_system_table->boot_services; -- status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); -+ status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); - if (status != GRUB_EFI_SUCCESS) - { -+ grub_dprintf ("efi", -+ "allocate_pages(%d, %d, 0x%0lx, 0x%016lx) = 0x%016lx\n", -+ alloctype, memtype, pages, address, status); - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); - return NULL; - } - -- if (address == 0) -+ if (ret == 0) - { - /* Uggh, the address 0 was allocated... This is too annoying, - so reallocate another one. */ -- address = GRUB_EFI_MAX_USABLE_ADDRESS; -- status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); -+ ret = address; -+ status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); - grub_efi_free_pages (0, pages); - if (status != GRUB_EFI_SUCCESS) - { -@@ -191,9 +195,9 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, - } - } - -- grub_efi_store_alloc (address, pages); -+ grub_efi_store_alloc (ret, pages); - -- return (void *) ((grub_addr_t) address); -+ return (void *) ((grub_addr_t) ret); - } - - void * -@@ -713,8 +717,21 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) - for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS; - (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); - desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) -- if (desc->attribute & GRUB_EFI_MEMORY_WB) -- *base_addr = grub_min (*base_addr, desc->physical_start); -+ { -+ if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY && -+ (desc->attribute & GRUB_EFI_MEMORY_WB)) -+ { -+ *base_addr = grub_min (*base_addr, desc->physical_start); -+ grub_dprintf ("efi", "setting base_addr=0x%016lx\n", *base_addr); -+ } -+ else -+ { -+ grub_dprintf ("efi", "ignoring address 0x%016lx\n", desc->physical_start); -+ } -+ } -+ -+ if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS) -+ grub_dprintf ("efi", "base_addr 0x%016lx is probably wrong.\n", *base_addr); - - grub_free(memory_map); - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index 04994d5c67d..70a0075ec5e 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -71,20 +71,25 @@ finalize_params_linux (void) - { - grub_efi_loaded_image_t *loaded_image = NULL; - int node, retval, len; -- -+ grub_err_t err = GRUB_ERR_NONE; - void *fdt; - - fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); -- - if (!fdt) -- goto failure; -+ { -+ err = grub_error(GRUB_ERR_BAD_OS, "failed to load FDT"); -+ goto failure; -+ } - - node = grub_fdt_find_subnode (fdt, 0, "chosen"); - if (node < 0) - node = grub_fdt_add_subnode (fdt, 0, "chosen"); - - if (node < 1) -- goto failure; -+ { -+ err = grub_error(grub_errno, "failed to load chosen fdt node."); -+ goto failure; -+ } - - /* Set initrd info */ - if (initrd_start && initrd_end > initrd_start) -@@ -95,15 +100,26 @@ finalize_params_linux (void) - retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", - initrd_start); - if (retval) -- goto failure; -+ { -+ err = grub_error(retval, "Failed to set linux,initrd-start property"); -+ goto failure; -+ } -+ - retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", - initrd_end); - if (retval) -- goto failure; -+ { -+ err = grub_error(retval, "Failed to set linux,initrd-end property"); -+ goto failure; -+ } - } - -- if (grub_fdt_install() != GRUB_ERR_NONE) -- goto failure; -+ retval = grub_fdt_install(); -+ if (retval != GRUB_ERR_NONE) -+ { -+ err = grub_error(retval, "Failed to install fdt"); -+ goto failure; -+ } - - grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n", - fdt); -@@ -111,14 +127,20 @@ finalize_params_linux (void) - /* Convert command line to UCS-2 */ - loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (!loaded_image) -- goto failure; -+ { -+ err = grub_error(grub_errno, "Failed to install fdt"); -+ goto failure; -+ } - - loaded_image->load_options_size = len = - (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); - loaded_image->load_options = - grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); - if (!loaded_image->load_options) -- return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); -+ { -+ err = grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); -+ goto failure; -+ } - - loaded_image->load_options_size = - 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, -@@ -128,7 +150,7 @@ finalize_params_linux (void) - - failure: - grub_fdt_unload(); -- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); -+ return err; - } - - static void -@@ -212,16 +234,28 @@ grub_linux_unload (void) - static void * - allocate_initrd_mem (int initrd_pages) - { -- grub_addr_t max_addr; -+ grub_addr_t max_addr = 0; -+ grub_err_t err; -+ void *ret; - -- if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE) -- return NULL; -+ err = grub_efi_get_ram_base (&max_addr); -+ if (err != GRUB_ERR_NONE) -+ { -+ grub_error (err, "grub_efi_get_ram_base() failed"); -+ return NULL; -+ } -+ -+ grub_dprintf ("linux", "max_addr: 0x%016lx, INITRD_MAX_ADDRESS_OFFSET: 0x%016llx\n", -+ max_addr, INITRD_MAX_ADDRESS_OFFSET); - - max_addr += INITRD_MAX_ADDRESS_OFFSET - 1; -+ grub_dprintf ("linux", "calling grub_efi_allocate_pages_real (0x%016lx, 0x%08x, EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA)", max_addr, initrd_pages); - -- return grub_efi_allocate_pages_real (max_addr, initrd_pages, -- GRUB_EFI_ALLOCATE_MAX_ADDRESS, -- GRUB_EFI_LOADER_DATA); -+ ret = grub_efi_allocate_pages_real (max_addr, initrd_pages, -+ GRUB_EFI_ALLOCATE_MAX_ADDRESS, -+ GRUB_EFI_LOADER_DATA); -+ grub_dprintf ("linux", "got 0x%016llx\n", (unsigned long long)ret); -+ return ret; - } - - static grub_err_t diff --git a/SOURCES/0115-Try-to-pick-better-locations-for-kernel-and-initrd.patch b/SOURCES/0115-Try-to-pick-better-locations-for-kernel-and-initrd.patch deleted file mode 100644 index ba918ed..0000000 --- a/SOURCES/0115-Try-to-pick-better-locations-for-kernel-and-initrd.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 11 Jul 2019 17:17:02 +0200 -Subject: [PATCH] Try to pick better locations for kernel and initrd - -- Don't limit allocations on 64-bit platforms to < 0x[37f]fffffff if - we're using the "large" code model ; use __UINTPTR_MAX__. -- Get the comparison right to check the address we've allocated. -- Fix the allocation for the command line as well. - -*But*, when we did this some systems started failing badly; coudln't -parse partition tables, etc. What's going on here is the disk controller -is silently failing DMAs to addresses above 4GB, so we're trying to parse -uninitialized (or HW zeroed) ram when looking for the partition table, -etc. - -So to limit this, we make grub_malloc() pick addresses below 4GB on -x86_64, but the direct EFI page allocation functions can get addresses -above that. - -Additionally, we now try to locate kernel+initrd+cmdline+etc below -0x7fffffff, and if they're too big to fit any memory window there, then -we try a higher address. - -Signed-off-by: Peter Jones ---- - grub-core/kern/efi/mm.c | 8 ++++---- - grub-core/loader/i386/efi/linux.c | 24 +++++++++++++++++------- - include/grub/arm/efi/memory.h | 1 + - include/grub/arm64/efi/memory.h | 1 + - include/grub/i386/efi/memory.h | 1 + - include/grub/ia64/efi/memory.h | 1 + - include/grub/x86_64/efi/memory.h | 4 +++- - 7 files changed, 28 insertions(+), 12 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 85ad4b4494c..e84961d078c 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -122,7 +122,7 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max, - grub_efi_boot_services_t *b; - grub_efi_physical_address_t address = max; - -- if (max > 0xffffffff) -+ if (max > GRUB_EFI_MAX_USABLE_ADDRESS) - return 0; - - b = grub_efi_system_table->boot_services; -@@ -480,7 +480,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - { - if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY - #if 1 -- && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS -+ && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS - #endif - && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 - && desc->num_pages != 0) -@@ -498,9 +498,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - #if 1 - if (BYTES_TO_PAGES (filtered_desc->physical_start) - + filtered_desc->num_pages -- > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)) -+ > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)) - filtered_desc->num_pages -- = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS) -+ = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS) - - BYTES_TO_PAGES (filtered_desc->physical_start)); - #endif - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 3017d0f3e52..33e981e76e7 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -106,7 +107,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - size += ALIGN_UP (grub_file_size (files[i]), 4); - } - -- initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size)); -+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size)); -+ if (!initrd_mem) -+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size)); - if (!initrd_mem) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd")); -@@ -202,8 +205,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- params = grub_efi_allocate_pages_max (0x3fffffff, -+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, - BYTES_TO_PAGES(sizeof(*params))); -+ if (!params) -+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, -+ BYTES_TO_PAGES(sizeof(*params))); - if (! params) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); -@@ -273,8 +279,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - #endif - - grub_dprintf ("linux", "setting up cmdline\n"); -- linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff, -- BYTES_TO_PAGES(lh->cmdline_size + 1)); -+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, -+ BYTES_TO_PAGES(lh->cmdline_size + 1)); -+ if (!linux_cmdline) -+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, -+ BYTES_TO_PAGES(lh->cmdline_size + 1)); - if (!linux_cmdline) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline")); -@@ -301,11 +310,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - kernel_mem = grub_efi_allocate_pages_max(lh->pref_address, - BYTES_TO_PAGES(lh->init_size)); -- - if (!kernel_mem) -- kernel_mem = grub_efi_allocate_pages_max(0x3fffffff, -+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, -+ BYTES_TO_PAGES(lh->init_size)); -+ if (!kernel_mem) -+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, - BYTES_TO_PAGES(lh->init_size)); -- - if (!kernel_mem) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); -diff --git a/include/grub/arm/efi/memory.h b/include/grub/arm/efi/memory.h -index 2c64918e3f7..a4c2ec83502 100644 ---- a/include/grub/arm/efi/memory.h -+++ b/include/grub/arm/efi/memory.h -@@ -2,5 +2,6 @@ - #include - - #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS - - #endif /* ! GRUB_MEMORY_CPU_HEADER */ -diff --git a/include/grub/arm64/efi/memory.h b/include/grub/arm64/efi/memory.h -index c6cb3241714..acb61dca44b 100644 ---- a/include/grub/arm64/efi/memory.h -+++ b/include/grub/arm64/efi/memory.h -@@ -2,5 +2,6 @@ - #include - - #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS - - #endif /* ! GRUB_MEMORY_CPU_HEADER */ -diff --git a/include/grub/i386/efi/memory.h b/include/grub/i386/efi/memory.h -index 2c64918e3f7..a4c2ec83502 100644 ---- a/include/grub/i386/efi/memory.h -+++ b/include/grub/i386/efi/memory.h -@@ -2,5 +2,6 @@ - #include - - #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS - - #endif /* ! GRUB_MEMORY_CPU_HEADER */ -diff --git a/include/grub/ia64/efi/memory.h b/include/grub/ia64/efi/memory.h -index 2c64918e3f7..a4c2ec83502 100644 ---- a/include/grub/ia64/efi/memory.h -+++ b/include/grub/ia64/efi/memory.h -@@ -2,5 +2,6 @@ - #include - - #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS - - #endif /* ! GRUB_MEMORY_CPU_HEADER */ -diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/efi/memory.h -index 46e9145a308..e81cfb32213 100644 ---- a/include/grub/x86_64/efi/memory.h -+++ b/include/grub/x86_64/efi/memory.h -@@ -2,9 +2,11 @@ - #include - - #if defined (__code_model_large__) --#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff -+#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__ -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff - #else - #define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS - #endif - - #endif /* ! GRUB_MEMORY_CPU_HEADER */ diff --git a/SOURCES/0115-grub-set-bootflag-Update-comment-about-running-as-ro.patch b/SOURCES/0115-grub-set-bootflag-Update-comment-about-running-as-ro.patch new file mode 100644 index 0000000..9ffb3ae --- /dev/null +++ b/SOURCES/0115-grub-set-bootflag-Update-comment-about-running-as-ro.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 13 Nov 2019 12:15:43 +0100 +Subject: [PATCH] grub-set-bootflag: Update comment about running as root + through pkexec + +We have stopped using pkexec for grub-set-bootflag, instead it is now +installed suid root, update the comment accordingly. + +Signed-off-by: Hans de Goede +--- + util/grub-set-bootflag.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index a6ccc11383..3eb04beb5e 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -18,7 +18,7 @@ + */ + + /* +- * NOTE this gets run by users as root (through pkexec), so this does not ++ * NOTE this gets run by users as root (its suid root), so this does not + * use any grub library / util functions to allow for easy auditing. + * The grub headers are only included to get certain defines. + */ diff --git a/SOURCES/0116-Attempt-to-fix-up-all-the-places-Wsign-compare-error.patch b/SOURCES/0116-Attempt-to-fix-up-all-the-places-Wsign-compare-error.patch deleted file mode 100644 index c2f2a59..0000000 --- a/SOURCES/0116-Attempt-to-fix-up-all-the-places-Wsign-compare-error.patch +++ /dev/null @@ -1,397 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 11 Jul 2019 18:03:25 +0200 -Subject: [PATCH] Attempt to fix up all the places -Wsign-compare=error finds. - -Signed-off-by: Peter Jones ---- - grub-core/kern/emu/misc.c | 2 +- - grub-core/lib/reed_solomon.c | 4 +- - grub-core/osdep/linux/blocklist.c | 2 +- - grub-core/osdep/linux/getroot.c | 2 +- - grub-core/osdep/linux/hostdisk.c | 2 +- - util/grub-fstest.c | 2 +- - util/grub-menulst2cfg.c | 2 +- - util/grub-mkfont.c | 13 +- - util/grub-probe.c | 2 +- - util/grub-rpm-sort.c | 2 +- - util/setup.c | 2 +- - bootstrap.conf | 3 +- - .../gnulib-patches/fix-sign-compare-errors.patch | 161 +++++++++++++++++++++ - 13 files changed, 181 insertions(+), 18 deletions(-) - create mode 100644 grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch - -diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c -index eeea092752d..f08a1bb8415 100644 ---- a/grub-core/kern/emu/misc.c -+++ b/grub-core/kern/emu/misc.c -@@ -189,7 +189,7 @@ grub_util_get_image_size (const char *path) - sz = ftello (f); - if (sz < 0) - grub_util_error (_("cannot open `%s': %s"), path, strerror (errno)); -- if (sz != (size_t) sz) -+ if (sz > (off_t)(GRUB_SIZE_MAX >> 1)) - grub_util_error (_("file `%s' is too big"), path); - ret = (size_t) sz; - -diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c -index 467305b46ab..79037c093f7 100644 ---- a/grub-core/lib/reed_solomon.c -+++ b/grub-core/lib/reed_solomon.c -@@ -157,7 +157,7 @@ static void - rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) - { - gf_single_t *rs_polynomial; -- int i, j; -+ unsigned int i, j; - gf_single_t *m; - m = xcalloc (s + rs, sizeof (gf_single_t)); - grub_memcpy (m, data, s * sizeof (gf_single_t)); -@@ -324,7 +324,7 @@ static void - encode_block (gf_single_t *ptr, grub_size_t s, - gf_single_t *rptr, grub_size_t rs) - { -- int i, j; -+ unsigned int i, j; - for (i = 0; i < SECTOR_SIZE; i++) - { - grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; -diff --git a/grub-core/osdep/linux/blocklist.c b/grub-core/osdep/linux/blocklist.c -index c77d6085ccb..42a315031ff 100644 ---- a/grub-core/osdep/linux/blocklist.c -+++ b/grub-core/osdep/linux/blocklist.c -@@ -109,7 +109,7 @@ grub_install_get_blocklist (grub_device_t root_dev, - else - { - struct fiemap *fie2; -- int i; -+ unsigned int i; - fie2 = xmalloc (sizeof (*fie2) - + fie1.fm_mapped_extents - * sizeof (fie1.fm_extents[1])); -diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c -index 28790307e00..9f730b35189 100644 ---- a/grub-core/osdep/linux/getroot.c -+++ b/grub-core/osdep/linux/getroot.c -@@ -236,7 +236,7 @@ grub_find_root_devices_from_btrfs (const char *dir) - { - int fd; - struct btrfs_ioctl_fs_info_args fsi; -- int i, j = 0; -+ unsigned int i, j = 0; - char **ret; - - fd = open (dir, 0); -diff --git a/grub-core/osdep/linux/hostdisk.c b/grub-core/osdep/linux/hostdisk.c -index da62f924e35..7bc99ac1c1d 100644 ---- a/grub-core/osdep/linux/hostdisk.c -+++ b/grub-core/osdep/linux/hostdisk.c -@@ -83,7 +83,7 @@ grub_util_get_fd_size_os (grub_util_fd_t fd, const char *name, unsigned *log_sec - if (sector_size & (sector_size - 1) || !sector_size) - return -1; - for (log_sector_size = 0; -- (1 << log_sector_size) < sector_size; -+ (1U << log_sector_size) < sector_size; - log_sector_size++); - - if (log_secsize) -diff --git a/util/grub-fstest.c b/util/grub-fstest.c -index 83865642009..bfcef852d83 100644 ---- a/util/grub-fstest.c -+++ b/util/grub-fstest.c -@@ -323,7 +323,7 @@ cmd_cmp (char *src, char *dest) - read_file (src, cmp_hook, ff); - - { -- grub_uint64_t pre; -+ long long pre; - pre = ftell (ff); - fseek (ff, 0, SEEK_END); - if (pre != ftell (ff)) -diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c -index a39f8693947..358d604210b 100644 ---- a/util/grub-menulst2cfg.c -+++ b/util/grub-menulst2cfg.c -@@ -34,7 +34,7 @@ main (int argc, char **argv) - char *buf = NULL; - size_t bufsize = 0; - char *suffix = xstrdup (""); -- int suffixlen = 0; -+ size_t suffixlen = 0; - const char *out_fname = 0; - - grub_util_host_init (&argc, &argv); -diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c -index 0fe45a6103d..3e09240b99f 100644 ---- a/util/grub-mkfont.c -+++ b/util/grub-mkfont.c -@@ -138,7 +138,8 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, - int width, height; - int cuttop, cutbottom, cutleft, cutright; - grub_uint8_t *data; -- int mask, i, j, bitmap_size; -+ int mask, i, bitmap_size; -+ unsigned int j; - FT_GlyphSlot glyph; - int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME; - FT_Error err; -@@ -183,7 +184,7 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, - cuttop = cutbottom = cutleft = cutright = 0; - else - { -- for (cuttop = 0; cuttop < glyph->bitmap.rows; cuttop++) -+ for (cuttop = 0; cuttop < (long)glyph->bitmap.rows; cuttop++) - { - for (j = 0; j < glyph->bitmap.width; j++) - if (glyph->bitmap.buffer[j / 8 + cuttop * glyph->bitmap.pitch] -@@ -203,10 +204,10 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, - break; - } - cutbottom = glyph->bitmap.rows - 1 - cutbottom; -- if (cutbottom + cuttop >= glyph->bitmap.rows) -+ if (cutbottom + cuttop >= (long)glyph->bitmap.rows) - cutbottom = 0; - -- for (cutleft = 0; cutleft < glyph->bitmap.width; cutleft++) -+ for (cutleft = 0; cutleft < (long)glyph->bitmap.width; cutleft++) - { - for (j = 0; j < glyph->bitmap.rows; j++) - if (glyph->bitmap.buffer[cutleft / 8 + j * glyph->bitmap.pitch] -@@ -225,7 +226,7 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, - break; - } - cutright = glyph->bitmap.width - 1 - cutright; -- if (cutright + cutleft >= glyph->bitmap.width) -+ if (cutright + cutleft >= (long)glyph->bitmap.width) - cutright = 0; - } - -@@ -262,7 +263,7 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, - - mask = 0; - data = &glyph_info->bitmap[0] - 1; -- for (j = cuttop; j < height + cuttop; j++) -+ for (j = cuttop; j < (long)height + cuttop; j++) - for (i = cutleft; i < width + cutleft; i++) - add_pixel (&data, &mask, - glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] & -diff --git a/util/grub-probe.c b/util/grub-probe.c -index c08e46bbb40..c6fac732b40 100644 ---- a/util/grub-probe.c -+++ b/util/grub-probe.c -@@ -798,7 +798,7 @@ argp_parser (int key, char *arg, struct argp_state *state) - - case 't': - { -- int i; -+ unsigned int i; - - for (i = PRINT_FS; i < ARRAY_SIZE (targets); i++) - if (strcmp (arg, targets[i]) == 0) -diff --git a/util/grub-rpm-sort.c b/util/grub-rpm-sort.c -index f33bd1ed568..8345944105f 100644 ---- a/util/grub-rpm-sort.c -+++ b/util/grub-rpm-sort.c -@@ -232,7 +232,7 @@ main (int argc, char *argv[]) - struct arguments arguments; - char **package_names = NULL; - size_t n_package_names = 0; -- int i; -+ unsigned int i; - - grub_util_host_init (&argc, &argv); - -diff --git a/util/setup.c b/util/setup.c -index da5f2c07f50..8b22bb8ccac 100644 ---- a/util/setup.c -+++ b/util/setup.c -@@ -406,7 +406,7 @@ SETUP (const char *dir, - int is_ldm; - grub_err_t err; - grub_disk_addr_t *sectors; -- int i; -+ unsigned int i; - grub_fs_t fs; - unsigned int nsec, maxsec; - -diff --git a/bootstrap.conf b/bootstrap.conf -index 6b043fc354c..186be9c48ce 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -80,7 +80,8 @@ cp -a INSTALL INSTALL.grub - bootstrap_post_import_hook () { - set -e - for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ -- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do -+ fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort \ -+ fix-sign-compare-errors; do - patch -d grub-core/lib/gnulib -p2 \ - < "grub-core/lib/gnulib-patches/$patchname.patch" - done -diff --git a/grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch b/grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch -new file mode 100644 -index 00000000000..479029c0565 ---- /dev/null -+++ b/grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch -@@ -0,0 +1,161 @@ -+diff --git a/lib/regcomp.c b/lib/regcomp.c -+index cc85f35ac58..361079d82d6 100644 -+--- a/lib/regcomp.c -++++ b/lib/regcomp.c -+@@ -322,7 +322,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, -+ *p++ = dfa->nodes[node].opr.c; -+ memset (&state, '\0', sizeof (state)); -+ if (__mbrtowc (&wc, (const char *) buf, p - buf, -+- &state) == p - buf -++ &state) == (size_t)(p - buf) -+ && (__wcrtomb ((char *) buf, __towlower (wc), &state) -+ != (size_t) -1)) -+ re_set_fastmap (fastmap, false, buf[0]); -+@@ -3778,7 +3778,7 @@ fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) -+ num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) -+ ? -2 -+ : num == -1 -+- ? c - '0' -++ ? (Idx)(c - '0') -+ : MIN (RE_DUP_MAX + 1, num * 10 + c - '0')); -+ } -+ return num; -+diff --git a/lib/regex_internal.c b/lib/regex_internal.c -+index 9004ce809eb..193a1e3d332 100644 -+--- a/lib/regex_internal.c -++++ b/lib/regex_internal.c -+@@ -233,7 +233,7 @@ build_wcs_buffer (re_string_t *pstr) -+ /* Apply the translation if we need. */ -+ if (__glibc_unlikely (pstr->trans != NULL)) -+ { -+- int i, ch; -++ unsigned int i, ch; -+ -+ for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) -+ { -+@@ -376,7 +376,7 @@ build_wcs_upper_buffer (re_string_t *pstr) -+ prev_st = pstr->cur_state; -+ if (__glibc_unlikely (pstr->trans != NULL)) -+ { -+- int i, ch; -++ unsigned int i, ch; -+ -+ for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) -+ { -+@@ -754,7 +754,7 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) -+ memset (&cur_state, 0, sizeof (cur_state)); -+ mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, -+ &cur_state); -+- if (raw + offset - p <= mbclen -++ if ((size_t)(raw + offset - p) <= mbclen -+ && mbclen < (size_t) -2) -+ { -+ memset (&pstr->cur_state, '\0', -+diff --git a/lib/regex_internal.h b/lib/regex_internal.h -+index 5462419b787..e0f8292395d 100644 -+--- a/lib/regex_internal.h -++++ b/lib/regex_internal.h -+@@ -425,7 +425,7 @@ struct re_string_t -+ unsigned char offsets_needed; -+ unsigned char newline_anchor; -+ unsigned char word_ops_used; -+- int mb_cur_max; -++ unsigned int mb_cur_max; -+ }; -+ typedef struct re_string_t re_string_t; -+ -+@@ -702,7 +702,7 @@ struct re_dfa_t -+ unsigned int is_utf8 : 1; -+ unsigned int map_notascii : 1; -+ unsigned int word_ops_used : 1; -+- int mb_cur_max; -++ unsigned int mb_cur_max; -+ bitset_t word_char; -+ reg_syntax_t syntax; -+ Idx *subexp_map; -+diff --git a/lib/regexec.c b/lib/regexec.c -+index 0a7a27b772e..b57d4f9141d 100644 -+--- a/lib/regexec.c -++++ b/lib/regexec.c -+@@ -443,7 +443,7 @@ re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length, -+ { -+ if (ret_len) -+ { -+- assert (pmatch[0].rm_so == start); -++ assert (pmatch[0].rm_so == (long)start); -+ rval = pmatch[0].rm_eo - start; -+ } -+ else -+@@ -877,11 +877,11 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, -+ if (__glibc_unlikely (mctx.input.offsets_needed != 0)) -+ { -+ pmatch[reg_idx].rm_so = -+- (pmatch[reg_idx].rm_so == mctx.input.valid_len -++ (pmatch[reg_idx].rm_so == (long)mctx.input.valid_len -+ ? mctx.input.valid_raw_len -+ : mctx.input.offsets[pmatch[reg_idx].rm_so]); -+ pmatch[reg_idx].rm_eo = -+- (pmatch[reg_idx].rm_eo == mctx.input.valid_len -++ (pmatch[reg_idx].rm_eo == (long)mctx.input.valid_len -+ ? mctx.input.valid_raw_len -+ : mctx.input.offsets[pmatch[reg_idx].rm_eo]); -+ } -+@@ -1418,11 +1418,11 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, -+ } -+ memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); -+ -+- for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) -++ for (idx = pmatch[0].rm_so; idx <= (long)pmatch[0].rm_eo ;) -+ { -+ update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); -+ -+- if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) -++ if (idx == (long)pmatch[0].rm_eo && cur_node == mctx->last_node) -+ { -+ Idx reg_idx; -+ if (fs) -+@@ -1519,7 +1519,7 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, -+ if (reg_num < nmatch) -+ { -+ /* We are at the last node of this sub expression. */ -+- if (pmatch[reg_num].rm_so < cur_idx) -++ if (pmatch[reg_num].rm_so < (long)cur_idx) -+ { -+ pmatch[reg_num].rm_eo = cur_idx; -+ /* This is a non-empty match or we are not inside an optional -+@@ -2938,7 +2938,7 @@ check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, -+ mctx->state_log[str_idx] = cur_state; -+ } -+ -+- for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) -++ for (null_cnt = 0; str_idx < last_str && null_cnt <= (long)mctx->max_mb_elem_len;) -+ { -+ re_node_set_empty (&next_nodes); -+ if (mctx->state_log[str_idx + 1]) -+@@ -3718,7 +3718,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, -+ const re_string_t *input, Idx str_idx) -+ { -+ const re_token_t *node = dfa->nodes + node_idx; -+- int char_len, elem_len; -++ unsigned int char_len, elem_len; -+ Idx i; -+ -+ if (__glibc_unlikely (node->type == OP_UTF8_PERIOD)) -+@@ -4066,7 +4066,7 @@ extend_buffers (re_match_context_t *mctx, int min_len) -+ /* Double the lengths of the buffers, but allocate at least MIN_LEN. */ -+ ret = re_string_realloc_buffers (pstr, -+ MAX (min_len, -+- MIN (pstr->len, pstr->bufs_len * 2))); -++ MIN ((long)pstr->len, pstr->bufs_len * 2))); -+ if (__glibc_unlikely (ret != REG_NOERROR)) -+ return ret; -+ -+@@ -4236,7 +4236,7 @@ match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, -+ = (from == to ? -1 : 0); -+ -+ mctx->bkref_ents[mctx->nbkref_ents++].more = 0; -+- if (mctx->max_mb_elem_len < to - from) -++ if (mctx->max_mb_elem_len < (long)(to - from)) -+ mctx->max_mb_elem_len = to - from; -+ return REG_NOERROR; -+ } diff --git a/SOURCES/0116-grub-set-bootflag-Write-new-env-to-tmpfile-and-then-.patch b/SOURCES/0116-grub-set-bootflag-Write-new-env-to-tmpfile-and-then-.patch new file mode 100644 index 0000000..11722d1 --- /dev/null +++ b/SOURCES/0116-grub-set-bootflag-Write-new-env-to-tmpfile-and-then-.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 13 Nov 2019 13:02:01 +0100 +Subject: [PATCH] grub-set-bootflag: Write new env to tmpfile and then rename + +Make the grubenv writing code in grub-set-bootflag more robust by +writing the modified grubenv to a tmpfile first and then renaming the +tmpfile over the old grubenv (following symlinks). + +Signed-off-by: Hans de Goede +--- + util/grub-set-bootflag.c | 87 +++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 78 insertions(+), 9 deletions(-) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index 3eb04beb5e..3b4c25ca2a 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -28,7 +28,9 @@ + #include + #include /* For GRUB_ENVBLK_DEFCFG define */ + #include ++#include + #include ++#include + #include + #include + +@@ -56,8 +58,10 @@ int main(int argc, char *argv[]) + { + /* NOTE buf must be at least the longest bootflag length + 4 bytes */ + char env[GRUBENV_SIZE + 1], buf[64], *s; ++ /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */ ++ char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1]; + const char *bootflag; +- int i, len, ret; ++ int i, fd, len, ret; + FILE *f; + + if (argc != 2) +@@ -89,7 +93,32 @@ int main(int argc, char *argv[]) + bootflag = bootflags[i]; + len = strlen (bootflag); + +- f = fopen (GRUBENV, "r"); ++ /* ++ * Really become root. setuid avoids an user killing us, possibly leaking ++ * the tmpfile. setgid avoids the new grubenv's gid being that of the user. ++ */ ++ ret = setuid(0); ++ if (ret) ++ { ++ perror ("Error setuid(0) failed"); ++ return 1; ++ } ++ ++ ret = setgid(0); ++ if (ret) ++ { ++ perror ("Error setgid(0) failed"); ++ return 1; ++ } ++ ++ /* Canonicalize GRUBENV filename, resolving symlinks, etc. */ ++ if (!realpath(GRUBENV, env_filename)) ++ { ++ perror ("Error canonicalizing " GRUBENV " filename"); ++ return 1; ++ } ++ ++ f = fopen (env_filename, "r"); + if (!f) + { + perror ("Error opening " GRUBENV " for reading"); +@@ -144,30 +173,70 @@ int main(int argc, char *argv[]) + snprintf(buf, sizeof(buf), "%s=1\n", bootflag); + memcpy(s, buf, len + 3); + +- /* "r+", don't truncate so that the diskspace stays reserved */ +- f = fopen (GRUBENV, "r+"); ++ ++ /* ++ * Create a tempfile for writing the new env. Use the canonicalized filename ++ * for the template so that the tmpfile is in the same dir / on same fs. ++ */ ++ snprintf(tmp_filename, sizeof(tmp_filename), "%sXXXXXX", env_filename); ++ fd = mkstemp(tmp_filename); ++ if (fd == -1) ++ { ++ perror ("Creating tmpfile failed"); ++ return 1; ++ } ++ ++ f = fdopen (fd, "w"); + if (!f) + { +- perror ("Error opening " GRUBENV " for writing"); ++ perror ("Error fdopen of tmpfile failed"); ++ unlink(tmp_filename); + return 1; + } + + ret = fwrite (env, 1, GRUBENV_SIZE, f); + if (ret != GRUBENV_SIZE) + { +- perror ("Error writing to " GRUBENV); ++ perror ("Error writing tmpfile"); ++ unlink(tmp_filename); + return 1; + } + + ret = fflush (f); + if (ret) + { +- perror ("Error flushing " GRUBENV); ++ perror ("Error flushing tmpfile"); ++ unlink(tmp_filename); + return 1; + } + +- fsync (fileno (f)); +- fclose (f); ++ ret = fsync (fileno (f)); ++ if (ret) ++ { ++ perror ("Error syncing tmpfile"); ++ unlink(tmp_filename); ++ return 1; ++ } ++ ++ ret = fclose (f); ++ if (ret) ++ { ++ perror ("Error closing tmpfile"); ++ unlink(tmp_filename); ++ return 1; ++ } ++ ++ /* ++ * And finally rename the tmpfile with the new env over the old env, the ++ * linux kernel guarantees that this is atomic (from a syscall pov). ++ */ ++ ret = rename(tmp_filename, env_filename); ++ if (ret) ++ { ++ perror ("Error renaming tmpfile to " GRUBENV " failed"); ++ unlink(tmp_filename); ++ return 1; ++ } + + return 0; + } diff --git a/SOURCES/0117-Don-t-use-Wno-sign-compare-Wno-conversion-Wno-error-.patch b/SOURCES/0117-Don-t-use-Wno-sign-compare-Wno-conversion-Wno-error-.patch deleted file mode 100644 index de71484..0000000 --- a/SOURCES/0117-Don-t-use-Wno-sign-compare-Wno-conversion-Wno-error-.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 11 Jul 2019 18:20:37 +0200 -Subject: [PATCH] Don't use -Wno-sign-compare -Wno-conversion -Wno-error, do - use -Wextra. - -Signed-off-by: Peter Jones ---- - configure.ac | 14 +++++++++++--- - conf/Makefile.common | 2 +- - 2 files changed, 12 insertions(+), 4 deletions(-) - -diff --git a/configure.ac b/configure.ac -index cfdac6bed5a..bd28edf3141 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1480,11 +1480,11 @@ fi - # Set them to their new values for the tests below. - CC="$TARGET_CC" - if test x"$platform" = xemu ; then --CFLAGS="$TARGET_CFLAGS -Wno-error" -+CFLAGS="$TARGET_CFLAGS" - elif test "x$TARGET_APPLE_LINKER" = x1 ; then --CFLAGS="$TARGET_CFLAGS -nostdlib -static -Wno-error" -+CFLAGS="$TARGET_CFLAGS -nostdlib -static" - else --CFLAGS="$TARGET_CFLAGS -nostdlib -Wno-error" -+CFLAGS="$TARGET_CFLAGS -nostdlib" - fi - CPPFLAGS="$TARGET_CPPFLAGS" - -@@ -2054,6 +2054,14 @@ if test x"$enable_werror" != xno ; then - HOST_CFLAGS="$HOST_CFLAGS -Werror" - fi - -+AC_ARG_ENABLE([wextra], -+ [AS_HELP_STRING([--disable-wextra], -+ [do not use -Wextra when building GRUB])]) -+if test x"$enable_wextra" != xno ; then -+ TARGET_CFLAGS="$TARGET_CFLAGS -Wextra" -+ HOST_CFLAGS="$HOST_CFLAGS -Wextra" -+fi -+ - TARGET_CPP="$TARGET_CC -E" - TARGET_CCAS=$TARGET_CC - -diff --git a/conf/Makefile.common b/conf/Makefile.common -index 2ff9b39357c..35e14ff017e 100644 ---- a/conf/Makefile.common -+++ b/conf/Makefile.common -@@ -66,7 +66,7 @@ grubconfdir = $(sysconfdir)/grub.d - platformdir = $(pkglibdir)/$(target_cpu)-$(platform) - starfielddir = $(pkgdatadir)/themes/starfield - --CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -+CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code - CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib - - CFLAGS_POSIX = -fno-builtin diff --git a/SOURCES/0117-grub.d-Fix-boot_indeterminate-getting-set-on-boot_su.patch b/SOURCES/0117-grub.d-Fix-boot_indeterminate-getting-set-on-boot_su.patch new file mode 100644 index 0000000..948ff73 --- /dev/null +++ b/SOURCES/0117-grub.d-Fix-boot_indeterminate-getting-set-on-boot_su.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 26 Nov 2019 09:51:41 +0100 +Subject: [PATCH] grub.d: Fix boot_indeterminate getting set on boot_success=0 + boot +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The "grub.d: Split out boot success reset from menu auto hide script" +not only moved the code to clear boot_success and boot_indeterminate +but for some reason also mixed in some broken changes to the +boot_indeterminate handling. + +The boot_indeterminate var is meant to suppress the boot menu after +a reboot from either a selinux-relabel or offline-updates. These +2 special boot scenarios do not set boot_success since there is no +successfull interaction with the user. Instead they increment +boot_indeterminate, and if it is 1 and only when it is 1, so the +first reboot after a "special" boot we suppress the menu. + +To ensure that we do show the menu if we somehow get stuck in a +"special" boot loop where we do special-boots without them +incrementing boot_indeterminate, the code before the +"grub.d: Split out boot success reset from menu auto hide script" +commit would increment boot_indeterminate once when it is 1, so that +even if the "special" boot reboot-loop immediately we would show the +menu on the next boot. + +That commit broke this however, because it not only moves the code, +it also changes it from only "incrementing" boot_indeterminate once to +always incrementing it, except when boot_success == 1 (and we reset it). + +This broken behavior causes the following problem: + +1. Boot a broken kernel, system hangs, power-cycle +2. boot_success now != 1, so we increment boot_indeterminate from 0 + (unset!) to 1. User either simply tries again, or makes some changes + but the end-result still is a system hang, power-cycle +3. Now boot_indeterminate==1 so we do not show the menu even though the + previous boot failed -> BAD + +This commit fixes this by restoring the behavior of setting +boot_indeterminate to 2 when it was 1 before. + +Fixes: "grub.d: Split out boot success reset from menu auto hide script" +Signed-off-by: Hans de Goede +[jpokorny: 01_menu_auto_hide.in: fix a then/than typo] +Signed-off-by: Jan Pokorný +Signed-off-by: Robbie Harwood +--- + util/grub.d/10_reset_boot_success.in | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in +index 6c88d933dd..e73f4137b3 100644 +--- a/util/grub.d/10_reset_boot_success.in ++++ b/util/grub.d/10_reset_boot_success.in +@@ -6,18 +6,18 @@ + # + # The boot_success var needs to be set to 1 from userspace to mark a boot successful. + cat << EOF +-insmod increment + # Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry + if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then + set menu_hide_ok=1 + else + set menu_hide_ok=0 + fi +-# Reset boot_indeterminate after a successful boot, increment otherwise ++# Reset boot_indeterminate after a successful boot + if [ "\${boot_success}" = "1" ] ; then + set boot_indeterminate=0 +-else +- increment boot_indeterminate ++# Avoid boot_indeterminate causing the menu to be hidden more than once ++elif [ "\${boot_indeterminate}" = "1" ]; then ++ set boot_indeterminate=2 + fi + # Reset boot_success for current boot + set boot_success=0 diff --git a/SOURCES/0118-Add-start-symbol-for-RISC-V.patch b/SOURCES/0118-Add-start-symbol-for-RISC-V.patch new file mode 100644 index 0000000..2746fa2 --- /dev/null +++ b/SOURCES/0118-Add-start-symbol-for-RISC-V.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +Date: Sat, 9 Nov 2019 19:51:57 +0000 +Subject: [PATCH] Add start symbol for RISC-V + +All other architectures have start symbol. + +Hopefully this resolves: + + BUILDSTDERR: ././grub-mkimage: error: undefined symbol start. + +Signed-off-by: David Abdurachmanov +--- + grub-core/kern/riscv/efi/startup.S | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/grub-core/kern/riscv/efi/startup.S b/grub-core/kern/riscv/efi/startup.S +index f2a7b2b1ed..781773136e 100644 +--- a/grub-core/kern/riscv/efi/startup.S ++++ b/grub-core/kern/riscv/efi/startup.S +@@ -29,6 +29,7 @@ + + .file "startup.S" + .text ++FUNCTION(start) + FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0. diff --git a/SOURCES/0118-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch b/SOURCES/0118-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch deleted file mode 100644 index fdd3096..0000000 --- a/SOURCES/0118-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 12 Jul 2019 09:53:32 +0200 -Subject: [PATCH] x86-efi: Use bounce buffers for reading to addresses > 4GB - -Lots of machines apparently can't DMA correctly above 4GB during UEFI, -so use bounce buffers for the initramfs read. - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 52 +++++++++++++++++++++++++++++++++------ - 1 file changed, 45 insertions(+), 7 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 33e981e76e7..2f0336809e7 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -35,11 +35,16 @@ static grub_dl_t my_mod; - static int loaded; - static void *kernel_mem; - static grub_uint64_t kernel_size; --static grub_uint8_t *initrd_mem; -+static void *initrd_mem; - static grub_uint32_t handover_offset; - struct linux_kernel_params *params; - static char *linux_cmdline; - -+#define MIN(a, b) \ -+ ({ typeof (a) _a = (a); \ -+ typeof (b) _b = (b); \ -+ _a < _b ? _a : _b; }) -+ - #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) - - static grub_err_t -@@ -73,6 +78,44 @@ grub_linuxefi_unload (void) - return GRUB_ERR_NONE; - } - -+#define BOUNCE_BUFFER_MAX 0x10000000ull -+ -+static grub_ssize_t -+read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) -+{ -+ grub_ssize_t bufpos = 0; -+ static grub_size_t bbufsz = 0; -+ static char *bbuf = NULL; -+ -+ if (bbufsz == 0) -+ bbufsz = MIN(BOUNCE_BUFFER_MAX, len); -+ -+ while (!bbuf && bbufsz) -+ { -+ bbuf = grub_malloc(bbufsz); -+ if (!bbuf) -+ bbufsz >>= 1; -+ } -+ if (!bbuf) -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate bounce buffer")); -+ -+ while (bufpos < (long long)len) -+ { -+ grub_ssize_t sz; -+ -+ sz = grub_file_read (file, bbuf, MIN(bbufsz, len - bufpos)); -+ if (sz < 0) -+ return sz; -+ if (sz == 0) -+ break; -+ -+ grub_memcpy(bufp + bufpos, bbuf, sz); -+ bufpos += sz; -+ } -+ -+ return bufpos; -+} -+ - static grub_err_t - grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -@@ -126,7 +169,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - for (i = 0; i < nfiles; i++) - { - grub_ssize_t cursize = grub_file_size (files[i]); -- if (grub_file_read (files[i], ptr, cursize) != cursize) -+ if (read (files[i], ptr, cursize) != cursize) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), -@@ -152,11 +195,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - return grub_errno; - } - --#define MIN(a, b) \ -- ({ typeof (a) _a = (a); \ -- typeof (b) _b = (b); \ -- _a < _b ? _a : _b; }) -- - static grub_err_t - grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) diff --git a/SOURCES/0119-bootstrap.conf-Force-autogen.sh-to-use-python3.patch b/SOURCES/0119-bootstrap.conf-Force-autogen.sh-to-use-python3.patch new file mode 100644 index 0000000..8bfc964 --- /dev/null +++ b/SOURCES/0119-bootstrap.conf-Force-autogen.sh-to-use-python3.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Wed, 15 Jan 2020 12:47:46 +0100 +Subject: [PATCH] bootstrap.conf: Force autogen.sh to use python3 + +The python-unversioned-command package is not installed in the buildroot, +but the bootstrap script expects the python command to be present if one +is not defined. So building the package leads to the following error: + +./autogen.sh: line 20: python: command not found + +This is harmless since gnulib is included as a source anyways, because the +builders can't download. But still the issue should be fixed by forcing to +use python3 that's the default in Fedora now. + +Signed-off-by: Javier Martinez Canillas +--- + bootstrap.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/bootstrap.conf b/bootstrap.conf +index 6b043fc354..52d4af44be 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -92,7 +92,7 @@ bootstrap_post_import_hook () { + patch -d po -p3 \ + < "po/gettext-patches/$patchname.patch" + done +- FROM_BOOTSTRAP=1 ./autogen.sh ++ PYTHON=python3 FROM_BOOTSTRAP=1 ./autogen.sh + set +e # bootstrap expects this + } + diff --git a/SOURCES/0119-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch b/SOURCES/0119-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch deleted file mode 100644 index f8284ec..0000000 --- a/SOURCES/0119-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 13 Sep 2018 14:42:34 -0400 -Subject: [PATCH] x86-efi: Re-arrange grub_cmd_linux() a little bit. - -This just helps the next patch be easier to read. - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 75 +++++++++++++++++++++------------------ - 1 file changed, 41 insertions(+), 34 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 2f0336809e7..5f48fa55619 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -243,32 +243,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, -- BYTES_TO_PAGES(sizeof(*params))); -- if (!params) -- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, -- BYTES_TO_PAGES(sizeof(*params))); -- if (! params) -- { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); -- goto fail; -- } -+ lh = (struct linux_i386_kernel_header *)kernel; -+ grub_dprintf ("linux", "original lh is at %p\n", kernel); - -- grub_dprintf ("linux", "params = %p\n", params); -- -- grub_memset (params, 0, sizeof(*params)); -- -- setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); -- grub_dprintf ("linux", "copying %lu bytes from %p to %p\n", -- MIN((grub_size_t)0x202+setup_header_end_offset, -- sizeof (*params)) - 0x1f1, -- (grub_uint8_t *)kernel + 0x1f1, -- (grub_uint8_t *)params + 0x1f1); -- grub_memcpy ((grub_uint8_t *)params + 0x1f1, -- (grub_uint8_t *)kernel + 0x1f1, -- MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1); -- lh = (struct linux_i386_kernel_header *)params; -- grub_dprintf ("linux", "lh is at %p\n", lh); - grub_dprintf ("linux", "checking lh->boot_flag\n"); - if (lh->boot_flag != grub_cpu_to_le16 (0xaa55)) - { -@@ -316,6 +293,34 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, -+ BYTES_TO_PAGES(sizeof(*params))); -+ if (!params) -+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, -+ BYTES_TO_PAGES(sizeof(*params))); -+ if (! params) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); -+ goto fail; -+ } -+ -+ grub_dprintf ("linux", "params = %p\n", params); -+ -+ grub_memset (params, 0, sizeof(*params)); -+ -+ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); -+ grub_dprintf ("linux", "copying %lu bytes from %p to %p\n", -+ MIN((grub_size_t)0x202+setup_header_end_offset, -+ sizeof (*params)) - 0x1f1, -+ (grub_uint8_t *)kernel + 0x1f1, -+ (grub_uint8_t *)params + 0x1f1); -+ grub_memcpy ((grub_uint8_t *)params + 0x1f1, -+ (grub_uint8_t *)kernel + 0x1f1, -+ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1); -+ -+ lh = (struct linux_i386_kernel_header *)params; -+ grub_dprintf ("linux", "new lh is at %p\n", lh); -+ - grub_dprintf ("linux", "setting up cmdline\n"); - linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, - BYTES_TO_PAGES(lh->cmdline_size + 1)); -@@ -341,8 +346,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "setting lh->cmd_line_ptr\n"); - lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline; - -- grub_dprintf ("linux", "computing handover offset\n"); - handover_offset = lh->handover_offset; -+ grub_dprintf("linux", "handover_offset: %08x\n", handover_offset); - - start = (lh->setup_sects + 1) * 512; - -@@ -359,26 +364,28 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); - goto fail; - } -- -- grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem); -+ grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); - - grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); -- loaded=1; -+ -+ loaded = 1; -+ - grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem); - lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem; - - grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start); - -- grub_dprintf ("linux", "setting lh->type_of_loader\n"); - lh->type_of_loader = 0x6; -+ grub_dprintf ("linux", "setting lh->type_of_loader = 0x%02x\n", -+ lh->type_of_loader); - -- grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n"); - params->ext_loader_type = 0; - params->ext_loader_ver = 2; -- grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n", -- kernel_mem, handover_offset); -+ grub_dprintf ("linux", -+ "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n", -+ params->ext_loader_type, params->ext_loader_ver); - -- fail: -+fail: - if (file) - grub_file_close (file); - diff --git a/SOURCES/0120-efi-http-Export-fw-http-_path-variables-to-make-them.patch b/SOURCES/0120-efi-http-Export-fw-http-_path-variables-to-make-them.patch new file mode 100644 index 0000000..f745782 --- /dev/null +++ b/SOURCES/0120-efi-http-Export-fw-http-_path-variables-to-make-them.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Thu, 5 Mar 2020 16:21:47 +0100 +Subject: [PATCH] efi/http: Export {fw,http}_path variables to make them global + +The fw_path environment variable is used by http_configure() function to +determine the HTTP path that should be used as prefix when using relative +HTTP paths. And this is stored in the http_path environment variable. + +Later, that variable is looked up by grub_efihttp_open() to generate the +complete path to be used in the HTTP request. + +But these variables are not exported, which means that are not global and +so are only found in the initial context. + +This can cause commands like configfile that create a new context to fail +because the fw_path and http_path variables will not be found. + +Resolves: rhbz#1616395 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/kern/main.c | 1 + + grub-core/net/efi/http.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 1c540fc8c2..b573be6650 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -143,6 +143,7 @@ grub_set_prefix_and_root (void) + if (fw_path) + { + grub_env_set ("fw_path", fw_path); ++ grub_env_export ("fw_path"); + grub_dprintf ("fw_path", "fw_path:\"%s\"\n", fw_path); + grub_free (fw_path); + } +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +index de351b2cd0..755b7a6d05 100644 +--- a/grub-core/net/efi/http.c ++++ b/grub-core/net/efi/http.c +@@ -39,6 +39,7 @@ http_configure (struct grub_efi_net_device *dev, int prefer_ip6) + http_path++; + grub_env_unset ("http_path"); + grub_env_set ("http_path", http_path); ++ grub_env_export ("http_path"); + } + } + diff --git a/SOURCES/0120-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch b/SOURCES/0120-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch deleted file mode 100644 index 4ad0696..0000000 --- a/SOURCES/0120-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 12 Sep 2018 16:03:55 -0400 -Subject: [PATCH] x86-efi: Make our own allocator for kernel stuff - -This helps enable allocations above 4GB. - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 167 +++++++++++++++++++++----------------- - 1 file changed, 94 insertions(+), 73 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 5f48fa55619..3e4f7ef39f4 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -47,6 +47,65 @@ static char *linux_cmdline; - - #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) - -+struct allocation_choice { -+ grub_efi_physical_address_t addr; -+ grub_efi_allocate_type_t alloc_type; -+}; -+ -+static struct allocation_choice max_addresses[] = -+ { -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { 0, 0 } -+ }; -+ -+static inline void -+kernel_free(void *addr, grub_efi_uintn_t size) -+{ -+ if (addr && size) -+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)addr, -+ BYTES_TO_PAGES(size)); -+} -+ -+static void * -+kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) -+{ -+ void *addr = 0; -+ unsigned int i; -+ grub_efi_physical_address_t prev_max = 0; -+ -+ for (i = 0; max_addresses[i].addr != 0 && addr == 0; i++) -+ { -+ grub_uint64_t max = max_addresses[i].addr; -+ grub_efi_uintn_t pages; -+ -+ if (max == prev_max) -+ continue; -+ -+ pages = BYTES_TO_PAGES(size); -+ grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", -+ pages, (void *)max); -+ -+ prev_max = max; -+ addr = grub_efi_allocate_pages_real (max, pages, -+ max_addresses[i].alloc_type, -+ GRUB_EFI_LOADER_DATA); -+ if (addr) -+ grub_dprintf ("linux", "Allocated at %p\n", addr); -+ } -+ -+ while (grub_error_pop ()) -+ { -+ ; -+ } -+ -+ if (addr == NULL) -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "%s", errmsg); -+ -+ return addr; -+} -+ - static grub_err_t - grub_linuxefi_boot (void) - { -@@ -62,19 +121,12 @@ grub_linuxefi_unload (void) - { - grub_dl_unref (my_mod); - loaded = 0; -- if (initrd_mem) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, -- BYTES_TO_PAGES(params->ramdisk_size)); -- if (linux_cmdline) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) -- linux_cmdline, -- BYTES_TO_PAGES(params->cmdline_size + 1)); -- if (kernel_mem) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, -- BYTES_TO_PAGES(kernel_size)); -- if (params) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params, -- BYTES_TO_PAGES(16384)); -+ -+ kernel_free(initrd_mem, params->ramdisk_size); -+ kernel_free(linux_cmdline, params->cmdline_size + 1); -+ kernel_free(kernel_mem, kernel_size); -+ kernel_free(params, sizeof(*params)); -+ - return GRUB_ERR_NONE; - } - -@@ -150,19 +202,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - size += ALIGN_UP (grub_file_size (files[i]), 4); - } - -- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size)); -- if (!initrd_mem) -- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size)); -- if (!initrd_mem) -- { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd")); -- goto fail; -- } -- -- grub_dprintf ("linux", "initrd_mem = %lx\n", (unsigned long) initrd_mem); -+ initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -+ if (initrd_mem == NULL) -+ goto fail; -+ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); - - params->ramdisk_size = size; -- params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem; -+ params->ramdisk_image = initrd_mem; - - ptr = initrd_mem; - -@@ -221,7 +267,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - filelen = grub_file_size (file); - - kernel = grub_malloc(filelen); -- - if (!kernel) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); -@@ -274,7 +319,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - --#if defined(__x86_64__) || defined(__aarch64__) -+#if defined(__x86_64__) - grub_dprintf ("linux", "checking lh->xloadflags\n"); - if (!(lh->xloadflags & LINUX_XLF_KERNEL_64)) - { -@@ -293,17 +338,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, -- BYTES_TO_PAGES(sizeof(*params))); -+ params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); - if (!params) -- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, -- BYTES_TO_PAGES(sizeof(*params))); -- if (! params) -- { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); -- goto fail; -- } -- -+ goto fail; - grub_dprintf ("linux", "params = %p\n", params); - - grub_memset (params, 0, sizeof(*params)); -@@ -322,19 +359,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "new lh is at %p\n", lh); - - grub_dprintf ("linux", "setting up cmdline\n"); -- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, -- BYTES_TO_PAGES(lh->cmdline_size + 1)); -+ linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); - if (!linux_cmdline) -- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, -- BYTES_TO_PAGES(lh->cmdline_size + 1)); -- if (!linux_cmdline) -- { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline")); -- goto fail; -- } -- -- grub_dprintf ("linux", "linux_cmdline = %lx\n", -- (unsigned long)linux_cmdline); -+ goto fail; -+ grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline); - - grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, -@@ -343,27 +371,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - GRUB_VERIFY_KERNEL_CMDLINE); - - grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); -- grub_dprintf ("linux", "setting lh->cmd_line_ptr\n"); -- lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline; -+ grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", -+ linux_cmdline); -+ lh->cmd_line_ptr = linux_cmdline; - - handover_offset = lh->handover_offset; -- grub_dprintf("linux", "handover_offset: %08x\n", handover_offset); -+ grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset); - - start = (lh->setup_sects + 1) * 512; - -- kernel_mem = grub_efi_allocate_pages_max(lh->pref_address, -- BYTES_TO_PAGES(lh->init_size)); -- if (!kernel_mem) -- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS, -- BYTES_TO_PAGES(lh->init_size)); -- if (!kernel_mem) -- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS, -- BYTES_TO_PAGES(lh->init_size)); -- if (!kernel_mem) -+ grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); -+ if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) - { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); -- goto fail; -+ max_addresses[0].addr = lh->pref_address; -+ max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; - } -+ kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); -+ if (!kernel_mem) -+ goto fail; - grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); - - grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); -@@ -398,18 +423,14 @@ fail: - loaded = 0; - } - -- if (linux_cmdline && lh && !loaded) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) -- linux_cmdline, -- BYTES_TO_PAGES(lh->cmdline_size + 1)); -+ if (!loaded) -+ { -+ if (lh) -+ kernel_free (linux_cmdline, lh->cmdline_size + 1); - -- if (kernel_mem && !loaded) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, -- BYTES_TO_PAGES(kernel_size)); -- -- if (params && !loaded) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params, -- BYTES_TO_PAGES(16384)); -+ kernel_free (kernel_mem, kernel_size); -+ kernel_free (params, sizeof(*params)); -+ } - - return grub_errno; - } diff --git a/SOURCES/0121-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch b/SOURCES/0121-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch new file mode 100644 index 0000000..03d85c2 --- /dev/null +++ b/SOURCES/0121-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch @@ -0,0 +1,114 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Thu, 5 Mar 2020 16:21:58 +0100 +Subject: [PATCH] efi/http: Enclose literal IPv6 addresses in square brackets + +According to RFC 2732 (https://www.ietf.org/rfc/rfc2732.txt), literal IPv6 +addresses must be enclosed in square brackets. But GRUB currently does not +do this and is causing HTTP servers to send Bad Request (400) responses. + +For example, the following is the HTTP stream when fetching a config file: + +HEAD /EFI/BOOT/grub.cfg HTTP/1.1 +Host: 2000:dead:beef:a::1 +Accept: */* +User-Agent: UefiHttpBoot/1.0 + +HTTP/1.1 400 Bad Request +Date: Thu, 05 Mar 2020 14:46:02 GMT +Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d +Connection: close +Content-Type: text/html; charset=iso-8859-1 + +and after enclosing the IPv6 address the HTTP request is successful: + +HEAD /EFI/BOOT/grub.cfg HTTP/1.1 +Host: [2000:dead:beef:a::1] +Accept: */* +User-Agent: UefiHttpBoot/1.0 + +HTTP/1.1 200 OK +Date: Thu, 05 Mar 2020 14:48:04 GMT +Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d +Last-Modified: Thu, 27 Feb 2020 17:45:58 GMT +ETag: "206-59f924b24b1da" +Accept-Ranges: bytes +Content-Length: 518 + +Resolves: rhbz#1732765 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/net/efi/http.c | 37 ++++++++++++++++++++++++++++--------- + 1 file changed, 28 insertions(+), 9 deletions(-) + +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +index 755b7a6d05..fc8cb25ae0 100644 +--- a/grub-core/net/efi/http.c ++++ b/grub-core/net/efi/http.c +@@ -158,13 +158,7 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, + grub_efi_status_t status; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + char *url = NULL; +- +- request_headers[0].field_name = (grub_efi_char8_t *)"Host"; +- request_headers[0].field_value = (grub_efi_char8_t *)server; +- request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; +- request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; +- request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; +- request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0"; ++ char *hostname = NULL; + + { + grub_efi_ipv6_address_t address; +@@ -174,9 +168,24 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, + const char *protocol = (use_https == 1) ? "https" : "http"; + + if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0) +- url = grub_xasprintf ("%s://[%s]%s", protocol, server, name); ++ { ++ hostname = grub_xasprintf ("[%s]", server); ++ if (!hostname) ++ return GRUB_ERR_OUT_OF_MEMORY; ++ ++ server = hostname; ++ ++ url = grub_xasprintf ("%s://%s%s", protocol, server, name); ++ if (!url) ++ { ++ grub_free (hostname); ++ return GRUB_ERR_OUT_OF_MEMORY; ++ } ++ } + else +- url = grub_xasprintf ("%s://%s%s", protocol, server, name); ++ { ++ url = grub_xasprintf ("%s://%s%s", protocol, server, name); ++ } + + if (!url) + { +@@ -199,6 +208,13 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, + request_data.url = ucs2_url; + } + ++ request_headers[0].field_name = (grub_efi_char8_t *)"Host"; ++ request_headers[0].field_value = (grub_efi_char8_t *)server; ++ request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; ++ request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; ++ request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; ++ request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0"; ++ + request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET; + + request_message.data.request = &request_data; +@@ -228,6 +244,9 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, + + status = efi_call_2 (http->request, http, &request_token); + ++ if (hostname) ++ grub_free (hostname); ++ + if (status != GRUB_EFI_SUCCESS) + { + efi_call_1 (b->close_event, request_token.event); diff --git a/SOURCES/0121-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch b/SOURCES/0121-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch deleted file mode 100644 index b1233ce..0000000 --- a/SOURCES/0121-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 12 Sep 2018 16:12:27 -0400 -Subject: [PATCH] x86-efi: Allow initrd+params+cmdline allocations above 4GB. - -This enables everything except the kernel itself to be above 4GB. -Putting the kernel up there still doesn't work, because of the way -params->code32_start is used. - -Signed-off-by: Peter Jones ---- - grub-core/loader/i386/efi/linux.c | 67 +++++++++++++++++++++++++++++++++++---- - include/grub/i386/linux.h | 6 +++- - 2 files changed, 65 insertions(+), 8 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 3e4f7ef39f4..6bc18d5aef5 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -52,13 +52,22 @@ struct allocation_choice { - grub_efi_allocate_type_t alloc_type; - }; - --static struct allocation_choice max_addresses[] = -+static struct allocation_choice max_addresses[4] = - { -+ /* the kernel overrides this one with pref_address and -+ * GRUB_EFI_ALLOCATE_ADDRESS */ - { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ /* this one is always below 4GB, which we still *prefer* even if the flag -+ * is set. */ - { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ /* If the flag in params is set, this one gets changed to be above 4GB. */ - { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - { 0, 0 } - }; -+static struct allocation_choice saved_addresses[4]; -+ -+#define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses)) -+#define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses)) - - static inline void - kernel_free(void *addr, grub_efi_uintn_t size) -@@ -80,6 +89,11 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) - grub_uint64_t max = max_addresses[i].addr; - grub_efi_uintn_t pages; - -+ /* -+ * When we're *not* loading the kernel, or >4GB allocations aren't -+ * supported, these entries are basically all the same, so don't re-try -+ * the same parameters. -+ */ - if (max == prev_max) - continue; - -@@ -168,6 +182,9 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) - return bufpos; - } - -+#define LOW_U32(val) ((grub_uint32_t)(((grub_addr_t)(val)) & 0xffffffffull)) -+#define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull)) -+ - static grub_err_t - grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -@@ -207,8 +224,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - goto fail; - grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); - -- params->ramdisk_size = size; -- params->ramdisk_image = initrd_mem; -+ params->ramdisk_size = LOW_U32(size); -+ params->ramdisk_image = LOW_U32(initrd_mem); -+#if defined(__x86_64__) -+ params->ext_ramdisk_size = HIGH_U32(size); -+ params->ext_ramdisk_image = HIGH_U32(initrd_mem); -+#endif - - ptr = initrd_mem; - -@@ -338,6 +359,18 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -+#if defined(__x86_64__) -+ if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) -+ { -+ grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); -+ max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS; -+ } -+ else -+ { -+ grub_dprintf ("linux", "Loading kernel above 4GB is not supported\n"); -+ } -+#endif -+ - params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); - if (!params) - goto fail; -@@ -372,21 +405,40 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); - grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", -- linux_cmdline); -- lh->cmd_line_ptr = linux_cmdline; -+ LOW_U32(linux_cmdline)); -+ lh->cmd_line_ptr = LOW_U32(linux_cmdline); -+#if defined(__x86_64__) -+ if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull) -+ { -+ grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n", -+ HIGH_U32(linux_cmdline)); -+ params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline); -+ } -+#endif - - handover_offset = lh->handover_offset; - grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset); - - start = (lh->setup_sects + 1) * 512; - -+ /* -+ * AFAICS >4GB for kernel *cannot* work because of params->code32_start being -+ * 32-bit and getting called unconditionally in head_64.S from either entry -+ * point. -+ * -+ * so nerf that out here... -+ */ -+ save_addresses(); - grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); - if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) - { - max_addresses[0].addr = lh->pref_address; - max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; - } -+ max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); -+ restore_addresses(); - if (!kernel_mem) - goto fail; - grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); -@@ -395,8 +447,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - loaded = 1; - -- grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem); -- lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem; -+ grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n", -+ LOW_U32(kernel_mem)); -+ lh->code32_start = LOW_U32(kernel_mem); - - grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start); - -diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h -index 25ef52c04eb..fac22476cc5 100644 ---- a/include/grub/i386/linux.h -+++ b/include/grub/i386/linux.h -@@ -236,7 +236,11 @@ struct linux_kernel_params - grub_uint32_t ofw_cif_handler; /* b8 */ - grub_uint32_t ofw_idt; /* bc */ - -- grub_uint8_t padding7[0x1b8 - 0xc0]; -+ grub_uint32_t ext_ramdisk_image; /* 0xc0 */ -+ grub_uint32_t ext_ramdisk_size; /* 0xc4 */ -+ grub_uint32_t ext_cmd_line_ptr; /* 0xc8 */ -+ -+ grub_uint8_t padding7[0x1b8 - 0xcc]; - - union - { diff --git a/SOURCES/0122-Fix-getroot.c-s-trampolines.patch b/SOURCES/0122-Fix-getroot.c-s-trampolines.patch deleted file mode 100644 index 29ec44c..0000000 --- a/SOURCES/0122-Fix-getroot.c-s-trampolines.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 28 Sep 2018 15:42:19 -0400 -Subject: [PATCH] Fix getroot.c's trampolines. - -This makes the stack executable on most of the grub utilities, which is -bad, and rpmdiff complains about it. - -Signed-off-by: Peter Jones ---- - grub-core/osdep/linux/getroot.c | 16 +++++++--------- - 1 file changed, 7 insertions(+), 9 deletions(-) - -diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c -index 9f730b35189..f0c503f43d3 100644 ---- a/grub-core/osdep/linux/getroot.c -+++ b/grub-core/osdep/linux/getroot.c -@@ -1264,22 +1264,20 @@ grub_util_get_grub_dev_os (const char *os_dev) - return grub_dev; - } - -+static void *mp = NULL; -+static void -+btrfs_mount_path_hook(const char *m) -+{ -+ mp = strdup (m); -+} - - char * - grub_util_get_btrfs_subvol (const char *path, char **mount_path) - { -- char *mp = NULL; -- - if (mount_path) - *mount_path = NULL; - -- auto void -- mount_path_hook (const char *m) -- { -- mp = strdup (m); -- } -- -- grub_find_root_btrfs_mount_path_hook = mount_path_hook; -+ grub_find_root_btrfs_mount_path_hook = btrfs_mount_path_hook; - grub_free (grub_find_root_devices_from_mountinfo (path, NULL)); - grub_find_root_btrfs_mount_path_hook = NULL; - diff --git a/SOURCES/0122-efi-net-Allow-to-specify-a-port-number-in-addresses.patch b/SOURCES/0122-efi-net-Allow-to-specify-a-port-number-in-addresses.patch new file mode 100644 index 0000000..8fe26cd --- /dev/null +++ b/SOURCES/0122-efi-net-Allow-to-specify-a-port-number-in-addresses.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 9 Mar 2020 15:29:45 +0100 +Subject: [PATCH] efi/net: Allow to specify a port number in addresses + +The grub_efi_net_parse_address() function is not covering the case where a +port number is specified in an IPv4 or IPv6 address, so will fail to parse +the network address. + +For most cases the issue is harmless, because the function is only used to +match an address with a network interface and if fails the default is used. + +But still is a bug that has to be fixed and it causes error messages to be +printed like the following: + +error: net/efi/net.c:782:unrecognised network address '192.168.122.1:8080' + +error: net/efi/net.c:781:unrecognised network address '[2000:dead:beef:a::1]:8080' + +Resolves: rhbz#1732765 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/net/efi/net.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +index 6603cd83ed..84573937b1 100644 +--- a/grub-core/net/efi/net.c ++++ b/grub-core/net/efi/net.c +@@ -742,7 +742,7 @@ grub_efi_net_parse_address (const char *address, + return GRUB_ERR_NONE; + } + } +- else if (*rest == 0) ++ else if (*rest == 0 || *rest == ':') + { + grub_uint32_t subnet_mask = 0xffffffffU; + grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); +@@ -768,7 +768,7 @@ grub_efi_net_parse_address (const char *address, + return GRUB_ERR_NONE; + } + } +- else if (*rest == 0) ++ else if (*rest == 0 || *rest == ':') + { + ip6->prefix_length = 128; + ip6->is_anycast = 0; diff --git a/SOURCES/0123-Do-not-allow-stack-trampolines-anywhere.patch b/SOURCES/0123-Do-not-allow-stack-trampolines-anywhere.patch deleted file mode 100644 index 4ee639d..0000000 --- a/SOURCES/0123-Do-not-allow-stack-trampolines-anywhere.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 12 Jul 2019 10:06:50 +0200 -Subject: [PATCH] Do not allow stack trampolines, anywhere. - -Signed-off-by: Peter Jones ---- - configure.ac | 3 +++ - conf/Makefile.common | 2 +- - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index bd28edf3141..907477a585c 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2062,6 +2062,9 @@ if test x"$enable_wextra" != xno ; then - HOST_CFLAGS="$HOST_CFLAGS -Wextra" - fi - -+TARGET_CFLAGS="$TARGET_CFLAGS -Werror=trampolines -fno-trampolines" -+HOST_CFLAGS="$HOST_CFLAGS -Werror=trampolines -fno-trampolines" -+ - TARGET_CPP="$TARGET_CC -E" - TARGET_CCAS=$TARGET_CC - -diff --git a/conf/Makefile.common b/conf/Makefile.common -index 35e14ff017e..0647c53b916 100644 ---- a/conf/Makefile.common -+++ b/conf/Makefile.common -@@ -66,7 +66,7 @@ grubconfdir = $(sysconfdir)/grub.d - platformdir = $(pkglibdir)/$(target_cpu)-$(platform) - starfielddir = $(pkgdatadir)/themes/starfield - --CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -+CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Werror=trampolines -fno-trampolines - CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib - - CFLAGS_POSIX = -fno-builtin diff --git a/SOURCES/0123-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch b/SOURCES/0123-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch new file mode 100644 index 0000000..2dc7001 --- /dev/null +++ b/SOURCES/0123-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 9 Mar 2020 15:30:05 +0100 +Subject: [PATCH] efi/ip4_config: Improve check to detect literal IPv6 + addresses + +The grub_efi_string_to_ip4_address() function wrongly assumes that an IPv6 +address is an IPv4 address, because it doesn't take into account the case +of a caller passing an IPv6 address as a string. + +This leads to the grub_efi_net_parse_address() function to fail and print +the following error message: + +error: net/efi/net.c:785:unrecognised network address '2000:dead:beef:a::1' + +Resolves: rhbz#1732765 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/net/efi/ip4_config.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c +index b711a5d945..313c818b18 100644 +--- a/grub-core/net/efi/ip4_config.c ++++ b/grub-core/net/efi/ip4_config.c +@@ -56,9 +56,20 @@ int + grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest) + { + grub_uint32_t newip = 0; +- int i; ++ int i, ncolon = 0; + const char *ptr = val; + ++ /* Check that is not an IPv6 address */ ++ for (i = 0; i < grub_strlen(ptr); i++) ++ { ++ if (ptr[i] == '[' && i == 0) ++ return 0; ++ ++ if (ptr[i] == ':') ++ if (i == 0 || ++ncolon == 2) ++ return 0; ++ } ++ + for (i = 0; i < 4; i++) + { + unsigned long t; diff --git a/SOURCES/0124-Reimplement-boot_counter.patch b/SOURCES/0124-Reimplement-boot_counter.patch deleted file mode 100644 index 164b229..0000000 --- a/SOURCES/0124-Reimplement-boot_counter.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 4 Oct 2018 14:22:09 -0400 -Subject: [PATCH] Reimplement boot_counter - -This adds "increment" and "decrement" commands, and uses them to maintain our -variables in 01_fallback_counter. It also simplifies the counter logic, so -that there are no nested tests that conflict with each other. - -Apparently, this *really* wasn't tested well enough. - -Resolves: rhbz#1614637 -Signed-off-by: Peter Jones -[lorbus: add comments and revert logic changes in 01_fallback_counting] -Signed-off-by: Christian Glombek ---- - Makefile.util.def | 6 +++ - grub-core/Makefile.core.def | 5 ++ - grub-core/commands/increment.c | 105 ++++++++++++++++++++++++++++++++++++ - util/grub.d/01_fallback_counting.in | 22 ++++++++ - 4 files changed, 138 insertions(+) - create mode 100644 grub-core/commands/increment.c - create mode 100644 util/grub.d/01_fallback_counting.in - -diff --git a/Makefile.util.def b/Makefile.util.def -index c6375933faa..2e5e05b25f1 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -458,6 +458,12 @@ script = { - installdir = grubconf; - }; - -+script = { -+ name = '01_fallback_counting'; -+ common = util/grub.d/01_fallback_counting.in; -+ installdir = grubconf; -+}; -+ - script = { - name = '01_menu_auto_hide'; - common = util/grub.d/01_menu_auto_hide.in; -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 498ca11762a..1e15345107e 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -398,6 +398,11 @@ kernel = { - extra_dist = kern/mips/cache_flush.S; - }; - -+module = { -+ name = increment; -+ common = commands/increment.c; -+}; -+ - program = { - name = grub-emu; - mansection = 1; -diff --git a/grub-core/commands/increment.c b/grub-core/commands/increment.c -new file mode 100644 -index 00000000000..79cf137656c ---- /dev/null -+++ b/grub-core/commands/increment.c -@@ -0,0 +1,105 @@ -+/* increment.c - Commands to increment and decrement variables. */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+typedef enum { -+ INCREMENT, -+ DECREMENT, -+} operation; -+ -+static grub_err_t -+incr_decr(operation op, int argc, char **args) -+{ -+ const char *old; -+ char *new; -+ long value; -+ -+ if (argc < 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no variable specified")); -+ if (argc > 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("too many arguments")); -+ -+ old = grub_env_get (*args); -+ if (!old) -+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("No such variable \"%s\""), -+ *args); -+ -+ value = grub_strtol (old, NULL, 0); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ -+ switch (op) -+ { -+ case INCREMENT: -+ value += 1; -+ break; -+ case DECREMENT: -+ value -= 1; -+ break; -+ } -+ -+ new = grub_xasprintf ("%ld", value); -+ if (!new) -+ return grub_errno; -+ -+ grub_env_set (*args, new); -+ grub_free (new); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_incr(struct grub_command *cmd UNUSED, -+ int argc, char **args) -+{ -+ return incr_decr(INCREMENT, argc, args); -+} -+ -+static grub_err_t -+grub_cmd_decr(struct grub_command *cmd UNUSED, -+ int argc, char **args) -+{ -+ return incr_decr(DECREMENT, argc, args); -+} -+ -+static grub_command_t cmd_incr, cmd_decr; -+ -+GRUB_MOD_INIT(increment) -+{ -+ cmd_incr = grub_register_command ("increment", grub_cmd_incr, N_("VARIABLE"), -+ N_("increment VARIABLE")); -+ cmd_decr = grub_register_command ("decrement", grub_cmd_decr, N_("VARIABLE"), -+ N_("decrement VARIABLE")); -+} -+ -+GRUB_MOD_FINI(increment) -+{ -+ grub_unregister_command (cmd_incr); -+ grub_unregister_command (cmd_decr); -+} -diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/01_fallback_counting.in -new file mode 100644 -index 00000000000..be0e770ea82 ---- /dev/null -+++ b/util/grub.d/01_fallback_counting.in -@@ -0,0 +1,22 @@ -+#! /bin/sh -e -+ -+# Boot Counting -+# The boot_counter env var can be used to count down boot attempts after an -+# OSTree upgrade and choose the rollback deployment when 0 is reached. Both -+# boot_counter and boot_success need to be (re-)set from userspace. -+cat << EOF -+insmod increment -+# Check if boot_counter exists and boot_success=0 to activate this behaviour. -+if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then -+ # if countdown has ended, choose to boot rollback deployment (default=1 on -+ # OSTree-based systems) -+ if [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then -+ set default=1 -+ set boot_counter=-1 -+ # otherwise decrement boot_counter -+ else -+ decrement boot_counter -+ fi -+ save_env boot_counter -+fi -+EOF diff --git a/SOURCES/0124-efi-net-Print-a-debug-message-if-parsing-the-address.patch b/SOURCES/0124-efi-net-Print-a-debug-message-if-parsing-the-address.patch new file mode 100644 index 0000000..da94e08 --- /dev/null +++ b/SOURCES/0124-efi-net-Print-a-debug-message-if-parsing-the-address.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 10 Mar 2020 11:23:49 +0100 +Subject: [PATCH] efi/net: Print a debug message if parsing the address fails + +Currently if parsing the address fails an error message is printed. But in +most cases this isn't a fatal error since the grub_efi_net_parse_address() +function is only used to match an address with a network interface to use. + +And if this fails, the default interface is used which is good enough for +most cases. So instead of printing an error that would pollute the console +just print a debug message if the address is not parsed correctly. + +A user can enable debug messages for the efinet driver to have information +about the failure and the fact that the default interface is being used. + +Related: rhbz#1732765 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/net/efi/net.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +index 84573937b1..a3f0535d43 100644 +--- a/grub-core/net/efi/net.c ++++ b/grub-core/net/efi/net.c +@@ -778,9 +778,9 @@ grub_efi_net_parse_address (const char *address, + } + } + +- return grub_error (GRUB_ERR_NET_BAD_ADDRESS, +- N_("unrecognised network address `%s'"), +- address); ++ grub_dprintf ("efinet", "unrecognised network address '%s'\n", address); ++ ++ return GRUB_ERR_NET_BAD_ADDRESS; + } + + static grub_efi_net_interface_t * +@@ -795,10 +795,7 @@ match_route (const char *server) + err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0); + + if (err) +- { +- grub_print_error (); + return NULL; +- } + + if (is_ip6) + { +@@ -1233,8 +1230,15 @@ grub_net_open_real (const char *name __attribute__ ((unused))) + /*FIXME: Use DNS translate name to address */ + net_interface = match_route (server); + ++ if (!net_interface && net_default_interface) ++ { ++ net_interface = net_default_interface; ++ grub_dprintf ("efinet", "interface lookup failed, using default '%s'\n", ++ net_interface->name); ++ } ++ + /*XXX: should we check device with default gateway ? */ +- if (!net_interface && !(net_interface = net_default_interface)) ++ if (!net_interface) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"), + name); diff --git a/SOURCES/0125-Fix-menu-entry-selection-based-on-ID-and-title.patch b/SOURCES/0125-Fix-menu-entry-selection-based-on-ID-and-title.patch deleted file mode 100644 index 84c1370..0000000 --- a/SOURCES/0125-Fix-menu-entry-selection-based-on-ID-and-title.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 19 Oct 2018 10:57:52 -0400 -Subject: [PATCH] Fix menu entry selection based on ID and title - -Currently if grub_strtoul(saved_entry_value, NULL, 0) does not return an -error, we assume the value it has produced is a correct index into our -menu entry list, and do not try to interpret the value as the "id" or -"title" . In cases where "id" or "title" start with a numeral, this -makes them impossible to use as selection criteria. - -This patch splits the search into three phases - matching id, matching -title, and only once those have been exhausted, trying to interpret the -ID as a numeral. In that case, we also require that the entire string -is numeric, not merely a string with leading numeric characters. - -Resolves: rhbz#1640979 - -Signed-off-by: Peter Jones -[javierm: fix menu entry selection based on title] -Signed-off-by: Javier Martinez Canillas ---- - grub-core/normal/menu.c | 141 ++++++++++++++++++++++++------------------------ - 1 file changed, 71 insertions(+), 70 deletions(-) - -diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c -index 37d753d8081..ea714d27176 100644 ---- a/grub-core/normal/menu.c -+++ b/grub-core/normal/menu.c -@@ -164,12 +164,12 @@ grub_menu_set_timeout (int timeout) - } - - static int --menuentry_eq (const char *id, const char *spec) -+menuentry_eq (const char *id, const char *spec, int limit) - { - const char *ptr1, *ptr2; - ptr1 = id; - ptr2 = spec; -- while (1) -+ while (limit == -1 || ptr1 - id <= limit) - { - if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0) - return ptr2 - spec; -@@ -178,7 +178,11 @@ menuentry_eq (const char *id, const char *spec) - if (*ptr2 == '>') - ptr2++; - if (*ptr1 != *ptr2) -- return 0; -+ { -+ if (limit > -1 && ptr1 - id == limit && !*ptr1 && grub_isspace(*ptr2)) -+ return ptr1 -id -1; -+ return 0; -+ } - if (*ptr1 == 0) - return ptr1 - id; - ptr1++; -@@ -187,6 +191,58 @@ menuentry_eq (const char *id, const char *spec) - return 0; - } - -+static int -+get_entry_number_helper(grub_menu_t menu, -+ const char * const val, const char ** const tail) -+{ -+ /* See if the variable matches the title of a menu entry. */ -+ int entry = -1; -+ grub_menu_entry_t e; -+ int i; -+ -+ for (i = 0, e = menu->entry_list; e; i++) -+ { -+ int l = 0; -+ while (val[l] && !grub_isspace(val[l])) -+ l++; -+ -+ if (menuentry_eq (e->id, val, l)) -+ { -+ if (tail) -+ *tail = val + l; -+ return i; -+ } -+ e = e->next; -+ } -+ -+ for (i = 0, e = menu->entry_list; e; i++) -+ { -+ -+ if (menuentry_eq (e->title, val, -1)) -+ { -+ if (tail) -+ *tail = NULL; -+ return i; -+ } -+ e = e->next; -+ } -+ -+ if (tail) -+ *tail = NULL; -+ -+ entry = (int) grub_strtoul (val, tail, 0); -+ if (grub_errno == GRUB_ERR_BAD_NUMBER || -+ (*tail && **tail && !grub_isspace(**tail))) -+ { -+ entry = -1; -+ if (tail) -+ *tail = NULL; -+ grub_errno = GRUB_ERR_NONE; -+ } -+ -+ return entry; -+} -+ - /* Get the first entry number from the value of the environment variable NAME, - which is a space-separated list of non-negative integers. The entry number - which is returned is stripped from the value of NAME. If no entry number -@@ -196,7 +252,6 @@ get_and_remove_first_entry_number (grub_menu_t menu, const char *name) - { - const char *val, *tail; - int entry; -- int sz = 0; - - val = grub_env_get (name); - if (! val) -@@ -204,50 +259,24 @@ get_and_remove_first_entry_number (grub_menu_t menu, const char *name) - - grub_error_push (); - -- entry = (int) grub_strtoul (val, &tail, 0); -+ entry = get_entry_number_helper(menu, val, &tail); -+ if (!(*tail == 0 || grub_isspace(*tail))) -+ entry = -1; - -- if (grub_errno == GRUB_ERR_BAD_NUMBER) -+ if (entry >= 0) - { -- /* See if the variable matches the title of a menu entry. */ -- grub_menu_entry_t e = menu->entry_list; -- int i; -- -- for (i = 0; e; i++) -- { -- sz = menuentry_eq (e->title, val); -- if (sz < 1) -- sz = menuentry_eq (e->id, val); -- -- if (sz >= 1) -- { -- entry = i; -- break; -- } -- e = e->next; -- } -- -- if (sz > 0) -- grub_errno = GRUB_ERR_NONE; -- -- if (! e) -- entry = -1; -- } -- -- if (grub_errno == GRUB_ERR_NONE) -- { -- if (sz > 0) -- tail += sz; -- - /* Skip whitespace to find the next entry. */ - while (*tail && grub_isspace (*tail)) - tail++; -- grub_env_set (name, tail); -+ if (*tail) -+ grub_env_set (name, tail); -+ else -+ grub_env_unset (name); - } - else - { - grub_env_unset (name); - grub_errno = GRUB_ERR_NONE; -- entry = -1; - } - - grub_error_pop (); -@@ -524,6 +553,7 @@ static int - get_entry_number (grub_menu_t menu, const char *name) - { - const char *val; -+ const char *tail; - int entry; - - val = grub_env_get (name); -@@ -531,38 +561,9 @@ get_entry_number (grub_menu_t menu, const char *name) - return -1; - - grub_error_push (); -- -- entry = (int) grub_strtoul (val, 0, 0); -- -- if (grub_errno == GRUB_ERR_BAD_NUMBER) -- { -- /* See if the variable matches the title of a menu entry. */ -- grub_menu_entry_t e = menu->entry_list; -- int i; -- -- grub_errno = GRUB_ERR_NONE; -- -- for (i = 0; e; i++) -- { -- if (menuentry_eq (e->title, val) -- || menuentry_eq (e->id, val)) -- { -- entry = i; -- break; -- } -- e = e->next; -- } -- -- if (! e) -- entry = -1; -- } -- -- if (grub_errno != GRUB_ERR_NONE) -- { -- grub_errno = GRUB_ERR_NONE; -- entry = -1; -- } -- -+ entry = get_entry_number_helper(menu, val, &tail); -+ if (tail && *tail != '\0') -+ entry = -1; - grub_error_pop (); - - return entry; diff --git a/SOURCES/0125-kern-term-Also-accept-F8-as-a-user-interrupt-key.patch b/SOURCES/0125-kern-term-Also-accept-F8-as-a-user-interrupt-key.patch new file mode 100644 index 0000000..8793b0d --- /dev/null +++ b/SOURCES/0125-kern-term-Also-accept-F8-as-a-user-interrupt-key.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Wed, 22 Apr 2020 12:41:52 +0200 +Subject: [PATCH] kern/term: Also accept F8 as a user interrupt key + +Make F8, which used to be the hotkey to show the Windows boot menu during +boot for a long long time, also interrupt sleeps / stop the menu countdown. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/kern/term.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c +index 14d5964983..4d61f4e979 100644 +--- a/grub-core/kern/term.c ++++ b/grub-core/kern/term.c +@@ -144,9 +144,10 @@ grub_key_is_interrupt (int key) + /* + * ESC sometimes is the BIOS setup hotkey and may be hard to discover, also + * check F4, which was chosen because is not used as a hotkey to enter the +- * BIOS setup by any vendor. ++ * BIOS setup by any vendor. Also, F8 which was the key to get the Windows ++ * bootmenu for a long time. + */ +- if (key == GRUB_TERM_ESC || key == GRUB_TERM_KEY_F4) ++ if (key == GRUB_TERM_ESC || key == GRUB_TERM_KEY_F4 || key == GRUB_TERM_KEY_F8) + return 1; + + /* diff --git a/SOURCES/0126-Make-the-menu-entry-users-option-argument-to-be-opti.patch b/SOURCES/0126-Make-the-menu-entry-users-option-argument-to-be-opti.patch deleted file mode 100644 index e0d36db..0000000 --- a/SOURCES/0126-Make-the-menu-entry-users-option-argument-to-be-opti.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 26 Nov 2018 10:06:42 +0100 -Subject: [PATCH] Make the menu entry users option argument to be optional - -The --users option is used to restrict the access to specific menu entries -only to a set of users. But the option requires an argument to either be a -constant or a variable that has been set. So for example the following: - - menuentry "May be run by superusers or users in $users" --users $users { - linux /vmlinuz - } - -Would fail if $users is not defined and grub would discard the menu entry. -Instead, allow the --users option to have an optional argument and ignore -the option if the argument was not set. - -Related: rhbz#1652434 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/commands/menuentry.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c -index b194123eb67..b175a1b43b7 100644 ---- a/grub-core/commands/menuentry.c -+++ b/grub-core/commands/menuentry.c -@@ -29,7 +29,7 @@ static const struct grub_arg_option options[] = - { - {"class", 1, GRUB_ARG_OPTION_REPEATABLE, - N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING}, -- {"users", 2, 0, -+ {"users", 2, GRUB_ARG_OPTION_OPTIONAL, - N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"), - ARG_TYPE_STRING}, - {"hotkey", 3, 0, -@@ -281,7 +281,7 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) - if (! ctxt->state[3].set && ! ctxt->script) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition"); - -- if (ctxt->state[1].set) -+ if (ctxt->state[1].set && ctxt->state[1].arg) - users = ctxt->state[1].arg; - else if (ctxt->state[5].set) - users = NULL; diff --git a/SOURCES/0126-efi-Set-image-base-address-before-jumping-to-the-PE-.patch b/SOURCES/0126-efi-Set-image-base-address-before-jumping-to-the-PE-.patch new file mode 100644 index 0000000..6aa5013 --- /dev/null +++ b/SOURCES/0126-efi-Set-image-base-address-before-jumping-to-the-PE-.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Thu, 23 Apr 2020 15:06:46 +0200 +Subject: [PATCH] efi: Set image base address before jumping to the PE/COFF + entry point + +Upstream GRUB uses the EFI LoadImage() and StartImage() to boot the Linux +kernel. But our custom EFI loader that supports Secure Boot instead uses +the EFI handover protocol (for x86) or jumping directly to the PE/COFF +entry point (for aarch64). + +This is done to allow the bootloader to verify the images using the shim +lock protocol to avoid booting untrusted binaries. + +Since the bootloader loads the kernel from the boot media instead of using +LoadImage(), it is responsible to set the Loaded Image base address before +booting the kernel. + +Otherwise the kernel EFI stub will complain that it was not set correctly +and print the following warning message: + +EFI stub: ERROR: FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value + +Resolves: rhbz#1814690 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/loader/efi/linux.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 0622dfa48d..e8b9ecb17f 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -72,6 +72,7 @@ grub_err_t + grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, + void *kernel_params) + { ++ grub_efi_loaded_image_t *loaded_image = NULL; + handover_func hf; + int offset = 0; + +@@ -79,6 +80,19 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, + offset = 512; + #endif + ++ /* ++ * Since the EFI loader is not calling the LoadImage() and StartImage() ++ * services for loading the kernel and booting respectively, it has to ++ * set the Loaded Image base address. ++ */ ++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (loaded_image) ++ loaded_image->image_base = kernel_addr; ++ else ++ grub_dprintf ("linux", "Loaded Image base address could not be set\n"); ++ ++ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", ++ kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); + hf = (handover_func)((char *)kernel_addr + handover_offset + offset); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); + diff --git a/SOURCES/0127-Add-efi-export-env-and-efi-load-env-commands.patch b/SOURCES/0127-Add-efi-export-env-and-efi-load-env-commands.patch deleted file mode 100644 index 73456bc..0000000 --- a/SOURCES/0127-Add-efi-export-env-and-efi-load-env-commands.patch +++ /dev/null @@ -1,346 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 16 Jan 2019 13:21:46 -0500 -Subject: [PATCH] Add efi-export-env and efi-load-env commands - -This adds "efi-export-env VARIABLE" and "efi-load-env", which manipulate the -environment block stored in the EFI variable -GRUB_ENV-91376aff-cba6-42be-949d-06fde81128e8. - -Signed-off-by: Peter Jones ---- - grub-core/Makefile.core.def | 6 ++ - grub-core/commands/efi/env.c | 168 +++++++++++++++++++++++++++++++++++++++++++ - grub-core/kern/efi/efi.c | 3 + - grub-core/kern/efi/init.c | 5 -- - grub-core/lib/envblk.c | 43 +++++++++++ - util/grub-set-bootflag.c | 1 + - include/grub/efi/efi.h | 5 ++ - include/grub/lib/envblk.h | 3 + - 8 files changed, 229 insertions(+), 5 deletions(-) - create mode 100644 grub-core/commands/efi/env.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 1e15345107e..81fc274148e 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -820,6 +820,12 @@ module = { - enable = efi; - }; - -+module = { -+ name = efienv; -+ common = commands/efi/env.c; -+ enable = efi; -+}; -+ - module = { - name = efifwsetup; - efi = commands/efi/efifwsetup.c; -diff --git a/grub-core/commands/efi/env.c b/grub-core/commands/efi/env.c -new file mode 100644 -index 00000000000..cbd13e03e81 ---- /dev/null -+++ b/grub-core/commands/efi/env.c -@@ -0,0 +1,168 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2012 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static const grub_efi_guid_t grub_env_guid = GRUB_EFI_GRUB_VARIABLE_GUID; -+ -+static grub_err_t -+grub_efi_export_env(grub_command_t cmd __attribute__ ((unused)), -+ int argc, char *argv[]) -+{ -+ const char *value; -+ char *old_value; -+ struct grub_envblk envblk_s = { NULL, 0 }; -+ grub_envblk_t envblk = &envblk_s; -+ grub_err_t err; -+ int changed = 1; -+ grub_efi_status_t status; -+ -+ grub_dprintf ("efienv", "argc:%d\n", argc); -+ for (int i = 0; i < argc; i++) -+ grub_dprintf ("efienv", "argv[%d]: %s\n", i, argv[i]); -+ -+ if (argc != 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable name expected")); -+ -+ grub_efi_get_variable ("GRUB_ENV", &grub_env_guid, &envblk_s.size, -+ (void **) &envblk_s.buf); -+ if (!envblk_s.buf || envblk_s.size < 1) -+ { -+ char *buf = grub_malloc (1025); -+ if (!buf) -+ return grub_errno; -+ -+ grub_memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); -+ grub_memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', -+ DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); -+ buf[1024] = '\0'; -+ -+ envblk_s.buf = buf; -+ envblk_s.size = 1024; -+ } -+ else -+ { -+ char *buf = grub_realloc (envblk_s.buf, envblk_s.size + 1); -+ if (!buf) -+ return grub_errno; -+ -+ envblk_s.buf = buf; -+ envblk_s.buf[envblk_s.size] = '\0'; -+ } -+ -+ err = grub_envblk_get(envblk, argv[0], &old_value); -+ if (err != GRUB_ERR_NONE) -+ { -+ grub_dprintf ("efienv", "grub_envblk_get returned %d\n", err); -+ return err; -+ } -+ -+ value = grub_env_get(argv[0]); -+ if ((!value && !old_value) || -+ (value && old_value && !grub_strcmp(old_value, value))) -+ changed = 0; -+ -+ if (old_value) -+ grub_free(old_value); -+ -+ if (changed == 0) -+ { -+ grub_dprintf ("efienv", "No changes necessary\n"); -+ return 0; -+ } -+ -+ if (value) -+ { -+ grub_dprintf ("efienv", "setting \"%s\" to \"%s\"\n", argv[0], value); -+ grub_envblk_set(envblk, argv[0], value); -+ } -+ else -+ { -+ grub_dprintf ("efienv", "deleting \"%s\" from envblk\n", argv[0]); -+ grub_envblk_delete(envblk, argv[0]); -+ } -+ -+ grub_dprintf ("efienv", "envblk is %lu bytes:\n\"%s\"\n", envblk_s.size, envblk_s.buf); -+ -+ grub_dprintf ("efienv", "removing GRUB_ENV\n"); -+ status = grub_efi_set_variable ("GRUB_ENV", &grub_env_guid, NULL, 0); -+ if (status != GRUB_EFI_SUCCESS) -+ grub_dprintf ("efienv", "removal returned %ld\n", status); -+ -+ grub_dprintf ("efienv", "setting GRUB_ENV\n"); -+ status = grub_efi_set_variable ("GRUB_ENV", &grub_env_guid, -+ envblk_s.buf, envblk_s.size); -+ if (status != GRUB_EFI_SUCCESS) -+ grub_dprintf ("efienv", "setting GRUB_ENV returned %ld\n", status); -+ -+ return 0; -+} -+ -+static int -+set_var (const char *name, const char *value, -+ void *whitelist __attribute__((__unused__))) -+{ -+ grub_env_set (name, value); -+ return 0; -+} -+ -+static grub_err_t -+grub_efi_load_env(grub_command_t cmd __attribute__ ((unused)), -+ int argc, char *argv[] __attribute__((__unused__))) -+{ -+ struct grub_envblk envblk_s = { NULL, 0 }; -+ grub_envblk_t envblk = &envblk_s; -+ -+ grub_efi_get_variable ("GRUB_ENV", &grub_env_guid, &envblk_s.size, -+ (void **) &envblk_s.buf); -+ if (!envblk_s.buf || envblk_s.size < 1) -+ return 0; -+ -+ if (argc > 0) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unexpected argument")); -+ -+ grub_envblk_iterate (envblk, NULL, set_var); -+ grub_free (envblk_s.buf); -+} -+ -+static grub_command_t export_cmd, loadenv_cmd; -+ -+GRUB_MOD_INIT(lsefi) -+{ -+ export_cmd = grub_register_command ("efi-export-env", grub_efi_export_env, -+ N_("VARIABLE_NAME"), N_("Export environment variable to UEFI.")); -+ loadenv_cmd = grub_register_command ("efi-load-env", grub_efi_load_env, -+ NULL, N_("Load the grub environment from UEFI.")); -+} -+ -+GRUB_MOD_FINI(lsefi) -+{ -+ grub_unregister_command (export_cmd); -+ grub_unregister_command (loadenv_cmd); -+} -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index 2a446f5031b..14bc10eb564 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -225,6 +225,9 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, - if (status == GRUB_EFI_SUCCESS) - return GRUB_ERR_NONE; - -+ if (status == GRUB_EFI_NOT_FOUND && datasize == 0) -+ return GRUB_ERR_NONE; -+ - return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var); - } - -diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c -index 2d12e6188fd..0574d8d6217 100644 ---- a/grub-core/kern/efi/init.c -+++ b/grub-core/kern/efi/init.c -@@ -85,11 +85,6 @@ stack_protector_init (void) - - grub_addr_t grub_modbase; - --#define GRUB_EFI_GRUB_VARIABLE_GUID \ -- { 0x91376aff, 0xcba6, 0x42be, \ -- { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \ -- } -- - /* Helper for grub_efi_env_init */ - static int - set_var (const char *name, const char *value, -diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c -index 2e4e78b132d..874506da169 100644 ---- a/grub-core/lib/envblk.c -+++ b/grub-core/lib/envblk.c -@@ -223,6 +223,49 @@ grub_envblk_delete (grub_envblk_t envblk, const char *name) - } - } - -+struct get_var_state { -+ const char * const name; -+ char * value; -+ int found; -+}; -+ -+static int -+get_var (const char * const name, const char * const value, void *statep) -+{ -+ struct get_var_state *state = (struct get_var_state *)statep; -+ -+ if (!grub_strcmp(state->name, name)) -+ { -+ state->found = 1; -+ state->value = grub_strdup(value); -+ if (!state->value) -+ grub_errno = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+grub_err_t -+grub_envblk_get (grub_envblk_t envblk, const char * const name, char ** const value) -+{ -+ struct get_var_state state = { -+ .name = name, -+ .value = NULL, -+ .found = 0, -+ }; -+ -+ grub_envblk_iterate(envblk, (void *)&state, get_var); -+ -+ *value = state.value; -+ -+ if (state.found && !state.value) -+ return grub_errno; -+ -+ return GRUB_ERR_NONE; -+} -+ - void - grub_envblk_iterate (grub_envblk_t envblk, - void *hook_data, -diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c -index bb198f02351..6a79ee67444 100644 ---- a/util/grub-set-bootflag.c -+++ b/util/grub-set-bootflag.c -@@ -25,6 +25,7 @@ - - #include /* For *_DIR_NAME defines */ - #include -+#include - #include /* For GRUB_ENVBLK_DEFCFG define */ - #include - #include -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 2e0691454b1..8dfc89a33b9 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -24,6 +24,11 @@ - #include - #include - -+#define GRUB_EFI_GRUB_VARIABLE_GUID \ -+ { 0x91376aff, 0xcba6, 0x42be, \ -+ { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \ -+ } -+ - /* Variables. */ - extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); - extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); -diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h -index c3e65592170..ab969af2461 100644 ---- a/include/grub/lib/envblk.h -+++ b/include/grub/lib/envblk.h -@@ -22,6 +22,8 @@ - #define GRUB_ENVBLK_SIGNATURE "# GRUB Environment Block\n" - #define GRUB_ENVBLK_DEFCFG "grubenv" - -+#define DEFAULT_ENVBLK_SIZE 1024 -+ - #ifndef ASM_FILE - - struct grub_envblk -@@ -33,6 +35,7 @@ typedef struct grub_envblk *grub_envblk_t; - - grub_envblk_t grub_envblk_open (char *buf, grub_size_t size); - int grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value); -+grub_err_t grub_envblk_get (grub_envblk_t envblk, const char * const name, char ** const value); - void grub_envblk_delete (grub_envblk_t envblk, const char *name); - void grub_envblk_iterate (grub_envblk_t envblk, - void *hook_data, diff --git a/SOURCES/0127-tpm-Don-t-propagate-TPM-measurement-errors-to-the-ve.patch b/SOURCES/0127-tpm-Don-t-propagate-TPM-measurement-errors-to-the-ve.patch new file mode 100644 index 0000000..d1c7b17 --- /dev/null +++ b/SOURCES/0127-tpm-Don-t-propagate-TPM-measurement-errors-to-the-ve.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Sat, 16 May 2020 11:33:18 +0200 +Subject: [PATCH] tpm: Don't propagate TPM measurement errors to the verifiers + layer + +Currently if the EFI firmware fails to do a TPM measurement for a file, +the error will be propagated to the verifiers framework and so opening +the file will not succeed. + +This mean that buggy firmwares will prevent the system to boot since the +loader won't be able to open any file. But failing to do TPM measurements +shouldn't be a fatal error and the system should still be able to boot. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/commands/tpm.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm.c +index 2052c36eab..e287d042e6 100644 +--- a/grub-core/commands/tpm.c ++++ b/grub-core/commands/tpm.c +@@ -42,7 +42,8 @@ grub_tpm_verify_init (grub_file_t io, + static grub_err_t + grub_tpm_verify_write (void *context, void *buf, grub_size_t size) + { +- return grub_tpm_measure (buf, size, GRUB_BINARY_PCR, context); ++ grub_tpm_measure (buf, size, GRUB_BINARY_PCR, context); ++ return GRUB_ERR_NONE; + } + + static grub_err_t +@@ -50,7 +51,6 @@ grub_tpm_verify_string (char *str, enum grub_verify_string_type type) + { + const char *prefix = NULL; + char *description; +- grub_err_t status; + + switch (type) + { +@@ -66,15 +66,15 @@ grub_tpm_verify_string (char *str, enum grub_verify_string_type type) + } + description = grub_malloc (grub_strlen (str) + grub_strlen (prefix) + 1); + if (!description) +- return grub_errno; ++ return GRUB_ERR_NONE; + grub_memcpy (description, prefix, grub_strlen (prefix)); + grub_memcpy (description + grub_strlen (prefix), str, + grub_strlen (str) + 1); +- status = +- grub_tpm_measure ((unsigned char *) str, grub_strlen (str), +- GRUB_STRING_PCR, description); ++ ++ grub_tpm_measure ((unsigned char *) str, grub_strlen (str), GRUB_STRING_PCR, ++ description); + grub_free (description); +- return status; ++ return GRUB_ERR_NONE; + } + + struct grub_file_verifier grub_tpm_verifier = { diff --git a/SOURCES/0128-Make-it-possible-to-subtract-conditions-from-debug.patch b/SOURCES/0128-Make-it-possible-to-subtract-conditions-from-debug.patch deleted file mode 100644 index fce51ea..0000000 --- a/SOURCES/0128-Make-it-possible-to-subtract-conditions-from-debug.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 17 Jan 2019 13:10:39 -0500 -Subject: [PATCH] Make it possible to subtract conditions from debug= - -This makes it so you can do set debug to "all,-scripting,-lexer" and get the -obvious outcome. Any negation present will take preference over that -conditional, so "all,-scripting,scripting" is the same thing as -"all,-scripting". - -Signed-off-by: Peter Jones ---- - grub-core/kern/misc.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index 9a2fae6398e..578bf51a5fc 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -164,12 +164,24 @@ int - grub_debug_enabled (const char * condition) - { - const char *debug; -+ char *negcond; -+ int negated = 0; - - debug = grub_env_get ("debug"); - if (!debug) - return 0; - -- if (grub_strword (debug, "all") || grub_strword (debug, condition)) -+ negcond = grub_zalloc (grub_strlen (condition) + 2); -+ if (negcond) -+ { -+ grub_strcpy (negcond, "-"); -+ grub_strcpy (negcond+1, condition); -+ negated = grub_strword (debug, negcond); -+ grub_free (negcond); -+ } -+ -+ if (!negated && -+ (grub_strword (debug, "all") || grub_strword (debug, condition))) - return 1; - - return 0; diff --git a/SOURCES/0128-x86-efi-Reduce-maximum-bounce-buffer-size-to-16-MiB.patch b/SOURCES/0128-x86-efi-Reduce-maximum-bounce-buffer-size-to-16-MiB.patch new file mode 100644 index 0000000..7c41e87 --- /dev/null +++ b/SOURCES/0128-x86-efi-Reduce-maximum-bounce-buffer-size-to-16-MiB.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 26 May 2020 16:59:28 +0200 +Subject: [PATCH] x86-efi: Reduce maximum bounce buffer size to 16 MiB + +The EFI linux loader allocates a bounce buffer to copy the initrd since in +some machines doing DMA on addresses above 4GB is not possible during EFI. + +But the verifiers framework also allocates a buffer to copy the initrd in +its grub_file_open() handler. It does this since the data to verify has to +be passed as a single chunk to modules that use the verifiers framework. + +If the initrd image size is big there may not be enough memory in the heap +to allocate two buffers of that size. This causes an allocation failure in +the verifiers framework and leads to the initrd not being read. + +To prevent these allocation failures, let's reduce the maximum size of the +bounce buffer used in the EFI loader. Since the data read can be copied to +the actual initrd address in multilple chunks. + +Resolves: rhbz#1838633 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/loader/i386/efi/linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 6bc18d5aef..15d40d6e35 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -144,7 +144,7 @@ grub_linuxefi_unload (void) + return GRUB_ERR_NONE; + } + +-#define BOUNCE_BUFFER_MAX 0x10000000ull ++#define BOUNCE_BUFFER_MAX 0x1000000ull + + static grub_ssize_t + read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) diff --git a/SOURCES/0129-Export-all-variables-from-the-initial-context-when-c.patch b/SOURCES/0129-Export-all-variables-from-the-initial-context-when-c.patch deleted file mode 100644 index bfe3165..0000000 --- a/SOURCES/0129-Export-all-variables-from-the-initial-context-when-c.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 22 Jan 2019 15:40:25 +0100 -Subject: [PATCH] Export all variables from the initial context when creating a - submenu - -When a submenu is created, only the exported variables are copied to the -new menu context. But we want the variables to be global, so export lets -export all variables to the new created submenu. - -Also, don't unset the default variable when a new submenu is created. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/normal/context.c | 2 +- - grub-core/normal/menu.c | 2 -- - 2 files changed, 1 insertion(+), 3 deletions(-) - -diff --git a/grub-core/normal/context.c b/grub-core/normal/context.c -index ee53d4a68e5..87edd254c44 100644 ---- a/grub-core/normal/context.c -+++ b/grub-core/normal/context.c -@@ -99,7 +99,7 @@ grub_env_new_context (int export_all) - grub_err_t - grub_env_context_open (void) - { -- return grub_env_new_context (0); -+ return grub_env_new_context (1); - } - - int grub_extractor_level = 0; -diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c -index ea714d27176..d4832f17699 100644 ---- a/grub-core/normal/menu.c -+++ b/grub-core/normal/menu.c -@@ -375,8 +375,6 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) - - if (ptr && ptr[0] && ptr[1]) - grub_env_set ("default", ptr + 1); -- else -- grub_env_unset ("default"); - - grub_script_execute_new_scope (entry->sourcecode, entry->argc, entry->args); - diff --git a/SOURCES/0129-http-Prepend-prefix-when-the-HTTP-path-is-relative-a.patch b/SOURCES/0129-http-Prepend-prefix-when-the-HTTP-path-is-relative-a.patch new file mode 100644 index 0000000..7fef93e --- /dev/null +++ b/SOURCES/0129-http-Prepend-prefix-when-the-HTTP-path-is-relative-a.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 2 Jun 2020 13:25:01 +0200 +Subject: [PATCH] http: Prepend prefix when the HTTP path is relative as done + in efi/http + +There are two different HTTP drivers that can be used when requesting an +HTTP resource: the efi/http that uses the EFI_HTTP_PROTOCOL and the http +that uses GRUB's HTTP and TCP/IP implementation. + +The efi/http driver appends a prefix that is defined in the variable +http_path, but the http driver doesn't. + +So using this driver and attempting to fetch a resource using a relative +path fails. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/net/http.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index b52b558d63..7f878b5615 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -501,13 +501,20 @@ http_open (struct grub_file *file, const char *filename) + { + grub_err_t err; + struct http_data *data; ++ const char *http_path; + + data = grub_zalloc (sizeof (*data)); + if (!data) + return grub_errno; + file->size = GRUB_FILE_SIZE_UNKNOWN; + +- data->filename = grub_strdup (filename); ++ /* If path is relative, prepend http_path */ ++ http_path = grub_env_get ("http_path"); ++ if (http_path && filename[0] != '/') ++ data->filename = grub_xasprintf ("%s/%s", http_path, filename); ++ else ++ data->filename = grub_strdup (filename); ++ + if (!data->filename) + { + grub_free (data); diff --git a/SOURCES/0130-Fix-a-missing-return-in-efi-export-env-and-efi-load-.patch b/SOURCES/0130-Fix-a-missing-return-in-efi-export-env-and-efi-load-.patch new file mode 100644 index 0000000..f3b10c1 --- /dev/null +++ b/SOURCES/0130-Fix-a-missing-return-in-efi-export-env-and-efi-load-.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 16 Jan 2019 13:21:46 -0500 +Subject: [PATCH] Fix a missing return in efi-export-env and efi-load-env + commands + +Somewhere along the way this got mis-merged to include a return without +a value. Fix it up. + +Signed-off-by: Peter Jones +--- + grub-core/commands/efi/env.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/commands/efi/env.c b/grub-core/commands/efi/env.c +index cbd13e03e8..977edb6b06 100644 +--- a/grub-core/commands/efi/env.c ++++ b/grub-core/commands/efi/env.c +@@ -149,6 +149,8 @@ grub_efi_load_env(grub_command_t cmd __attribute__ ((unused)), + + grub_envblk_iterate (envblk, NULL, set_var); + grub_free (envblk_s.buf); ++ ++ return GRUB_ERR_NONE; + } + + static grub_command_t export_cmd, loadenv_cmd; diff --git a/SOURCES/0130-grub.d-Split-out-boot-success-reset-from-menu-auto-h.patch b/SOURCES/0130-grub.d-Split-out-boot-success-reset-from-menu-auto-h.patch deleted file mode 100644 index 9788fd5..0000000 --- a/SOURCES/0130-grub.d-Split-out-boot-success-reset-from-menu-auto-h.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christian Glombek -Date: Tue, 2 Apr 2019 16:22:21 +0200 -Subject: [PATCH] grub.d: Split out boot success reset from menu auto hide - script - -Also rename fallback and menu auto hide script to be executed -before and after boot success reset script. -In menu auto hide script, rename last_boot_ok var to menu_hide_ok ---- - Makefile.util.def | 14 ++++++++---- - ...allback_counting.in => 08_fallback_counting.in} | 14 ++++++------ - util/grub.d/10_reset_boot_success.in | 25 ++++++++++++++++++++++ - .../{01_menu_auto_hide.in => 12_menu_auto_hide.in} | 23 +++++--------------- - 4 files changed, 48 insertions(+), 28 deletions(-) - rename util/grub.d/{01_fallback_counting.in => 08_fallback_counting.in} (65%) - create mode 100644 util/grub.d/10_reset_boot_success.in - rename util/grub.d/{01_menu_auto_hide.in => 12_menu_auto_hide.in} (58%) - -diff --git a/Makefile.util.def b/Makefile.util.def -index 2e5e05b25f1..11ab2d6fad1 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -459,14 +459,14 @@ script = { - }; - - script = { -- name = '01_fallback_counting'; -- common = util/grub.d/01_fallback_counting.in; -+ name = '08_fallback_counting'; -+ common = util/grub.d/08_fallback_counting.in; - installdir = grubconf; - }; - - script = { -- name = '01_menu_auto_hide'; -- common = util/grub.d/01_menu_auto_hide.in; -+ name = '12_menu_auto_hide'; -+ common = util/grub.d/12_menu_auto_hide.in; - installdir = grubconf; - }; - -@@ -518,6 +518,12 @@ script = { - condition = COND_HOST_LINUX; - }; - -+script = { -+ name = '10_reset_boot_success'; -+ common = util/grub.d/10_reset_boot_success.in; -+ installdir = grubconf; -+}; -+ - script = { - name = '10_xnu'; - common = util/grub.d/10_xnu.in; -diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/08_fallback_counting.in -similarity index 65% -rename from util/grub.d/01_fallback_counting.in -rename to util/grub.d/08_fallback_counting.in -index be0e770ea82..2e2c3ff7d31 100644 ---- a/util/grub.d/01_fallback_counting.in -+++ b/util/grub.d/08_fallback_counting.in -@@ -1,15 +1,17 @@ - #! /bin/sh -e -- --# Boot Counting -+# Fallback Countdown -+# -+# This snippet depends on 10_reset_boot_success and needs to be kept in sync. -+# - # The boot_counter env var can be used to count down boot attempts after an --# OSTree upgrade and choose the rollback deployment when 0 is reached. Both --# boot_counter and boot_success need to be (re-)set from userspace. -+# OSTree upgrade and choose the rollback deployment when 0 is reached. -+# Both boot_counter=X and boot_success=1 need to be set from userspace. - cat << EOF - insmod increment - # Check if boot_counter exists and boot_success=0 to activate this behaviour. - if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then -- # if countdown has ended, choose to boot rollback deployment (default=1 on -- # OSTree-based systems) -+ # if countdown has ended, choose to boot rollback deployment, -+ # i.e. default=1 on OSTree-based systems. - if [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then - set default=1 - set boot_counter=-1 -diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in -new file mode 100644 -index 00000000000..6c88d933dde ---- /dev/null -+++ b/util/grub.d/10_reset_boot_success.in -@@ -0,0 +1,25 @@ -+#! /bin/sh -e -+# Reset Boot Success -+# -+# The 08_fallback_counting and 12_menu_auto_hide snippets rely on this one -+# and need to be kept in sync. -+# -+# The boot_success var needs to be set to 1 from userspace to mark a boot successful. -+cat << EOF -+insmod increment -+# Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry -+if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then -+ set menu_hide_ok=1 -+else -+ set menu_hide_ok=0 -+fi -+# Reset boot_indeterminate after a successful boot, increment otherwise -+if [ "\${boot_success}" = "1" ] ; then -+ set boot_indeterminate=0 -+else -+ increment boot_indeterminate -+fi -+# Reset boot_success for current boot -+set boot_success=0 -+save_env boot_success boot_indeterminate -+EOF -diff --git a/util/grub.d/01_menu_auto_hide.in b/util/grub.d/12_menu_auto_hide.in -similarity index 58% -rename from util/grub.d/01_menu_auto_hide.in -rename to util/grub.d/12_menu_auto_hide.in -index ad175870a54..6a7c0fa0d43 100644 ---- a/util/grub.d/01_menu_auto_hide.in -+++ b/util/grub.d/12_menu_auto_hide.in -@@ -1,5 +1,8 @@ - #! /bin/sh -- -+# Menu Auto Hide -+# -+# This snippet depends on 10_reset_boot_success and needs to be kept in sync. -+# - # Disable / skip generating menu-auto-hide config parts on serial terminals - for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do - case "$x" in -@@ -10,29 +13,13 @@ for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do - done - - cat << EOF --if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then -- set last_boot_ok=1 --else -- set last_boot_ok=0 --fi -- --# Reset boot_indeterminate after a successful boot --if [ "\${boot_success}" = "1" ] ; then -- set boot_indeterminate=0 --# Avoid boot_indeterminate causing the menu to be hidden more then once --elif [ "\${boot_indeterminate}" = "1" ]; then -- set boot_indeterminate=2 --fi --set boot_success=0 --save_env boot_success boot_indeterminate -- - if [ x\$feature_timeout_style = xy ] ; then - if [ "\${menu_show_once}" ]; then - unset menu_show_once - save_env menu_show_once - set timeout_style=menu - set timeout=60 -- elif [ "\${menu_auto_hide}" -a "\${last_boot_ok}" = "1" ]; then -+ elif [ "\${menu_auto_hide}" -a "\${menu_hide_ok}" = "1" ]; then - set orig_timeout_style=\${timeout_style} - set orig_timeout=\${timeout} - if [ "\${fastboot}" = "1" ]; then diff --git a/SOURCES/0131-Fix-systemctl-kexec-exit-status-check.patch b/SOURCES/0131-Fix-systemctl-kexec-exit-status-check.patch deleted file mode 100644 index 74ecedc..0000000 --- a/SOURCES/0131-Fix-systemctl-kexec-exit-status-check.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 9 Apr 2019 12:30:38 +0200 -Subject: [PATCH] Fix systemctl kexec exit status check - -There's always an error printed even when the systemctl kexec command does -succeed. That's because systemctl executes it asynchronously, but the emu -loader seems to expect it to be synchronous and that should never return. - -Also, it's wrong to test if kexecute == 1 since we already know that's the -case or otherwise the function wouldn't had called grub_fatal() earlier. - -Finally, systemctl kexec failing shouldn't be a fatal error since the emu -loader fallbacks to executing the kexec command in case of a failure. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/loader/emu/linux.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c -index fda9e00d24c..5b85b225eed 100644 ---- a/grub-core/loader/emu/linux.c -+++ b/grub-core/loader/emu/linux.c -@@ -71,8 +71,10 @@ grub_linux_boot (void) - (kexecute==1) ? "do-or-die" : "just-in-case"); - rc = grub_util_exec (systemctl); - -- if (kexecute == 1) -- grub_fatal (N_("Error trying to perform 'systemctl kexec'")); -+ if (rc == GRUB_ERR_NONE) -+ return rc; -+ -+ grub_error (rc, N_("Error trying to perform 'systemctl kexec'")); - - /* need to check read-only root before resetting hard!? */ - grub_printf("Performing 'kexec -e'"); diff --git a/SOURCES/0131-efi-dhcp-fix-some-allocation-error-checking.patch b/SOURCES/0131-efi-dhcp-fix-some-allocation-error-checking.patch new file mode 100644 index 0000000..90e7a34 --- /dev/null +++ b/SOURCES/0131-efi-dhcp-fix-some-allocation-error-checking.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 17:11:06 -0400 +Subject: [PATCH] efi+dhcp: fix some allocation error checking. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/dhcp.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c +index dbef63d8c0..e5c79b748b 100644 +--- a/grub-core/net/efi/dhcp.c ++++ b/grub-core/net/efi/dhcp.c +@@ -80,7 +80,7 @@ grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packe + if (status != GRUB_EFI_BUFFER_TOO_SMALL) + return NULL; + +- option_list = grub_malloc (option_count * sizeof(*option_list)); ++ option_list = grub_calloc (option_count, sizeof(*option_list)); + if (!option_list) + return NULL; + +@@ -360,8 +360,11 @@ grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)), + + if (status == GRUB_EFI_BUFFER_TOO_SMALL && count) + { +- options = grub_malloc (count * sizeof(*options)); +- status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options); ++ options = grub_calloc (count, sizeof(*options)); ++ if (options) ++ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options); ++ else ++ status = GRUB_EFI_OUT_OF_RESOURCES; + } + + if (status != GRUB_EFI_SUCCESS) diff --git a/SOURCES/0132-Print-grub-emu-linux-loader-messages-as-debug.patch b/SOURCES/0132-Print-grub-emu-linux-loader-messages-as-debug.patch deleted file mode 100644 index a49ec44..0000000 --- a/SOURCES/0132-Print-grub-emu-linux-loader-messages-as-debug.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 9 Apr 2019 12:42:37 +0200 -Subject: [PATCH] Print grub-emu linux loader messages as debug - -They just polute the output and should better be debug messages instead. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/loader/emu/linux.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c -index 5b85b225eed..22ab6af1727 100644 ---- a/grub-core/loader/emu/linux.c -+++ b/grub-core/loader/emu/linux.c -@@ -50,7 +50,7 @@ grub_linux_boot (void) - initrd_param = grub_xasprintf("%s", ""); - } - -- grub_printf("%serforming 'kexec -l %s %s %s'\n", -+ grub_dprintf ("linux", "%serforming 'kexec -l %s %s %s'\n", - (kexecute) ? "P" : "Not p", - kernel_path, initrd_param, boot_cmdline); - -@@ -67,7 +67,7 @@ grub_linux_boot (void) - if (kexecute < 1) - grub_fatal (N_("Use '"PACKAGE"-emu --kexec' to force a system restart.")); - -- grub_printf("Performing 'systemctl kexec' (%s) ", -+ grub_dprintf ("linux", "Performing 'systemctl kexec' (%s) ", - (kexecute==1) ? "do-or-die" : "just-in-case"); - rc = grub_util_exec (systemctl); - diff --git a/SOURCES/0132-efi-http-fix-some-allocation-error-checking.patch b/SOURCES/0132-efi-http-fix-some-allocation-error-checking.patch new file mode 100644 index 0000000..149ada8 --- /dev/null +++ b/SOURCES/0132-efi-http-fix-some-allocation-error-checking.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 17:14:15 -0400 +Subject: [PATCH] efi+http: fix some allocation error checking. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/http.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +index fc8cb25ae0..26647a50fa 100644 +--- a/grub-core/net/efi/http.c ++++ b/grub-core/net/efi/http.c +@@ -412,8 +412,8 @@ grub_efihttp_open (struct grub_efi_net_device *dev, + int type) + { + grub_err_t err; +- grub_off_t size; +- char *buf; ++ grub_off_t size = 0; ++ char *buf = NULL; + char *file_name = NULL; + const char *http_path; + +@@ -441,8 +441,11 @@ grub_efihttp_open (struct grub_efi_net_device *dev, + return err; + } + +- buf = grub_malloc (size); +- efihttp_read (dev, buf, size); ++ if (size) ++ { ++ buf = grub_malloc (size); ++ efihttp_read (dev, buf, size); ++ } + + file->size = size; + file->data = buf; diff --git a/SOURCES/0133-Don-t-assume-that-boot-commands-will-only-return-on-.patch b/SOURCES/0133-Don-t-assume-that-boot-commands-will-only-return-on-.patch deleted file mode 100644 index 418a1ef..0000000 --- a/SOURCES/0133-Don-t-assume-that-boot-commands-will-only-return-on-.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 9 Apr 2019 13:12:40 +0200 -Subject: [PATCH] Don't assume that boot commands will only return on fail - -While it's true that for most loaders the boot command never returns, it -may be the case that it does. For example the GRUB emulator boot command -calls to systemctl kexec which in turn does an asynchonous call to kexec. - -So in this case GRUB will wrongly assume that the boot command fails and -print a "Failed to boot both default and fallback entries" even when the -kexec call later succeeds. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/normal/menu.c | 23 +++++++++++++---------- - 1 file changed, 13 insertions(+), 10 deletions(-) - -diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c -index d4832f17699..14ceb9bb060 100644 ---- a/grub-core/normal/menu.c -+++ b/grub-core/normal/menu.c -@@ -285,7 +285,7 @@ get_and_remove_first_entry_number (grub_menu_t menu, const char *name) - } - - /* Run a menu entry. */ --static void -+static grub_err_t - grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) - { - grub_err_t err = GRUB_ERR_NONE; -@@ -302,7 +302,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; -- return; -+ return grub_errno; - } - - errs_before = grub_err_printed_errors; -@@ -315,7 +315,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) - grub_env_context_open (); - menu = grub_zalloc (sizeof (*menu)); - if (! menu) -- return; -+ return grub_errno; - grub_env_set_menu (menu); - if (auto_boot) - grub_env_set ("timeout", "0"); -@@ -385,7 +385,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) - - if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) - /* Implicit execution of boot, only if something is loaded. */ -- grub_command_execute ("boot", 0, 0); -+ err = grub_command_execute ("boot", 0, 0); - - if (errs_before != grub_err_printed_errors) - grub_wait_after_message (); -@@ -408,6 +408,8 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) - else - grub_env_unset ("default"); - grub_env_unset ("timeout"); -+ -+ return err; - } - - /* Execute ENTRY from the menu MENU, falling back to entries specified -@@ -422,10 +424,13 @@ grub_menu_execute_with_fallback (grub_menu_t menu, - void *callback_data) - { - int fallback_entry; -+ grub_err_t err; - - callback->notify_booting (entry, callback_data); - -- grub_menu_execute_entry (entry, 1); -+ err = grub_menu_execute_entry (entry, 1); -+ if (err == GRUB_ERR_NONE) -+ return; - - /* Deal with fallback entries. */ - while ((fallback_entry = get_and_remove_first_entry_number (menu, "fallback")) -@@ -436,11 +441,9 @@ grub_menu_execute_with_fallback (grub_menu_t menu, - - entry = grub_menu_get_entry (menu, fallback_entry); - callback->notify_fallback (entry, callback_data); -- grub_menu_execute_entry (entry, 1); -- /* If the function call to execute the entry returns at all, then this is -- taken to indicate a boot failure. For menu entries that do something -- other than actually boot an operating system, this could assume -- incorrectly that something failed. */ -+ err = grub_menu_execute_entry (entry, 1); -+ if (err == GRUB_ERR_NONE) -+ return; - } - - if (!autobooted) diff --git a/SOURCES/0133-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch b/SOURCES/0133-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch new file mode 100644 index 0000000..6413eb6 --- /dev/null +++ b/SOURCES/0133-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 17:27:00 -0400 +Subject: [PATCH] efi/ip[46]_config.c: fix some potential allocation overflows + +In theory all of this data comes from the firmware stack and it should +be safe, but it's better to be paranoid. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/ip4_config.c | 25 ++++++++++++++++++------- + grub-core/net/efi/ip6_config.c | 13 ++++++++++--- + 2 files changed, 28 insertions(+), 10 deletions(-) + +diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c +index 313c818b18..9725e928f7 100644 +--- a/grub-core/net/efi/ip4_config.c ++++ b/grub-core/net/efi/ip4_config.c +@@ -4,15 +4,20 @@ + #include + #include + #include ++#include + + char * + grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address) + { + char *hw_addr, *p; +- int sz, s; +- int i; ++ grub_size_t sz, s, i; + +- sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1; ++ if (grub_mul (hw_address_size, sizeof ("XX:") - 1, &sz) || ++ grub_add (sz, 1, &sz)) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ return NULL; ++ } + + hw_addr = grub_malloc (sz); + if (!hw_addr) +@@ -20,7 +25,7 @@ grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_a + + p = hw_addr; + s = sz; +- for (i = 0; i < (int)hw_address_size; i++) ++ for (i = 0; i < hw_address_size; i++) + { + grub_snprintf (p, sz, "%02x:", hw_address[i]); + p += sizeof ("XX:") - 1; +@@ -238,14 +243,20 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev) + { + grub_efi_ip4_config2_interface_info_t *interface_info; + char **ret; +- int i, id; ++ int id; ++ grub_size_t i, nmemb; + + interface_info = efi_ip4_config_interface_info (dev->ip4_config); + if (!interface_info) + return NULL; + +- ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1)); ++ if (grub_add (interface_info->route_table_size, 1, &nmemb)) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ return NULL; ++ } + ++ ret = grub_calloc (nmemb, sizeof (*ret)); + if (!ret) + { + grub_free (interface_info); +@@ -253,7 +264,7 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev) + } + + id = 0; +- for (i = 0; i < (int)interface_info->route_table_size; i++) ++ for (i = 0; i < interface_info->route_table_size; i++) + { + char *subnet, *gateway, *mask; + grub_uint32_t u32_subnet, u32_gateway; +diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c +index 017c4d05bc..a46f6f9b68 100644 +--- a/grub-core/net/efi/ip6_config.c ++++ b/grub-core/net/efi/ip6_config.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + char * + grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address) +@@ -228,14 +229,20 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev) + { + grub_efi_ip6_config_interface_info_t *interface_info; + char **ret; +- int i, id; ++ int id; ++ grub_size_t i, nmemb; + + interface_info = efi_ip6_config_interface_info (dev->ip6_config); + if (!interface_info) + return NULL; + +- ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1)); ++ if (grub_add (interface_info->route_count, 1, &nmemb)) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ return NULL; ++ } + ++ ret = grub_calloc (nmemb, sizeof (*ret)); + if (!ret) + { + grub_free (interface_info); +@@ -243,7 +250,7 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev) + } + + id = 0; +- for (i = 0; i < (int)interface_info->route_count ; i++) ++ for (i = 0; i < interface_info->route_count ; i++) + { + char *gateway, *destination; + grub_uint64_t u64_gateway[2]; diff --git a/SOURCES/0134-Fix-undefined-references-for-fdt-when-building-with-.patch b/SOURCES/0134-Fix-undefined-references-for-fdt-when-building-with-.patch deleted file mode 100644 index 9065da8..0000000 --- a/SOURCES/0134-Fix-undefined-references-for-fdt-when-building-with-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Wed, 1 May 2019 00:36:19 +0200 -Subject: [PATCH] Fix undefined references for fdt when building with platform - emu - -The fdt module isn't build for this platform, so adding the declarations -with platform emu will lead to the following undefined reference errors: - -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x500): undefined reference to `grub_fdt_add_subnode' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x518): undefined reference to `grub_fdt_check_header' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x530): undefined reference to `grub_fdt_check_header_nosize' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x548): undefined reference to `grub_fdt_create_empty_tree' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x560): undefined reference to `grub_fdt_find_subnode' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x578): undefined reference to `grub_fdt_first_node' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x590): undefined reference to `grub_fdt_get_nodename' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x5a8): undefined reference to `grub_fdt_get_prop' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x5c0): undefined reference to `grub_fdt_next_node' -BUILDSTDERR: /usr/bin/ld: grub_emu_lite-symlist.o:(.data+0x5d8): undefined reference to `grub_fdt_set_prop' -BUILDSTDERR: collect2: error: ld returned 1 exit status -BUILDSTDERR: make[1]: *** [Makefile:27093: grub-emu-lite] Error 1 -BUILDSTDERR: make[1]: *** Waiting for unfinished jobs.... - -Signed-off-by: Javier Martinez Canillas ---- - include/grub/fdt.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/grub/fdt.h b/include/grub/fdt.h -index 22b7c5463fc..2041341fd68 100644 ---- a/include/grub/fdt.h -+++ b/include/grub/fdt.h -@@ -19,7 +19,7 @@ - #ifndef GRUB_FDT_HEADER - #define GRUB_FDT_HEADER 1 - --#if defined(__arm__) || defined(__aarch64__) -+#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__aarch64__)) - - #include - #include diff --git a/SOURCES/0134-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch b/SOURCES/0134-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch new file mode 100644 index 0000000..8e63d1d --- /dev/null +++ b/SOURCES/0134-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Fri, 24 Jul 2020 17:18:09 +0100 +Subject: [PATCH] efilinux: Fix integer overflows in grub_cmd_initrd + +These could be triggered by an extremely large number of arguments to +the initrd command on 32-bit architectures, or a crafted filesystem with +very large files on any architecture. + +Signed-off-by: Colin Watson +--- + grub-core/loader/i386/efi/linux.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 15d40d6e35..f992ceeef2 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -206,7 +208,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- files = grub_zalloc (argc * sizeof (files[0])); ++ files = grub_calloc (argc, sizeof (files[0])); + if (!files) + goto fail; + +@@ -216,7 +218,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + if (! files[i]) + goto fail; + nfiles++; +- size += ALIGN_UP (grub_file_size (files[i]), 4); ++ if (grub_add (size, ALIGN_UP (grub_file_size (files[i]), 4), &size)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ goto fail; ++ } + } + + initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); diff --git a/SOURCES/0135-Do-better-in-bootstrap.conf.patch b/SOURCES/0135-Do-better-in-bootstrap.conf.patch deleted file mode 100644 index ec9d8ec..0000000 --- a/SOURCES/0135-Do-better-in-bootstrap.conf.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 29 Jul 2019 10:58:52 -0400 -Subject: [PATCH] Do better in bootstrap.conf - ---- - bootstrap.conf | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/bootstrap.conf b/bootstrap.conf -index 186be9c48ce..9259526e891 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -16,7 +16,13 @@ - # along with this program. If not, see . - - --GNULIB_REVISION=d271f868a8df9bbec29049d01e056481b7a1a263 -+# GNULIB_REVISION=d271f868a8df9bbec29049d01e056481b7a1a263 -+if [[ -z "${GNULIB_REVISION}" ]] ;then -+ GNULIB_REVISION=fixes -+fi -+if [[ -z "${GNULIB_URL}" ]] ;then -+ GNULIB_URL=https://github.com/rhboot/gnulib.git -+fi - - # gnulib modules used by this package. - # mbswidth is used by gnulib-fix-width.diff's changes to argp rather than diff --git a/SOURCES/0135-linuxefi-fail-kernel-validation-without-shim-protoco.patch b/SOURCES/0135-linuxefi-fail-kernel-validation-without-shim-protoco.patch new file mode 100644 index 0000000..828fe16 --- /dev/null +++ b/SOURCES/0135-linuxefi-fail-kernel-validation-without-shim-protoco.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Wed, 22 Jul 2020 11:31:43 +0100 +Subject: [PATCH] linuxefi: fail kernel validation without shim protocol. + +If certificates that signed grub are installed into db, grub can be +booted directly. It will then boot any kernel without signature +validation. The booted kernel will think it was booted in secureboot +mode and will implement lockdown, yet it could have been tampered. + +This version of the patch skips calling verification, when booted +without secureboot. And is indented with gnu ident. + +CVE-2020-15705 + +Reported-by: Mathieu Trudel-Lapierre +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/arm64/linux.c | 13 +++++++++---- + grub-core/loader/efi/chainloader.c | 1 + + grub-core/loader/efi/linux.c | 1 + + grub-core/loader/i386/efi/linux.c | 17 +++++++++++------ + 4 files changed, 22 insertions(+), 10 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 70a0075ec5..47f8cf0d84 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -363,11 +364,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); + +- rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); +- if (rc < 0) ++ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { +- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); +- goto fail; ++ rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); ++ if (rc <= 0) ++ { ++ grub_error (GRUB_ERR_INVALID_COMMAND, ++ N_("%s has invalid signature"), argv[0]); ++ goto fail; ++ } + } + + pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index ac8dfd40c6..d41e8ea14a 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -1084,6 +1084,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + return 0; + } ++ // -1 fall-through to fail + + fail: + if (dev) +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index e8b9ecb17f..9260731c10 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -33,6 +33,7 @@ struct grub_efi_shim_lock + }; + typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; + ++// Returns 1 on success, -1 on error, 0 when not available + int + grub_linuxefi_secure_validate (void *data, grub_uint32_t size) + { +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index f992ceeef2..3cf0f9b330 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -101,7 +102,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) + + pages = BYTES_TO_PAGES(size); + grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", +- pages, (void *)max); ++ (unsigned long)pages, (void *)(unsigned long)max); + + prev_max = max; + addr = grub_efi_allocate_pages_real (max, pages, +@@ -307,12 +308,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- rc = grub_linuxefi_secure_validate (kernel, filelen); +- if (rc < 0) ++ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { +- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), +- argv[0]); +- goto fail; ++ rc = grub_linuxefi_secure_validate (kernel, filelen); ++ if (rc <= 0) ++ { ++ grub_error (GRUB_ERR_INVALID_COMMAND, ++ N_("%s has invalid signature"), argv[0]); ++ goto fail; ++ } + } + + lh = (struct linux_i386_kernel_header *)kernel; +@@ -386,6 +390,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); + grub_dprintf ("linux", "copying %lu bytes from %p to %p\n", ++ (unsigned long) + MIN((grub_size_t)0x202+setup_header_end_offset, + sizeof (*params)) - 0x1f1, + (grub_uint8_t *)kernel + 0x1f1, diff --git a/SOURCES/0136-Fix-const-char-pointers-in-grub-core-net-bootp.c.patch b/SOURCES/0136-Fix-const-char-pointers-in-grub-core-net-bootp.c.patch new file mode 100644 index 0000000..f20f5c7 --- /dev/null +++ b/SOURCES/0136-Fix-const-char-pointers-in-grub-core-net-bootp.c.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 20 Jul 2020 12:24:02 -0400 +Subject: [PATCH] Fix const char ** pointers in grub-core/net/bootp.c + +This will need to get folded back in the right place on the next rebase, +but it's before "Make grub_strtol() "end" pointers have safer const +qualifiers" currently, so for now I'm leaving it here instead of merging +it back with the original patch. + +Signed-off-by: Peter Jones +--- + grub-core/net/bootp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 8fb8918ae7..7baf3540c8 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -329,7 +329,7 @@ grub_net_configure_by_dhcp_ack (const char *name, + struct grub_net_network_level_interface *inter; + int mask = -1; + char server_ip[sizeof ("xxx.xxx.xxx.xxx")]; +- const grub_uint8_t *opt; ++ const char *opt; + grub_uint8_t opt_len, overload = 0; + const char *boot_file = 0, *server_name = 0; + grub_size_t boot_file_len, server_name_len; +@@ -505,7 +505,7 @@ grub_net_configure_by_dhcp_ack (const char *name, + if (opt && opt_len) + { + grub_env_set_net_property (name, "vendor_class_identifier", (const char *) opt, opt_len); +- if (opt && grub_strcmp (opt, "HTTPClient") == 0) ++ if (opt && grub_strcmp ((char *)opt, "HTTPClient") == 0) + { + char *proto, *ip, *pa; + diff --git a/SOURCES/0136-Use-git-to-apply-gnulib-patches.patch b/SOURCES/0136-Use-git-to-apply-gnulib-patches.patch deleted file mode 100644 index 7654648..0000000 --- a/SOURCES/0136-Use-git-to-apply-gnulib-patches.patch +++ /dev/null @@ -1,631 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 29 Jul 2019 11:21:27 -0400 -Subject: [PATCH] Use git to apply gnulib patches. - -Signed-off-by: Peter Jones ---- - bootstrap.conf | 6 - - conf/Makefile.extra-dist | 10 - - grub-core/lib/gnulib-patches/fix-base64.patch | 21 -- - grub-core/lib/gnulib-patches/fix-null-deref.patch | 13 -- - .../lib/gnulib-patches/fix-null-state-deref.patch | 12 -- - .../gnulib-patches/fix-regcomp-uninit-token.patch | 15 -- - .../gnulib-patches/fix-regexec-null-deref.patch | 12 -- - .../gnulib-patches/fix-sign-compare-errors.patch | 161 --------------- - .../lib/gnulib-patches/fix-uninit-structure.patch | 11 -- - .../lib/gnulib-patches/fix-unused-value.patch | 14 -- - grub-core/lib/gnulib-patches/fix-width.patch | 217 --------------------- - grub-core/lib/gnulib-patches/no-abort.patch | 26 --- - 12 files changed, 518 deletions(-) - delete mode 100644 grub-core/lib/gnulib-patches/fix-base64.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-null-deref.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-null-state-deref.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-uninit-structure.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-unused-value.patch - delete mode 100644 grub-core/lib/gnulib-patches/fix-width.patch - delete mode 100644 grub-core/lib/gnulib-patches/no-abort.patch - -diff --git a/bootstrap.conf b/bootstrap.conf -index 9259526e891..452f4d79b0d 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -85,12 +85,6 @@ cp -a INSTALL INSTALL.grub - - bootstrap_post_import_hook () { - set -e -- for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ -- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort \ -- fix-sign-compare-errors; do -- patch -d grub-core/lib/gnulib -p2 \ -- < "grub-core/lib/gnulib-patches/$patchname.patch" -- done - for patchname in \ - 0001-Support-POTFILES-shell \ - 0002-Handle-gettext_printf-shell-function \ -diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist -index ea58362b555..8ddf22e6c99 100644 ---- a/conf/Makefile.extra-dist -+++ b/conf/Makefile.extra-dist -@@ -30,16 +30,6 @@ EXTRA_DIST += grub-core/gensymlist.sh - EXTRA_DIST += grub-core/genemuinit.sh - EXTRA_DIST += grub-core/genemuinitheader.sh - --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch --EXTRA_DIST += grub-core/lib/gnulib-patches/no-abort.patch -- - EXTRA_DIST += grub-core/lib/libgcrypt - EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic - EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h') -diff --git a/grub-core/lib/gnulib-patches/fix-base64.patch b/grub-core/lib/gnulib-patches/fix-base64.patch -deleted file mode 100644 -index 985db127971..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-base64.patch -+++ /dev/null -@@ -1,21 +0,0 @@ --diff --git a/lib/base64.h b/lib/base64.h --index 9cd0183b8..185a2afa1 100644 ----- a/lib/base64.h --+++ b/lib/base64.h --@@ -21,8 +21,14 @@ -- /* Get size_t. */ -- # include -- ---/* Get bool. */ ---# include --+#ifndef GRUB_POSIX_BOOL_DEFINED --+typedef enum { false = 0, true = 1 } bool; --+#define GRUB_POSIX_BOOL_DEFINED 1 --+#endif --+ --+#ifndef _GL_ATTRIBUTE_CONST --+# define _GL_ATTRIBUTE_CONST /* empty */ --+#endif -- -- # ifdef __cplusplus -- extern "C" { -diff --git a/grub-core/lib/gnulib-patches/fix-null-deref.patch b/grub-core/lib/gnulib-patches/fix-null-deref.patch -deleted file mode 100644 -index 8fafa153a47..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-null-deref.patch -+++ /dev/null -@@ -1,13 +0,0 @@ --diff --git a/lib/argp-parse.c b/lib/argp-parse.c --index 6dec57310..900adad54 100644 ----- a/lib/argp-parse.c --+++ b/lib/argp-parse.c --@@ -940,7 +940,7 @@ weak_alias (__argp_parse, argp_parse) -- void * -- __argp_input (const struct argp *argp, const struct argp_state *state) -- { --- if (state) --+ if (state && state->pstate) -- { -- struct group *group; -- struct parser *parser = state->pstate; -diff --git a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch -deleted file mode 100644 -index 813ec09c8a1..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch -+++ /dev/null -@@ -1,12 +0,0 @@ ----- a/lib/argp-help.c 2020-10-28 14:32:19.189215988 +0000 --+++ b/lib/argp-help.c 2020-10-28 14:38:21.204673940 +0000 --@@ -145,7 +145,8 @@ -- if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) -- { -- __argp_failure (state, 0, 0, --- dgettext (state->root_argp->argp_domain, --+ dgettext (state == NULL ? NULL --+ : state->root_argp->argp_domain, -- "\ -- ARGP_HELP_FMT: %s value is less than or equal to %s"), -- "rmargin", up->name); -diff --git a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch -deleted file mode 100644 -index 02e06315dff..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch -+++ /dev/null -@@ -1,15 +0,0 @@ ----- a/lib/regcomp.c 2020-11-24 17:06:08.159223858 +0000 --+++ b/lib/regcomp.c 2020-11-24 17:06:15.630253923 +0000 --@@ -3808,11 +3808,7 @@ -- create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, -- re_token_type_t type) -- { --- re_token_t t; ---#if defined GCC_LINT || defined lint --- memset (&t, 0, sizeof t); ---#endif --- t.type = type; --+ re_token_t t = { .type = type }; -- return create_token_tree (dfa, left, right, &t); -- } -- -diff --git a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch -deleted file mode 100644 -index db6dac9c9e3..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch -+++ /dev/null -@@ -1,12 +0,0 @@ ----- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 --+++ b/lib/regexec.c 2020-11-05 10:55:09.621542984 +0000 --@@ -1692,6 +1692,9 @@ -- { -- Idx top = mctx->state_log_top; -- --+ if (mctx->state_log == NULL) --+ return REG_NOERROR; --+ -- if ((next_state_log_idx >= mctx->input.bufs_len -- && mctx->input.bufs_len < mctx->input.len) -- || (next_state_log_idx >= mctx->input.valid_len -diff --git a/grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch b/grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch -deleted file mode 100644 -index 479029c0565..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-sign-compare-errors.patch -+++ /dev/null -@@ -1,161 +0,0 @@ --diff --git a/lib/regcomp.c b/lib/regcomp.c --index cc85f35ac58..361079d82d6 100644 ----- a/lib/regcomp.c --+++ b/lib/regcomp.c --@@ -322,7 +322,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, -- *p++ = dfa->nodes[node].opr.c; -- memset (&state, '\0', sizeof (state)); -- if (__mbrtowc (&wc, (const char *) buf, p - buf, --- &state) == p - buf --+ &state) == (size_t)(p - buf) -- && (__wcrtomb ((char *) buf, __towlower (wc), &state) -- != (size_t) -1)) -- re_set_fastmap (fastmap, false, buf[0]); --@@ -3778,7 +3778,7 @@ fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) -- num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) -- ? -2 -- : num == -1 --- ? c - '0' --+ ? (Idx)(c - '0') -- : MIN (RE_DUP_MAX + 1, num * 10 + c - '0')); -- } -- return num; --diff --git a/lib/regex_internal.c b/lib/regex_internal.c --index 9004ce809eb..193a1e3d332 100644 ----- a/lib/regex_internal.c --+++ b/lib/regex_internal.c --@@ -233,7 +233,7 @@ build_wcs_buffer (re_string_t *pstr) -- /* Apply the translation if we need. */ -- if (__glibc_unlikely (pstr->trans != NULL)) -- { --- int i, ch; --+ unsigned int i, ch; -- -- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) -- { --@@ -376,7 +376,7 @@ build_wcs_upper_buffer (re_string_t *pstr) -- prev_st = pstr->cur_state; -- if (__glibc_unlikely (pstr->trans != NULL)) -- { --- int i, ch; --+ unsigned int i, ch; -- -- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) -- { --@@ -754,7 +754,7 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) -- memset (&cur_state, 0, sizeof (cur_state)); -- mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, -- &cur_state); --- if (raw + offset - p <= mbclen --+ if ((size_t)(raw + offset - p) <= mbclen -- && mbclen < (size_t) -2) -- { -- memset (&pstr->cur_state, '\0', --diff --git a/lib/regex_internal.h b/lib/regex_internal.h --index 5462419b787..e0f8292395d 100644 ----- a/lib/regex_internal.h --+++ b/lib/regex_internal.h --@@ -425,7 +425,7 @@ struct re_string_t -- unsigned char offsets_needed; -- unsigned char newline_anchor; -- unsigned char word_ops_used; --- int mb_cur_max; --+ unsigned int mb_cur_max; -- }; -- typedef struct re_string_t re_string_t; -- --@@ -702,7 +702,7 @@ struct re_dfa_t -- unsigned int is_utf8 : 1; -- unsigned int map_notascii : 1; -- unsigned int word_ops_used : 1; --- int mb_cur_max; --+ unsigned int mb_cur_max; -- bitset_t word_char; -- reg_syntax_t syntax; -- Idx *subexp_map; --diff --git a/lib/regexec.c b/lib/regexec.c --index 0a7a27b772e..b57d4f9141d 100644 ----- a/lib/regexec.c --+++ b/lib/regexec.c --@@ -443,7 +443,7 @@ re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length, -- { -- if (ret_len) -- { --- assert (pmatch[0].rm_so == start); --+ assert (pmatch[0].rm_so == (long)start); -- rval = pmatch[0].rm_eo - start; -- } -- else --@@ -877,11 +877,11 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, -- if (__glibc_unlikely (mctx.input.offsets_needed != 0)) -- { -- pmatch[reg_idx].rm_so = --- (pmatch[reg_idx].rm_so == mctx.input.valid_len --+ (pmatch[reg_idx].rm_so == (long)mctx.input.valid_len -- ? mctx.input.valid_raw_len -- : mctx.input.offsets[pmatch[reg_idx].rm_so]); -- pmatch[reg_idx].rm_eo = --- (pmatch[reg_idx].rm_eo == mctx.input.valid_len --+ (pmatch[reg_idx].rm_eo == (long)mctx.input.valid_len -- ? mctx.input.valid_raw_len -- : mctx.input.offsets[pmatch[reg_idx].rm_eo]); -- } --@@ -1418,11 +1418,11 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, -- } -- memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); -- --- for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) --+ for (idx = pmatch[0].rm_so; idx <= (long)pmatch[0].rm_eo ;) -- { -- update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); -- --- if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) --+ if (idx == (long)pmatch[0].rm_eo && cur_node == mctx->last_node) -- { -- Idx reg_idx; -- if (fs) --@@ -1519,7 +1519,7 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, -- if (reg_num < nmatch) -- { -- /* We are at the last node of this sub expression. */ --- if (pmatch[reg_num].rm_so < cur_idx) --+ if (pmatch[reg_num].rm_so < (long)cur_idx) -- { -- pmatch[reg_num].rm_eo = cur_idx; -- /* This is a non-empty match or we are not inside an optional --@@ -2938,7 +2938,7 @@ check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, -- mctx->state_log[str_idx] = cur_state; -- } -- --- for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) --+ for (null_cnt = 0; str_idx < last_str && null_cnt <= (long)mctx->max_mb_elem_len;) -- { -- re_node_set_empty (&next_nodes); -- if (mctx->state_log[str_idx + 1]) --@@ -3718,7 +3718,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, -- const re_string_t *input, Idx str_idx) -- { -- const re_token_t *node = dfa->nodes + node_idx; --- int char_len, elem_len; --+ unsigned int char_len, elem_len; -- Idx i; -- -- if (__glibc_unlikely (node->type == OP_UTF8_PERIOD)) --@@ -4066,7 +4066,7 @@ extend_buffers (re_match_context_t *mctx, int min_len) -- /* Double the lengths of the buffers, but allocate at least MIN_LEN. */ -- ret = re_string_realloc_buffers (pstr, -- MAX (min_len, --- MIN (pstr->len, pstr->bufs_len * 2))); --+ MIN ((long)pstr->len, pstr->bufs_len * 2))); -- if (__glibc_unlikely (ret != REG_NOERROR)) -- return ret; -- --@@ -4236,7 +4236,7 @@ match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, -- = (from == to ? -1 : 0); -- -- mctx->bkref_ents[mctx->nbkref_ents++].more = 0; --- if (mctx->max_mb_elem_len < to - from) --+ if (mctx->max_mb_elem_len < (long)(to - from)) -- mctx->max_mb_elem_len = to - from; -- return REG_NOERROR; -- } -diff --git a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch -deleted file mode 100644 -index 7b4d9f67af4..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch -+++ /dev/null -@@ -1,11 +0,0 @@ ----- a/lib/regcomp.c 2020-10-22 13:49:06.770168928 +0000 --+++ b/lib/regcomp.c 2020-10-22 13:50:37.026528298 +0000 --@@ -3662,7 +3662,7 @@ -- Idx alloc = 0; -- #endif /* not RE_ENABLE_I18N */ -- reg_errcode_t ret; --- re_token_t br_token; --+ re_token_t br_token = {0}; -- bin_tree_t *tree; -- -- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -diff --git a/grub-core/lib/gnulib-patches/fix-unused-value.patch b/grub-core/lib/gnulib-patches/fix-unused-value.patch -deleted file mode 100644 -index ba51f1bf223..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-unused-value.patch -+++ /dev/null -@@ -1,14 +0,0 @@ ----- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 --+++ b/lib/regexec.c 2020-10-21 14:32:07.961765604 +0000 --@@ -828,7 +828,11 @@ -- break; -- if (__glibc_unlikely (err != REG_NOMATCH)) -- goto free_return; --+#ifdef DEBUG --+ /* Only used for assertion below when DEBUG is set, otherwise --+ it will be over-written when we loop around. */ -- match_last = -1; --+#endif -- } -- else -- break; /* We found a match. */ -diff --git a/grub-core/lib/gnulib-patches/fix-width.patch b/grub-core/lib/gnulib-patches/fix-width.patch -deleted file mode 100644 -index 0a208ad08b5..00000000000 ---- a/grub-core/lib/gnulib-patches/fix-width.patch -+++ /dev/null -@@ -1,217 +0,0 @@ --diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c --index ba6a407f7..d0685b3d4 100644 ----- a/lib/argp-fmtstream.c --+++ b/lib/argp-fmtstream.c --@@ -28,9 +28,11 @@ -- #include -- #include -- #include --+#include -- -- #include "argp-fmtstream.h" -- #include "argp-namefrob.h" --+#include "mbswidth.h" -- -- #ifndef ARGP_FMTSTREAM_USE_LINEWRAP -- --@@ -115,6 +117,51 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free) -- #endif -- #endif -- --+ --+/* Return the pointer to the first character that doesn't fit in l columns. */ --+static inline const ptrdiff_t --+add_width (const char *ptr, const char *end, size_t l) --+{ --+ mbstate_t ps; --+ const char *ptr0 = ptr; --+ --+ memset (&ps, 0, sizeof (ps)); --+ --+ while (ptr < end) --+ { --+ wchar_t wc; --+ size_t s, k; --+ --+ s = mbrtowc (&wc, ptr, end - ptr, &ps); --+ if (s == (size_t) -1) --+ break; --+ if (s == (size_t) -2) --+ { --+ if (1 >= l) --+ break; --+ l--; --+ ptr++; --+ continue; --+ } --+ --+ if (wc == '\e' && ptr + 3 < end --+ && ptr[1] == '[' && (ptr[2] == '0' || ptr[2] == '1') --+ && ptr[3] == 'm') --+ { --+ ptr += 4; --+ continue; --+ } --+ --+ k = wcwidth (wc); --+ --+ if (k >= l) --+ break; --+ l -= k; --+ ptr += s; --+ } --+ return ptr - ptr0; --+} --+ -- /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the -- end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ -- void --@@ -168,13 +215,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs) -- if (!nl) -- { -- /* The buffer ends in a partial line. */ --+ size_t display_width = mbsnwidth (buf, fs->p - buf, --+ MBSW_STOP_AT_NUL); -- --- if (fs->point_col + len < fs->rmargin) --+ if (fs->point_col + display_width < fs->rmargin) -- { -- /* The remaining buffer text is a partial line and fits -- within the maximum line width. Advance point for the -- characters to be written and stop scanning. */ --- fs->point_col += len; --+ fs->point_col += display_width; -- break; -- } -- else --@@ -182,14 +231,18 @@ __argp_fmtstream_update (argp_fmtstream_t fs) -- the end of the buffer. */ -- nl = fs->p; -- } --- else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) --- { --- /* The buffer contains a full line that fits within the maximum --- line width. Reset point and scan the next line. */ --- fs->point_col = 0; --- buf = nl + 1; --- continue; --- } --+ else --+ { --+ size_t display_width = mbsnwidth (buf, nl - buf, MBSW_STOP_AT_NUL); --+ if (display_width < (ssize_t) fs->rmargin) --+ { --+ /* The buffer contains a full line that fits within the maximum --+ line width. Reset point and scan the next line. */ --+ fs->point_col = 0; --+ buf = nl + 1; --+ continue; --+ } --+ } -- -- /* This line is too long. */ -- r = fs->rmargin - 1; --@@ -225,7 +278,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) -- char *p, *nextline; -- int i; -- --- p = buf + (r + 1 - fs->point_col); --+ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); -- while (p >= buf && !isblank ((unsigned char) *p)) -- --p; -- nextline = p + 1; /* This will begin the next line. */ --@@ -243,7 +296,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) -- { -- /* A single word that is greater than the maximum line width. -- Oh well. Put it on an overlong line by itself. */ --- p = buf + (r + 1 - fs->point_col); --+ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); -- /* Find the end of the long word. */ -- if (p < nl) -- do --@@ -277,7 +330,8 @@ __argp_fmtstream_update (argp_fmtstream_t fs) -- && fs->p > nextline) -- { -- /* The margin needs more blanks than we removed. */ --- if (fs->end - fs->p > fs->wmargin + 1) --+ if (mbsnwidth (fs->p, fs->end - fs->p, MBSW_STOP_AT_NUL) --+ > fs->wmargin + 1) -- /* Make some space for them. */ -- { -- size_t mv = fs->p - nextline; --diff --git a/lib/argp-help.c b/lib/argp-help.c --index e5375a0f0..5d8f451ec 100644 ----- a/lib/argp-help.c --+++ b/lib/argp-help.c --@@ -51,6 +51,7 @@ -- #include "argp.h" -- #include "argp-fmtstream.h" -- #include "argp-namefrob.h" --+#include "mbswidth.h" -- -- #ifndef SIZE_MAX -- # define SIZE_MAX ((size_t) -1) --@@ -1432,7 +1433,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, -- -- /* Manually do line wrapping so that it (probably) won't get wrapped at -- any embedded spaces. */ --- space (stream, 1 + nl - cp); --+ space (stream, 1 + mbsnwidth (cp, nl - cp, MBSW_STOP_AT_NUL)); -- -- __argp_fmtstream_write (stream, cp, nl - cp); -- } --diff --git a/lib/mbswidth.c b/lib/mbswidth.c --index 408a15e34..b3fb7f83a 100644 ----- a/lib/mbswidth.c --+++ b/lib/mbswidth.c --@@ -38,6 +38,14 @@ -- /* Get INT_MAX. */ -- #include -- --+#ifndef FALLTHROUGH --+# if __GNUC__ < 7 --+# define FALLTHROUGH ((void) 0) --+# else --+# define FALLTHROUGH __attribute__ ((__fallthrough__)) --+# endif --+#endif --+ -- /* Returns the number of columns needed to represent the multibyte -- character string pointed to by STRING. If a non-printable character -- occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. --@@ -90,6 +98,10 @@ mbsnwidth (const char *string, size_t nbytes, int flags) -- p++; -- width++; -- break; --+ case '\0': --+ if (flags & MBSW_STOP_AT_NUL) --+ return width; --+ FALLTHROUGH; -- default: -- /* If we have a multibyte sequence, scan it up to its end. */ -- { --@@ -168,6 +180,9 @@ mbsnwidth (const char *string, size_t nbytes, int flags) -- { -- unsigned char c = (unsigned char) *p++; -- --+ if (c == 0 && (flags & MBSW_STOP_AT_NUL)) --+ return width; --+ -- if (isprint (c)) -- { -- if (width == INT_MAX) --diff --git a/lib/mbswidth.h b/lib/mbswidth.h --index 2b5c53c37..45a123e63 100644 ----- a/lib/mbswidth.h --+++ b/lib/mbswidth.h --@@ -45,6 +45,10 @@ extern "C" { -- control characters and 1 otherwise. */ -- #define MBSW_REJECT_UNPRINTABLE 2 -- --+/* If this bit is set \0 is treated as the end of string. --+ Otherwise it's treated as a normal one column width character. */ --+#define MBSW_STOP_AT_NUL 4 --+ -- -- /* Returns the number of screen columns needed for STRING. */ -- #define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ -diff --git a/grub-core/lib/gnulib-patches/no-abort.patch b/grub-core/lib/gnulib-patches/no-abort.patch -deleted file mode 100644 -index e469c4762eb..00000000000 ---- a/grub-core/lib/gnulib-patches/no-abort.patch -+++ /dev/null -@@ -1,26 +0,0 @@ --diff --git a/lib/regcomp.c b/lib/regcomp.c --index cc85f35ac..de45ebb5c 100644 ----- a/lib/regcomp.c --+++ b/lib/regcomp.c --@@ -528,9 +528,9 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, -- to this routine. If we are given anything else, or if other regex -- code generates an invalid error code, then the program has a bug. -- Dump core so we can fix it. */ --- abort (); --- --- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); --+ msg = gettext ("unknown regexp error"); --+ else --+ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); -- -- msg_size = strlen (msg) + 1; /* Includes the null. */ -- --@@ -1136,7 +1136,7 @@ optimize_utf8 (re_dfa_t *dfa) -- } -- break; -- default: --- abort (); --+ break; -- } -- -- if (mb_chars || has_period) diff --git a/SOURCES/0137-Fix-build-error-with-the-fdt-module-on-risc-v.patch b/SOURCES/0137-Fix-build-error-with-the-fdt-module-on-risc-v.patch deleted file mode 100644 index 35f2878..0000000 --- a/SOURCES/0137-Fix-build-error-with-the-fdt-module-on-risc-v.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 27 Aug 2019 10:34:24 +0200 -Subject: [PATCH] Fix build error with the fdt module on risc-v - -The risc-v architecture also uses Device Trees, but the symbols in the -fdt header aren't defined for this arch which lead to following error: - -BUILDSTDERR: ../../grub-core/loader/efi/fdt.c: In function 'grub_fdt_load': -BUILDSTDERR: ../../grub-core/loader/efi/fdt.c:48:39: warning: implicit declaration of function 'grub_fdt_get_totalsize' [-Wimplicit-function-declaration] -BUILDSTDERR: 48 | size = GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)); - -Signed-off-by: Javier Martinez Canillas ---- - include/grub/fdt.h | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/include/grub/fdt.h b/include/grub/fdt.h -index 2041341fd68..3514aa4a5b6 100644 ---- a/include/grub/fdt.h -+++ b/include/grub/fdt.h -@@ -19,7 +19,8 @@ - #ifndef GRUB_FDT_HEADER - #define GRUB_FDT_HEADER 1 - --#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__aarch64__)) -+#if !defined(GRUB_MACHINE_EMU) && \ -+ (defined(__arm__) || defined(__aarch64__) || defined(__riscv)) - - #include - #include -@@ -146,6 +147,7 @@ int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const ch - grub_fdt_set_prop ((fdt), (nodeoffset), "reg", reg_64, 16); \ - }) - --#endif /* defined(__arm__) || defined(__aarch64__) */ -+#endif /* !defined(GRUB_MACHINE_EMU) && \ -+ (defined(__arm__) || defined(__aarch64__) || defined(__riscv)) */ - - #endif /* ! GRUB_FDT_HEADER */ diff --git a/SOURCES/0137-Fix-const-char-pointers-in-grub-core-net-efi-ip4_con.patch b/SOURCES/0137-Fix-const-char-pointers-in-grub-core-net-efi-ip4_con.patch new file mode 100644 index 0000000..ea92110 --- /dev/null +++ b/SOURCES/0137-Fix-const-char-pointers-in-grub-core-net-efi-ip4_con.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 20 Jul 2020 12:24:02 -0400 +Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/ip4_config.c + +This will need to get folded back in the right place on the next rebase, +but it's before "Make grub_strtol() "end" pointers have safer const +qualifiers" currently, so for now I'm leaving it here instead of merging +it back with the original patch. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/ip4_config.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c +index 9725e928f7..cb880fc3e8 100644 +--- a/grub-core/net/efi/ip4_config.c ++++ b/grub-core/net/efi/ip4_config.c +@@ -61,7 +61,8 @@ int + grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest) + { + grub_uint32_t newip = 0; +- int i, ncolon = 0; ++ grub_size_t i; ++ int ncolon = 0; + const char *ptr = val; + + /* Check that is not an IPv6 address */ +@@ -78,7 +79,7 @@ grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *addres + for (i = 0; i < 4; i++) + { + unsigned long t; +- t = grub_strtoul (ptr, (char **) &ptr, 0); ++ t = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; diff --git a/SOURCES/0138-Fix-const-char-pointers-in-grub-core-net-efi-ip6_con.patch b/SOURCES/0138-Fix-const-char-pointers-in-grub-core-net-efi-ip6_con.patch new file mode 100644 index 0000000..915e6d7 --- /dev/null +++ b/SOURCES/0138-Fix-const-char-pointers-in-grub-core-net-efi-ip6_con.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 20 Jul 2020 12:24:02 -0400 +Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/ip6_config.c + +This will need to get folded back in the right place on the next rebase, +but it's before "Make grub_strtol() "end" pointers have safer const +qualifiers" currently, so for now I'm leaving it here instead of merging +it back with the original patch. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/ip6_config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c +index a46f6f9b68..1c5415d718 100644 +--- a/grub-core/net/efi/ip6_config.c ++++ b/grub-core/net/efi/ip6_config.c +@@ -85,7 +85,7 @@ grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *addres + ptr++; + continue; + } +- t = grub_strtoul (ptr, (char **) &ptr, 16); ++ t = grub_strtoul (ptr, &ptr, 16); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; diff --git a/SOURCES/0138-grub-set-bootflag-Update-comment-about-running-as-ro.patch b/SOURCES/0138-grub-set-bootflag-Update-comment-about-running-as-ro.patch deleted file mode 100644 index cd4ef77..0000000 --- a/SOURCES/0138-grub-set-bootflag-Update-comment-about-running-as-ro.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Wed, 13 Nov 2019 12:15:43 +0100 -Subject: [PATCH] grub-set-bootflag: Update comment about running as root - through pkexec - -We have stopped using pkexec for grub-set-bootflag, instead it is now -installed suid root, update the comment accordingly. - -Signed-off-by: Hans de Goede ---- - util/grub-set-bootflag.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c -index 6a79ee67444..65d74ce010f 100644 ---- a/util/grub-set-bootflag.c -+++ b/util/grub-set-bootflag.c -@@ -18,7 +18,7 @@ - */ - - /* -- * NOTE this gets run by users as root (through pkexec), so this does not -+ * NOTE this gets run by users as root (its suid root), so this does not - * use any grub library / util functions to allow for easy auditing. - * The grub headers are only included to get certain defines. - */ diff --git a/SOURCES/0139-Fix-const-char-pointers-in-grub-core-net-efi-net.c.patch b/SOURCES/0139-Fix-const-char-pointers-in-grub-core-net-efi-net.c.patch new file mode 100644 index 0000000..fbba65a --- /dev/null +++ b/SOURCES/0139-Fix-const-char-pointers-in-grub-core-net-efi-net.c.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 20 Jul 2020 12:24:02 -0400 +Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/net.c + +This will need to get folded back in the right place on the next rebase, +but it's before "Make grub_strtol() "end" pointers have safer const +qualifiers" currently, so for now I'm leaving it here instead of merging +it back with the original patch. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/net.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +index a3f0535d43..78e5442fc5 100644 +--- a/grub-core/net/efi/net.c ++++ b/grub-core/net/efi/net.c +@@ -729,7 +729,7 @@ grub_efi_net_parse_address (const char *address, + { + grub_uint32_t subnet_mask_size; + +- subnet_mask_size = grub_strtoul (rest + 1, (char **) &rest, 0); ++ subnet_mask_size = grub_strtoul (rest + 1, &rest, 0); + + if (!grub_errno && subnet_mask_size <= 32 && *rest == 0) + { +@@ -758,7 +758,7 @@ grub_efi_net_parse_address (const char *address, + { + grub_efi_uint8_t prefix_length; + +- prefix_length = grub_strtoul (rest + 1, (char **) &rest, 0); ++ prefix_length = grub_strtoul (rest + 1, &rest, 0); + if (!grub_errno && prefix_length <= 128 && *rest == 0) + { + ip6->prefix_length = prefix_length; diff --git a/SOURCES/0139-grub-set-bootflag-Write-new-env-to-tmpfile-and-then-.patch b/SOURCES/0139-grub-set-bootflag-Write-new-env-to-tmpfile-and-then-.patch deleted file mode 100644 index 122bf68..0000000 --- a/SOURCES/0139-grub-set-bootflag-Write-new-env-to-tmpfile-and-then-.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Wed, 13 Nov 2019 13:02:01 +0100 -Subject: [PATCH] grub-set-bootflag: Write new env to tmpfile and then rename - -Make the grubenv writing code in grub-set-bootflag more robust by -writing the modified grubenv to a tmpfile first and then renaming the -tmpfile over the old grubenv (following symlinks). - -Signed-off-by: Hans de Goede ---- - util/grub-set-bootflag.c | 87 +++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 78 insertions(+), 9 deletions(-) - -diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c -index 65d74ce010f..d1c5e28862b 100644 ---- a/util/grub-set-bootflag.c -+++ b/util/grub-set-bootflag.c -@@ -28,7 +28,9 @@ - #include - #include /* For GRUB_ENVBLK_DEFCFG define */ - #include -+#include - #include -+#include - #include - #include - -@@ -54,8 +56,10 @@ int main(int argc, char *argv[]) - { - /* NOTE buf must be at least the longest bootflag length + 4 bytes */ - char env[GRUBENV_SIZE + 1], buf[64], *s; -+ /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */ -+ char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1]; - const char *bootflag; -- int i, len, ret; -+ int i, fd, len, ret; - FILE *f; - - if (argc != 2) -@@ -77,7 +81,32 @@ int main(int argc, char *argv[]) - bootflag = bootflags[i]; - len = strlen (bootflag); - -- f = fopen (GRUBENV, "r"); -+ /* -+ * Really become root. setuid avoids an user killing us, possibly leaking -+ * the tmpfile. setgid avoids the new grubenv's gid being that of the user. -+ */ -+ ret = setuid(0); -+ if (ret) -+ { -+ perror ("Error setuid(0) failed"); -+ return 1; -+ } -+ -+ ret = setgid(0); -+ if (ret) -+ { -+ perror ("Error setgid(0) failed"); -+ return 1; -+ } -+ -+ /* Canonicalize GRUBENV filename, resolving symlinks, etc. */ -+ if (!realpath(GRUBENV, env_filename)) -+ { -+ perror ("Error canonicalizing " GRUBENV " filename"); -+ return 1; -+ } -+ -+ f = fopen (env_filename, "r"); - if (!f) - { - perror ("Error opening " GRUBENV " for reading"); -@@ -132,30 +161,70 @@ int main(int argc, char *argv[]) - snprintf(buf, sizeof(buf), "%s=1\n", bootflag); - memcpy(s, buf, len + 3); - -- /* "r+", don't truncate so that the diskspace stays reserved */ -- f = fopen (GRUBENV, "r+"); -+ -+ /* -+ * Create a tempfile for writing the new env. Use the canonicalized filename -+ * for the template so that the tmpfile is in the same dir / on same fs. -+ */ -+ snprintf(tmp_filename, sizeof(tmp_filename), "%sXXXXXX", env_filename); -+ fd = mkstemp(tmp_filename); -+ if (fd == -1) -+ { -+ perror ("Creating tmpfile failed"); -+ return 1; -+ } -+ -+ f = fdopen (fd, "w"); - if (!f) - { -- perror ("Error opening " GRUBENV " for writing"); -+ perror ("Error fdopen of tmpfile failed"); -+ unlink(tmp_filename); - return 1; - } - - ret = fwrite (env, 1, GRUBENV_SIZE, f); - if (ret != GRUBENV_SIZE) - { -- perror ("Error writing to " GRUBENV); -+ perror ("Error writing tmpfile"); -+ unlink(tmp_filename); - return 1; - } - - ret = fflush (f); - if (ret) - { -- perror ("Error flushing " GRUBENV); -+ perror ("Error flushing tmpfile"); -+ unlink(tmp_filename); - return 1; - } - -- fsync (fileno (f)); -- fclose (f); -+ ret = fsync (fileno (f)); -+ if (ret) -+ { -+ perror ("Error syncing tmpfile"); -+ unlink(tmp_filename); -+ return 1; -+ } -+ -+ ret = fclose (f); -+ if (ret) -+ { -+ perror ("Error closing tmpfile"); -+ unlink(tmp_filename); -+ return 1; -+ } -+ -+ /* -+ * And finally rename the tmpfile with the new env over the old env, the -+ * linux kernel guarantees that this is atomic (from a syscall pov). -+ */ -+ ret = rename(tmp_filename, env_filename); -+ if (ret) -+ { -+ perror ("Error renaming tmpfile to " GRUBENV " failed"); -+ unlink(tmp_filename); -+ return 1; -+ } - - return 0; - } diff --git a/SOURCES/0140-Fix-const-char-pointers-in-grub-core-net-efi-pxe.c.patch b/SOURCES/0140-Fix-const-char-pointers-in-grub-core-net-efi-pxe.c.patch new file mode 100644 index 0000000..9b9acfe --- /dev/null +++ b/SOURCES/0140-Fix-const-char-pointers-in-grub-core-net-efi-pxe.c.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 20 Jul 2020 12:24:02 -0400 +Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/pxe.c + +This will need to get folded back in the right place on the next rebase, +but it's before "Make grub_strtol() "end" pointers have safer const +qualifiers" currently, so for now I'm leaving it here instead of merging +it back with the original patch. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/pxe.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/efi/pxe.c b/grub-core/net/efi/pxe.c +index 531949cba5..73e2bb01c1 100644 +--- a/grub-core/net/efi/pxe.c ++++ b/grub-core/net/efi/pxe.c +@@ -187,7 +187,7 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) + ptr++; + continue; + } +- t = grub_strtoul (ptr, (char **) &ptr, 16); ++ t = grub_strtoul (ptr, &ptr, 16); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; +@@ -225,7 +225,7 @@ pxe_open (struct grub_efi_net_device *dev, + int type __attribute__((unused))) + { + int i; +- char *p; ++ const char *p; + grub_efi_status_t status; + grub_efi_pxe_ip_address_t server_ip; + grub_efi_uint64_t file_size = 0; +@@ -313,7 +313,7 @@ pxe_read (struct grub_efi_net_device *dev, + grub_size_t len) + { + int i; +- char *p; ++ const char *p; + grub_efi_status_t status; + grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; + grub_efi_uint64_t bufsz = len; diff --git a/SOURCES/0140-grub.d-Fix-boot_indeterminate-getting-set-on-boot_su.patch b/SOURCES/0140-grub.d-Fix-boot_indeterminate-getting-set-on-boot_su.patch deleted file mode 100644 index 54b73e6..0000000 --- a/SOURCES/0140-grub.d-Fix-boot_indeterminate-getting-set-on-boot_su.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Tue, 26 Nov 2019 09:51:41 +0100 -Subject: [PATCH] grub.d: Fix boot_indeterminate getting set on boot_success=0 - boot - -The "grub.d: Split out boot success reset from menu auto hide script" -not only moved the code to clear boot_success and boot_indeterminate -but for some reason also mixed in some broken changes to the -boot_indeterminate handling. - -The boot_indeterminate var is meant to suppress the boot menu after -a reboot from either a selinux-relabel or offline-updates. These -2 special boot scenarios do not set boot_success since there is no -successfull interaction with the user. Instead they increment -boot_indeterminate, and if it is 1 and only when it is 1, so the -first reboot after a "special" boot we suppress the menu. - -To ensure that we do show the menu if we somehow get stuck in a -"special" boot loop where we do special-boots without them -incrementing boot_indeterminate, the code before the -"grub.d: Split out boot success reset from menu auto hide script" -commit would increment boot_indeterminate once when it is 1, so that -even if the "special" boot reboot-loop immediately we would show the -menu on the next boot. - -That commit broke this however, because it not only moves the code, -it also changes it from only "incrementing" boot_indeterminate once to -always incrementing it, except when boot_success == 1 (and we reset it). - -This broken behavior causes the following problem: - -1. Boot a broken kernel, system hangs, power-cycle -2. boot_success now != 1, so we increment boot_indeterminate from 0 - (unset!) to 1. User either simply tries again, or makes some changes - but the end-result still is a system hang, power-cycle -3. Now boot_indeterminate==1 so we do not show the menu even though the - previous boot failed -> BAD - -This commit fixes this by restoring the behavior of setting -boot_indeterminate to 2 when it was 1 before. - -Fixes: "grub.d: Split out boot success reset from menu auto hide script" -Signed-off-by: Hans de Goede ---- - util/grub.d/10_reset_boot_success.in | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in -index 6c88d933dde..737e1ae5b68 100644 ---- a/util/grub.d/10_reset_boot_success.in -+++ b/util/grub.d/10_reset_boot_success.in -@@ -6,18 +6,18 @@ - # - # The boot_success var needs to be set to 1 from userspace to mark a boot successful. - cat << EOF --insmod increment - # Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry - if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then - set menu_hide_ok=1 - else - set menu_hide_ok=0 - fi --# Reset boot_indeterminate after a successful boot, increment otherwise -+# Reset boot_indeterminate after a successful boot - if [ "\${boot_success}" = "1" ] ; then - set boot_indeterminate=0 --else -- increment boot_indeterminate -+# Avoid boot_indeterminate causing the menu to be hidden more then once -+elif [ "\${boot_indeterminate}" = "1" ]; then -+ set boot_indeterminate=2 - fi - # Reset boot_success for current boot - set boot_success=0 diff --git a/SOURCES/0141-Add-systemd-integration-scripts-to-make-systemctl-re.patch b/SOURCES/0141-Add-systemd-integration-scripts-to-make-systemctl-re.patch new file mode 100644 index 0000000..8cf45c3 --- /dev/null +++ b/SOURCES/0141-Add-systemd-integration-scripts-to-make-systemctl-re.patch @@ -0,0 +1,190 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 22 Jul 2020 14:03:42 +0200 +Subject: [PATCH] Add systemd integration scripts to make "systemctl reboot + --boot-loader-menu=xxx" work with grub + +This commit adds a number of scripts / config files to make +"systemctl reboot --boot-loader-menu=xxx" work with grub: + +1. /lib/systemd/system/systemd-logind.service.d/10-grub.conf +This sets SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU in the env. for logind, +indicating that the boot-loader which is used supports this feature, see: +https://github.com/systemd/systemd/blob/master/docs/ENVIRONMENT.md + +2. /lib/systemd/system/grub-systemd-integration.service + /lib/systemd/system/reboot.target.wants/grub-systemd-integration.service -> + ../grub-systemd-integration.service + /usr/libexec/grub/grub-systemd-integration.sh + +The symlink in the .wants dir causes the added service file to be started +by systemd just before rebooting the system. +If /run/systemd/reboot-to-boot-loader-menu exist then the service will run +the grub-systemd-integration.sh script. +This script sets the new menu_show_once_timeout grubenv variable to the +requested timeout in seconds. + +3. /etc/grub.d/14_menu_show_once + +This new grub-mkconfig snippet adds the necessary code to the generated +grub.conf to honor the new menu_show_once_timeout variable, and to +automatically clear it after consuming it. + +Note the service and libexec script use grub-systemd-integration as name +because in the future they may be used to add further integration with +systemctl reboot --foo options, e.g. support for --boot-loader-entry=NAME. + +A few notes about upstreaming this patch from the rhboot grub2 fork: +1. I have deliberately put the grub.conf bits for this in a new / separate + grub-mkconfig snippet generator for easy upstreaming +2. Even though the commit message mentions the .wants symlink for the .service + I have been unable to come up with a clean way to do this at "make install" + time, this should be fixed before upstreaming. + +Downstream notes: +1. Since make install does not add the .wants symlink, this needs to be done + in grub2.spec %install +2. This is keeping support for the "old" Fedora specific menu_show_once env + variable, which has a hardcoded timeout of 60 sec in 12_menu_auto_hide in + place for now. This can be dropped (eventually) in a follow-up patch once + GNOME has been converted to use the systemd dbus API equivalent of + "systemctl reboot --boot-loader-menu=xxx". + +Signed-off-by: Hans de Goede +--- + Makefile.util.def | 27 ++++++++++++++++++++++++ + conf/Makefile.common | 6 ++++++ + util/grub.d/14_menu_show_once.in | 13 ++++++++++++ + util/systemd/10-grub-logind-service.conf.in | 2 ++ + util/systemd/grub-systemd-integration.service.in | 8 +++++++ + util/systemd/systemd-integration.sh.in | 6 ++++++ + 6 files changed, 62 insertions(+) + create mode 100755 util/grub.d/14_menu_show_once.in + create mode 100644 util/systemd/10-grub-logind-service.conf.in + create mode 100644 util/systemd/grub-systemd-integration.service.in + create mode 100644 util/systemd/systemd-integration.sh.in + +diff --git a/Makefile.util.def b/Makefile.util.def +index b4ce5383b7..6366442129 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -470,6 +470,12 @@ script = { + installdir = grubconf; + }; + ++script = { ++ name = '14_menu_show_once'; ++ common = util/grub.d/14_menu_show_once.in; ++ installdir = grubconf; ++}; ++ + script = { + name = '01_users'; + common = util/grub.d/01_users.in; +@@ -569,6 +575,27 @@ script = { + installdir = grubconf; + }; + ++script = { ++ name = 'grub-systemd-integration.service'; ++ common = util/systemd/grub-systemd-integration.service.in; ++ installdir = systemdunit; ++ condition = COND_HOST_LINUX; ++}; ++ ++script = { ++ name = 'systemd-integration.sh'; ++ common = util/systemd/systemd-integration.sh.in; ++ installdir = grublibexec; ++ condition = COND_HOST_LINUX; ++}; ++ ++script = { ++ name = '10-grub-logind-service.conf'; ++ common = util/systemd/10-grub-logind-service.conf.in; ++ installdir = systemd_logind_service_d; ++ condition = COND_HOST_LINUX; ++}; ++ + program = { + mansection = 1; + name = grub-mkrescue; +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 0647c53b91..9fe5863b2d 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -63,8 +63,11 @@ CCASFLAGS_LIBRARY = $(UTILS_CCASFLAGS) + # Other variables + + grubconfdir = $(sysconfdir)/grub.d ++grublibexecdir = $(libexecdir)/$(grubdirname) + platformdir = $(pkglibdir)/$(target_cpu)-$(platform) + starfielddir = $(pkgdatadir)/themes/starfield ++systemdunitdir = ${prefix}/lib/systemd/system ++systemd_logind_service_ddir = $(systemdunitdir)/systemd-logind.service.d + + CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Werror=trampolines -fno-trampolines + CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib +@@ -121,6 +124,9 @@ noinst_LIBRARIES = + dist_noinst_DATA = + platform_SCRIPTS = + platform_PROGRAMS = ++grublibexec_SCRIPTS = ++systemdunit_SCRIPTS = ++systemd_logind_service_d_SCRIPTS = + + TESTS = + EXTRA_DIST = +diff --git a/util/grub.d/14_menu_show_once.in b/util/grub.d/14_menu_show_once.in +new file mode 100755 +index 0000000000..1cd7f36142 +--- /dev/null ++++ b/util/grub.d/14_menu_show_once.in +@@ -0,0 +1,13 @@ ++#! /bin/sh ++# Force the menu to be shown once, with a timeout of ${menu_show_once_timeout} ++# if requested by ${menu_show_once_timeout} being set in the env. ++cat << EOF ++if [ x\$feature_timeout_style = xy ]; then ++ if [ "\${menu_show_once_timeout}" ]; then ++ set timeout_style=menu ++ set timeout="\${menu_show_once_timeout}" ++ unset menu_show_once_timeout ++ save_env menu_show_once_timeout ++ fi ++fi ++EOF +diff --git a/util/systemd/10-grub-logind-service.conf.in b/util/systemd/10-grub-logind-service.conf.in +new file mode 100644 +index 0000000000..f2d4ac0073 +--- /dev/null ++++ b/util/systemd/10-grub-logind-service.conf.in +@@ -0,0 +1,2 @@ ++[Service] ++Environment=SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU=true +diff --git a/util/systemd/grub-systemd-integration.service.in b/util/systemd/grub-systemd-integration.service.in +new file mode 100644 +index 0000000000..c81fb594ce +--- /dev/null ++++ b/util/systemd/grub-systemd-integration.service.in +@@ -0,0 +1,8 @@ ++[Unit] ++Description=Grub2 systemctl reboot --boot-loader-menu=... support ++Before=umount.target systemd-reboot.service ++DefaultDependencies=no ++ConditionPathExists=/run/systemd/reboot-to-boot-loader-menu ++ ++[Service] ++ExecStart=@libexecdir@/@grubdirname@/systemd-integration.sh +diff --git a/util/systemd/systemd-integration.sh.in b/util/systemd/systemd-integration.sh.in +new file mode 100644 +index 0000000000..dc1218597b +--- /dev/null ++++ b/util/systemd/systemd-integration.sh.in +@@ -0,0 +1,6 @@ ++#!/bin/sh ++ ++TIMEOUT_USEC=$(cat /run/systemd/reboot-to-boot-loader-menu) ++TIMEOUT=$(((TIMEOUT_USEC + 500000) / 1000000)) ++ ++@grub_editenv@ - set menu_show_once_timeout=$TIMEOUT diff --git a/SOURCES/0141-Also-define-GRUB_EFI_MAX_ALLOCATION_ADDRESS-for-RISC.patch b/SOURCES/0141-Also-define-GRUB_EFI_MAX_ALLOCATION_ADDRESS-for-RISC.patch deleted file mode 100644 index b694ec9..0000000 --- a/SOURCES/0141-Also-define-GRUB_EFI_MAX_ALLOCATION_ADDRESS-for-RISC.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Abdurachmanov -Date: Thu, 16 Jan 2020 13:10:10 +0100 -Subject: [PATCH] Also define GRUB_EFI_MAX_ALLOCATION_ADDRESS for RISC-V - -The commit "Try to pick better locations for kernel and initrd" missed to -define this macro for the RISC-V (riscv64) architecture, so add it there. - -Signed-off-by: David Abdurachmanov ---- - include/grub/riscv64/efi/memory.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/grub/riscv64/efi/memory.h b/include/grub/riscv64/efi/memory.h -index c6cb3241714..acb61dca44b 100644 ---- a/include/grub/riscv64/efi/memory.h -+++ b/include/grub/riscv64/efi/memory.h -@@ -2,5 +2,6 @@ - #include - - #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS - - #endif /* ! GRUB_MEMORY_CPU_HEADER */ diff --git a/SOURCES/0142-chainloader-Define-machine-types-for-RISC-V.patch b/SOURCES/0142-chainloader-Define-machine-types-for-RISC-V.patch deleted file mode 100644 index 480db52..0000000 --- a/SOURCES/0142-chainloader-Define-machine-types-for-RISC-V.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Abdurachmanov -Date: Sat, 9 Nov 2019 18:06:32 +0000 -Subject: [PATCH] chainloader: Define machine types for RISC-V - -The commit "Add secureboot support on efi chainloader" didn't add machine -types for RISC-V, so this patch adds them. - -Note, that grub-core/loader/riscv/linux.c is skipped because Linux is not -supported yet. This patch might need a new revision once that's the case. - -Signed-off-by: David Abdurachmanov ---- - grub-core/loader/efi/chainloader.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 47f5aa14817..ac8dfd40c61 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -333,6 +333,10 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) = - GRUB_PE32_MACHINE_I386; - #elif defined(__ia64__) - GRUB_PE32_MACHINE_IA64; -+#elif defined(__riscv) && (__riscv_xlen == 32) -+ GRUB_PE32_MACHINE_RISCV32; -+#elif defined(__riscv) && (__riscv_xlen == 64) -+ GRUB_PE32_MACHINE_RISCV64; - #else - #error this architecture is not supported by grub2 - #endif diff --git a/SOURCES/0142-systemd-integration.sh-Also-set-old-menu_show_once-g.patch b/SOURCES/0142-systemd-integration.sh-Also-set-old-menu_show_once-g.patch new file mode 100644 index 0000000..a16ed68 --- /dev/null +++ b/SOURCES/0142-systemd-integration.sh-Also-set-old-menu_show_once-g.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 23 Jul 2020 09:27:36 +0200 +Subject: [PATCH] systemd-integration.sh: Also set old menu_show_once grubenv + var + +Downstream RH / Fedora patch for compatibility with old, not (yet) +regenerated grub.cfg files which miss the menu_show_once_timeout check. +This older grubenv variable leads to a fixed timeout of 60 seconds. + +Note that the new menu_show_once_timeout will overrule these 60 seconds +if both are set and the grub.cfg does have the menu_show_once_timeout +check. + +Signed-off-by: Hans de Goede +--- + util/systemd/systemd-integration.sh.in | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/util/systemd/systemd-integration.sh.in b/util/systemd/systemd-integration.sh.in +index dc1218597b..a4c071c5b0 100644 +--- a/util/systemd/systemd-integration.sh.in ++++ b/util/systemd/systemd-integration.sh.in +@@ -4,3 +4,8 @@ TIMEOUT_USEC=$(cat /run/systemd/reboot-to-boot-loader-menu) + TIMEOUT=$(((TIMEOUT_USEC + 500000) / 1000000)) + + @grub_editenv@ - set menu_show_once_timeout=$TIMEOUT ++ ++# Downstream RH / Fedora patch for compatibility with old, not (yet) ++# regenerated grub.cfg files which miss the menu_show_once_timeout check ++# this older grubenv variable leads to a fixed timeout of 60 seconds ++@grub_editenv@ - set menu_show_once=1 diff --git a/SOURCES/0143-Add-start-symbol-for-RISC-V.patch b/SOURCES/0143-Add-start-symbol-for-RISC-V.patch deleted file mode 100644 index 677efae..0000000 --- a/SOURCES/0143-Add-start-symbol-for-RISC-V.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Abdurachmanov -Date: Sat, 9 Nov 2019 19:51:57 +0000 -Subject: [PATCH] Add start symbol for RISC-V - -All other architectures have start symbol. - -Hopefully this resolves: - - BUILDSTDERR: ././grub-mkimage: error: undefined symbol start. - -Signed-off-by: David Abdurachmanov ---- - grub-core/kern/riscv/efi/startup.S | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/grub-core/kern/riscv/efi/startup.S b/grub-core/kern/riscv/efi/startup.S -index f2a7b2b1ede..781773136e8 100644 ---- a/grub-core/kern/riscv/efi/startup.S -+++ b/grub-core/kern/riscv/efi/startup.S -@@ -29,6 +29,7 @@ - - .file "startup.S" - .text -+FUNCTION(start) - FUNCTION(_start) - /* - * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0. diff --git a/SOURCES/0143-at_keyboard-use-set-1-when-keyboard-is-in-Translate-.patch b/SOURCES/0143-at_keyboard-use-set-1-when-keyboard-is-in-Translate-.patch new file mode 100644 index 0000000..f891a69 --- /dev/null +++ b/SOURCES/0143-at_keyboard-use-set-1-when-keyboard-is-in-Translate-.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Thu, 3 Dec 2020 09:13:24 +0100 +Subject: [PATCH] at_keyboard: use set 1 when keyboard is in Translate mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When keyboard controller acts in Translate mode (0x40 mask), then use +set 1 since translation is done. +Otherwise use the mode queried from the controller (usually set 2). + +Added "atkeyb" debugging messages in at_keyboard module as well. + +Resolves: rhbz#1897587 + +Tested on: +- Asus N53SN (set 1 used) +- Dell Precision (set 1 used) +- HP Elitebook (set 2 used) +- HP G5430 (set 1 used, keyboard in XT mode!) +- Lenovo P71 & Lenovo T460s (set 2 used) +- QEMU/KVM (set 1 used) + +Signed-off-by: Renaud Métrich +--- + grub-core/term/at_keyboard.c | 29 ++++++++++++++++++++++++----- + include/grub/at_keyboard.h | 4 ++++ + 2 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c +index 597111077b..2601438260 100644 +--- a/grub-core/term/at_keyboard.c ++++ b/grub-core/term/at_keyboard.c +@@ -135,20 +135,28 @@ query_mode (void) + int e; + + e = write_mode (0); +- if (!e) ++ if (!e) { ++ grub_dprintf("atkeyb", "query_mode: write_mode(0) failed\n"); + return 0; ++ } + + do { + keyboard_controller_wait_until_ready (); + ret = grub_inb (KEYBOARD_REG_DATA); + } while (ret == GRUB_AT_ACK); + /* QEMU translates the set even in no-translate mode. */ +- if (ret == 0x43 || ret == 1) ++ if (ret == 0x43 || ret == 1) { ++ grub_dprintf("atkeyb", "query_mode: returning 1 (ret=0x%x)\n", ret); + return 1; +- if (ret == 0x41 || ret == 2) ++ } ++ if (ret == 0x41 || ret == 2) { ++ grub_dprintf("atkeyb", "query_mode: returning 2 (ret=0x%x)\n", ret); + return 2; +- if (ret == 0x3f || ret == 3) ++ } ++ if (ret == 0x3f || ret == 3) { ++ grub_dprintf("atkeyb", "query_mode: returning 3 (ret=0x%x)\n", ret); + return 3; ++ } + return 0; + } + +@@ -165,7 +173,13 @@ set_scancodes (void) + } + + #if !USE_SCANCODE_SET +- ps2_state.current_set = 1; ++ if ((grub_keyboard_controller_orig & KEYBOARD_AT_TRANSLATE) == KEYBOARD_AT_TRANSLATE) { ++ grub_dprintf ("atkeyb", "queried set is %d but keyboard in Translate mode, so actually in set 1\n", grub_keyboard_orig_set); ++ ps2_state.current_set = 1; ++ } else { ++ grub_dprintf ("atkeyb", "using queried set %d\n", grub_keyboard_orig_set); ++ ps2_state.current_set = grub_keyboard_orig_set; ++ } + return; + #else + +@@ -266,6 +280,7 @@ grub_keyboard_controller_init (void) + grub_keyboard_orig_set = 2; + #else + grub_keyboard_controller_orig = grub_keyboard_controller_read (); ++ grub_dprintf ("atkeyb", "grub_keyboard_controller_orig = 0x%x\n", grub_keyboard_controller_orig); + grub_keyboard_orig_set = query_mode (); + #endif + set_scancodes (); +@@ -275,11 +290,15 @@ grub_keyboard_controller_init (void) + static grub_err_t + grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) + { ++/* In !USE_SCANCODE_SET mode, we didn't change anything, so nothing to restore */ ++#if USE_SCANCODE_SET + if (ps2_state.current_set == 0) + return GRUB_ERR_NONE; ++ grub_dprintf ("atkeyb", "restoring set %d, controller 0x%x\n", grub_keyboard_orig_set, grub_keyboard_controller_orig); + if (grub_keyboard_orig_set) + write_mode (grub_keyboard_orig_set); + grub_keyboard_controller_write (grub_keyboard_controller_orig); ++#endif + return GRUB_ERR_NONE; + } + +diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h +index bcb4d9ba78..9414dc1b99 100644 +--- a/include/grub/at_keyboard.h ++++ b/include/grub/at_keyboard.h +@@ -19,6 +19,10 @@ + #ifndef GRUB_AT_KEYBOARD_HEADER + #define GRUB_AT_KEYBOARD_HEADER 1 + ++/* ++ * Refer to https://wiki.osdev.org/%228042%22_PS/2_Controller for details. ++ */ ++ + /* Used for sending commands to the controller. */ + #define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02) + #define KEYBOARD_COMMAND_READ 0x20 diff --git a/SOURCES/0144-bootstrap.conf-Force-autogen.sh-to-use-python3.patch b/SOURCES/0144-bootstrap.conf-Force-autogen.sh-to-use-python3.patch deleted file mode 100644 index 5c3b968..0000000 --- a/SOURCES/0144-bootstrap.conf-Force-autogen.sh-to-use-python3.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Wed, 15 Jan 2020 12:47:46 +0100 -Subject: [PATCH] bootstrap.conf: Force autogen.sh to use python3 - -The python-unversioned-command package is not installed in the buildroot, -but the bootstrap script expects the python command to be present if one -is not defined. So building the package leads to the following error: - -./autogen.sh: line 20: python: command not found - -This is harmless since gnulib is included as a source anyways, because the -builders can't download. But still the issue should be fixed by forcing to -use python3 that's the default in Fedora now. - -Signed-off-by: Javier Martinez Canillas ---- - bootstrap.conf | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/bootstrap.conf b/bootstrap.conf -index 452f4d79b0d..03f10930230 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -93,7 +93,7 @@ bootstrap_post_import_hook () { - patch -d po -p3 \ - < "po/gettext-patches/$patchname.patch" - done -- FROM_BOOTSTRAP=1 ./autogen.sh -+ PYTHON=python3 FROM_BOOTSTRAP=1 ./autogen.sh - set +e # bootstrap expects this - } - diff --git a/SOURCES/0144-grub-install-disable-support-for-EFI-platforms.patch b/SOURCES/0144-grub-install-disable-support-for-EFI-platforms.patch new file mode 100644 index 0000000..f6a7530 --- /dev/null +++ b/SOURCES/0144-grub-install-disable-support-for-EFI-platforms.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jan Hlavac +Date: Fri, 20 Nov 2020 23:51:47 +0100 +Subject: [PATCH] grub-install: disable support for EFI platforms + +For each platform, GRUB is shipped as a kernel image and a set of +modules. These files are then used by the grub-install utility to +install GRUB on a specific device. However, in order to support UEFI +Secure Boot, the resulting EFI binary must be signed by a recognized +private key. For this reason, for EFI platforms, most distributions also +ship prebuilt EFI binaries signed by a distribution-specific private +key. In this case, however, the grub-install utility should not be used +because it would overwrite the signed EFI binary. + +The current fix is suboptimal because it preserves all EFI-related code. +A better solution could be to modularize the code and provide a +build-time option. + +Resolves: rhbz#1737444 + +Signed-off-by: Jan Hlavac +[rharwood: drop man page] +--- + util/grub-install.c | 37 ++++++++++++++++--------------------- + docs/grub.texi | 7 +++++++ + 2 files changed, 23 insertions(+), 21 deletions(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index a2bec7446c..5babc7af55 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -899,6 +899,22 @@ main (int argc, char *argv[]) + + platform = grub_install_get_target (grub_install_source_directory); + ++ switch (platform) ++ { ++ case GRUB_INSTALL_PLATFORM_ARM_EFI: ++ case GRUB_INSTALL_PLATFORM_ARM64_EFI: ++ case GRUB_INSTALL_PLATFORM_I386_EFI: ++ case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_X86_64_EFI: ++ is_efi = 1; ++ grub_util_error (_("this utility cannot be used for EFI platforms" ++ " because it does not support UEFI Secure Boot")); ++ break; ++ default: ++ is_efi = 0; ++ break; ++ } ++ + { + char *platname = grub_install_get_platform_name (platform); + fprintf (stderr, _("Installing for %s platform.\n"), platname); +@@ -1011,28 +1027,7 @@ main (int argc, char *argv[]) + grub_hostfs_init (); + grub_host_init (); + +- switch (platform) +- { +- case GRUB_INSTALL_PLATFORM_I386_EFI: +- case GRUB_INSTALL_PLATFORM_X86_64_EFI: +- case GRUB_INSTALL_PLATFORM_ARM_EFI: +- case GRUB_INSTALL_PLATFORM_ARM64_EFI: +- case GRUB_INSTALL_PLATFORM_RISCV32_EFI: +- case GRUB_INSTALL_PLATFORM_RISCV64_EFI: +- case GRUB_INSTALL_PLATFORM_IA64_EFI: +- is_efi = 1; +- break; +- default: +- is_efi = 0; +- break; +- +- /* pacify warning. */ +- case GRUB_INSTALL_PLATFORM_MAX: +- break; +- } +- + /* Find the EFI System Partition. */ +- + if (is_efi) + { + grub_fs_t fs; +diff --git a/docs/grub.texi b/docs/grub.texi +index 04ed6ac1f0..4870faaa00 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -6509,6 +6509,13 @@ grub2-install @var{install_device} + The device name @var{install_device} is an OS device name or a GRUB + device name. + ++In order to support UEFI Secure Boot, the resulting GRUB EFI binary must ++be signed by a recognized private key. For this reason, for EFI ++platforms, most distributions also ship prebuilt GRUB EFI binaries ++signed by a distribution-specific private key. In this case, however, ++@command{grub2-install} should not be used because it would overwrite ++the signed EFI binary. ++ + @command{grub2-install} accepts the following options: + + @table @option diff --git a/SOURCES/0145-New-with-debug-timestamps-configure-flag-to-prepend-.patch b/SOURCES/0145-New-with-debug-timestamps-configure-flag-to-prepend-.patch new file mode 100644 index 0000000..ec5b30b --- /dev/null +++ b/SOURCES/0145-New-with-debug-timestamps-configure-flag-to-prepend-.patch @@ -0,0 +1,112 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Sat, 23 Nov 2019 14:57:41 +0100 +Subject: [PATCH] New --with-debug-timestamps configure flag to prepend debug + traces with absolute and relative timestamp +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Renaud Métrich +--- + configure.ac | 18 ++++++++++++++++++ + grub-core/kern/misc.c | 20 ++++++++++++++++++++ + config.h.in | 1 + + 3 files changed, 39 insertions(+) + +diff --git a/configure.ac b/configure.ac +index a02d40a05b..ab0d326f00 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1585,6 +1585,17 @@ else + fi + AC_SUBST([BOOT_TIME_STATS]) + ++AC_ARG_WITH([debug-timestamps], ++ AS_HELP_STRING([--with-debug-timestamps], ++ [prepend debug traces with absolute and relative timestamps])) ++ ++if test x$with_debug_timestamps = xyes; then ++ DEBUG_WITH_TIMESTAMPS=1 ++else ++ DEBUG_WITH_TIMESTAMPS=0 ++fi ++AC_SUBST([DEBUG_WITH_TIMESTAMPS]) ++ + AC_ARG_ENABLE([grub-emu-sdl], + [AS_HELP_STRING([--enable-grub-emu-sdl], + [build and install the `grub-emu' debugging utility with SDL support (default=guessed)])]) +@@ -2136,6 +2147,7 @@ AM_CONDITIONAL([COND_APPLE_LINKER], [test x$TARGET_APPLE_LINKER = x1]) + AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) + AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1]) + AM_CONDITIONAL([COND_ENABLE_BOOT_TIME_STATS], [test x$BOOT_TIME_STATS = x1]) ++AM_CONDITIONAL([COND_DEBUG_WITH_TIMESTAMPS], [test x$DEBUG_WITH_TIMESTAMPS = x1]) + + AM_CONDITIONAL([COND_HAVE_CXX], [test x$HAVE_CXX = xyes]) + +@@ -2231,6 +2243,12 @@ else + echo With boot time statistics: No + fi + ++if [ x"$with_debug_timestamps" = xyes ]; then ++echo Debug traces with timestamps: Yes ++else ++echo Debug traces with timestamps: No ++fi ++ + if [ x"$efiemu_excuse" = x ]; then + echo efiemu runtime: Yes + else +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index 578bf51a5f..9f54b6b7d2 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -25,6 +25,9 @@ + #include + #include + #include ++#if DEBUG_WITH_TIMESTAMPS ++#include ++#endif + + union printf_arg + { +@@ -192,9 +195,26 @@ grub_real_dprintf (const char *file, const int line, const char *condition, + const char *fmt, ...) + { + va_list args; ++#if DEBUG_WITH_TIMESTAMPS ++ static long unsigned int last_time = 0; ++ static int last_had_cr = 1; ++#endif + + if (grub_debug_enabled (condition)) + { ++#if DEBUG_WITH_TIMESTAMPS ++ /* Don't print timestamp if last printed message isn't terminated yet */ ++ if (last_had_cr) { ++ long unsigned int tmabs = (long unsigned int) grub_get_time_ms(); ++ long unsigned int tmrel = tmabs - last_time; ++ last_time = tmabs; ++ grub_printf ("%3lu.%03lus +%2lu.%03lus ", tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000); ++ } ++ if (fmt[grub_strlen(fmt)-1] == '\n') ++ last_had_cr = 1; ++ else ++ last_had_cr = 0; ++#endif + grub_printf ("%s:%d: ", file, line); + va_start (args, fmt); + grub_vprintf (fmt, args); +diff --git a/config.h.in b/config.h.in +index c7e316f0f1..c80e3e0aba 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -12,6 +12,7 @@ + /* Define to 1 to enable disk cache statistics. */ + #define DISK_CACHE_STATS @DISK_CACHE_STATS@ + #define BOOT_TIME_STATS @BOOT_TIME_STATS@ ++#define DEBUG_WITH_TIMESTAMPS @DEBUG_WITH_TIMESTAMPS@ + + /* We don't need those. */ + #define MINILZO_CFG_SKIP_LZO_PTR 1 diff --git a/SOURCES/0145-efi-http-Export-fw-http-_path-variables-to-make-them.patch b/SOURCES/0145-efi-http-Export-fw-http-_path-variables-to-make-them.patch deleted file mode 100644 index 6f2e93d..0000000 --- a/SOURCES/0145-efi-http-Export-fw-http-_path-variables-to-make-them.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Thu, 5 Mar 2020 16:21:47 +0100 -Subject: [PATCH] efi/http: Export {fw,http}_path variables to make them global - -The fw_path environment variable is used by http_configure() function to -determine the HTTP path that should be used as prefix when using relative -HTTP paths. And this is stored in the http_path environment variable. - -Later, that variable is looked up by grub_efihttp_open() to generate the -complete path to be used in the HTTP request. - -But these variables are not exported, which means that are not global and -so are only found in the initial context. - -This can cause commands like configfile that create a new context to fail -because the fw_path and http_path variables will not be found. - -Resolves: rhbz#1616395 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/kern/main.c | 1 + - grub-core/net/efi/http.c | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index 4ec3f5e4d33..0285e95a2bb 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -143,6 +143,7 @@ grub_set_prefix_and_root (void) - if (fw_path) - { - grub_env_set ("fw_path", fw_path); -+ grub_env_export ("fw_path"); - grub_dprintf ("fw_path", "fw_path:\"%s\"\n", fw_path); - grub_free (fw_path); - } -diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c -index de351b2cd03..755b7a6d054 100644 ---- a/grub-core/net/efi/http.c -+++ b/grub-core/net/efi/http.c -@@ -39,6 +39,7 @@ http_configure (struct grub_efi_net_device *dev, int prefer_ip6) - http_path++; - grub_env_unset ("http_path"); - grub_env_set ("http_path", http_path); -+ grub_env_export ("http_path"); - } - } - diff --git a/SOURCES/0146-Added-debug-statements-to-grub_disk_open-and-grub_di.patch b/SOURCES/0146-Added-debug-statements-to-grub_disk_open-and-grub_di.patch new file mode 100644 index 0000000..d26027c --- /dev/null +++ b/SOURCES/0146-Added-debug-statements-to-grub_disk_open-and-grub_di.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Sat, 23 Nov 2019 15:22:16 +0100 +Subject: [PATCH] Added debug statements to grub_disk_open() and + grub_disk_close() on success +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Renaud Métrich +--- + grub-core/kern/disk.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c +index e1b0e073e0..05a28ab142 100644 +--- a/grub-core/kern/disk.c ++++ b/grub-core/kern/disk.c +@@ -285,6 +285,8 @@ grub_disk_open (const char *name) + return 0; + } + ++ grub_dprintf ("disk", "Opening `%s' succeeded.\n", name); ++ + return disk; + } + +@@ -292,7 +294,7 @@ void + grub_disk_close (grub_disk_t disk) + { + grub_partition_t part; +- grub_dprintf ("disk", "Closing `%s'.\n", disk->name); ++ grub_dprintf ("disk", "Closing `%s'...\n", disk->name); + + if (disk->dev && disk->dev->disk_close) + (disk->dev->disk_close) (disk); +@@ -306,8 +308,10 @@ grub_disk_close (grub_disk_t disk) + grub_free (disk->partition); + disk->partition = part; + } ++ grub_dprintf ("disk", "Closing `%s' succeeded.\n", disk->name); + grub_free ((void *) disk->name); + grub_free (disk); ++ + } + + /* Small read (less than cache size and not pass across cache unit boundaries). diff --git a/SOURCES/0146-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch b/SOURCES/0146-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch deleted file mode 100644 index c394549..0000000 --- a/SOURCES/0146-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Thu, 5 Mar 2020 16:21:58 +0100 -Subject: [PATCH] efi/http: Enclose literal IPv6 addresses in square brackets - -According to RFC 2732 (https://www.ietf.org/rfc/rfc2732.txt), literal IPv6 -addresses must be enclosed in square brackets. But GRUB currently does not -do this and is causing HTTP servers to send Bad Request (400) responses. - -For example, the following is the HTTP stream when fetching a config file: - -HEAD /EFI/BOOT/grub.cfg HTTP/1.1 -Host: 2000:dead:beef:a::1 -Accept: */* -User-Agent: UefiHttpBoot/1.0 - -HTTP/1.1 400 Bad Request -Date: Thu, 05 Mar 2020 14:46:02 GMT -Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d -Connection: close -Content-Type: text/html; charset=iso-8859-1 - -and after enclosing the IPv6 address the HTTP request is successful: - -HEAD /EFI/BOOT/grub.cfg HTTP/1.1 -Host: [2000:dead:beef:a::1] -Accept: */* -User-Agent: UefiHttpBoot/1.0 - -HTTP/1.1 200 OK -Date: Thu, 05 Mar 2020 14:48:04 GMT -Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d -Last-Modified: Thu, 27 Feb 2020 17:45:58 GMT -ETag: "206-59f924b24b1da" -Accept-Ranges: bytes -Content-Length: 518 - -Resolves: rhbz#1732765 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/net/efi/http.c | 37 ++++++++++++++++++++++++++++--------- - 1 file changed, 28 insertions(+), 9 deletions(-) - -diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c -index 755b7a6d054..fc8cb25ae0a 100644 ---- a/grub-core/net/efi/http.c -+++ b/grub-core/net/efi/http.c -@@ -158,13 +158,7 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, - grub_efi_status_t status; - grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; - char *url = NULL; -- -- request_headers[0].field_name = (grub_efi_char8_t *)"Host"; -- request_headers[0].field_value = (grub_efi_char8_t *)server; -- request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; -- request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; -- request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; -- request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0"; -+ char *hostname = NULL; - - { - grub_efi_ipv6_address_t address; -@@ -174,9 +168,24 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, - const char *protocol = (use_https == 1) ? "https" : "http"; - - if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0) -- url = grub_xasprintf ("%s://[%s]%s", protocol, server, name); -+ { -+ hostname = grub_xasprintf ("[%s]", server); -+ if (!hostname) -+ return GRUB_ERR_OUT_OF_MEMORY; -+ -+ server = hostname; -+ -+ url = grub_xasprintf ("%s://%s%s", protocol, server, name); -+ if (!url) -+ { -+ grub_free (hostname); -+ return GRUB_ERR_OUT_OF_MEMORY; -+ } -+ } - else -- url = grub_xasprintf ("%s://%s%s", protocol, server, name); -+ { -+ url = grub_xasprintf ("%s://%s%s", protocol, server, name); -+ } - - if (!url) - { -@@ -199,6 +208,13 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, - request_data.url = ucs2_url; - } - -+ request_headers[0].field_name = (grub_efi_char8_t *)"Host"; -+ request_headers[0].field_value = (grub_efi_char8_t *)server; -+ request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; -+ request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; -+ request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; -+ request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0"; -+ - request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET; - - request_message.data.request = &request_data; -@@ -228,6 +244,9 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, - - status = efi_call_2 (http->request, http, &request_token); - -+ if (hostname) -+ grub_free (hostname); -+ - if (status != GRUB_EFI_SUCCESS) - { - efi_call_1 (b->close_event, request_token.event); diff --git a/SOURCES/0147-Introduce-function-grub_debug_is_enabled-void-return.patch b/SOURCES/0147-Introduce-function-grub_debug_is_enabled-void-return.patch new file mode 100644 index 0000000..9ce5d9d --- /dev/null +++ b/SOURCES/0147-Introduce-function-grub_debug_is_enabled-void-return.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Mon, 25 Nov 2019 09:29:53 +0100 +Subject: [PATCH] Introduce function grub_debug_is_enabled(void) returning 1 if + 'debug' is in the environment and not empty +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Renaud Métrich +--- + grub-core/kern/misc.c | 13 +++++++++++++ + include/grub/misc.h | 1 + + 2 files changed, 14 insertions(+) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index 9f54b6b7d2..a186ad3dd4 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -163,6 +163,19 @@ int grub_err_printf (const char *fmt, ...) + __attribute__ ((alias("grub_printf"))); + #endif + ++/* Return 1 if 'debug' is set and not empty */ ++int ++grub_debug_is_enabled (void) ++{ ++ const char *debug; ++ ++ debug = grub_env_get ("debug"); ++ if (!debug || debug[0] == '\0') ++ return 0; ++ ++ return 1; ++} ++ + int + grub_debug_enabled (const char * condition) + { +diff --git a/include/grub/misc.h b/include/grub/misc.h +index 3adc4036e3..6c4aa85ac5 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -340,6 +340,7 @@ grub_puts (const char *s) + } + + int EXPORT_FUNC(grub_puts_) (const char *s); ++int EXPORT_FUNC(grub_debug_is_enabled) (void); + int EXPORT_FUNC(grub_debug_enabled) (const char *condition); + void EXPORT_FUNC(grub_real_dprintf) (const char *file, + const int line, diff --git a/SOURCES/0147-efi-net-Allow-to-specify-a-port-number-in-addresses.patch b/SOURCES/0147-efi-net-Allow-to-specify-a-port-number-in-addresses.patch deleted file mode 100644 index 209aed8..0000000 --- a/SOURCES/0147-efi-net-Allow-to-specify-a-port-number-in-addresses.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 9 Mar 2020 15:29:45 +0100 -Subject: [PATCH] efi/net: Allow to specify a port number in addresses - -The grub_efi_net_parse_address() function is not covering the case where a -port number is specified in an IPv4 or IPv6 address, so will fail to parse -the network address. - -For most cases the issue is harmless, because the function is only used to -match an address with a network interface and if fails the default is used. - -But still is a bug that has to be fixed and it causes error messages to be -printed like the following: - -error: net/efi/net.c:782:unrecognised network address '192.168.122.1:8080' - -error: net/efi/net.c:781:unrecognised network address '[2000:dead:beef:a::1]:8080' - -Resolves: rhbz#1732765 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/net/efi/net.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c -index 6603cd83edc..84573937b18 100644 ---- a/grub-core/net/efi/net.c -+++ b/grub-core/net/efi/net.c -@@ -742,7 +742,7 @@ grub_efi_net_parse_address (const char *address, - return GRUB_ERR_NONE; - } - } -- else if (*rest == 0) -+ else if (*rest == 0 || *rest == ':') - { - grub_uint32_t subnet_mask = 0xffffffffU; - grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); -@@ -768,7 +768,7 @@ grub_efi_net_parse_address (const char *address, - return GRUB_ERR_NONE; - } - } -- else if (*rest == 0) -+ else if (*rest == 0 || *rest == ':') - { - ip6->prefix_length = 128; - ip6->is_anycast = 0; diff --git a/SOURCES/0148-Don-t-clear-screen-when-debugging-is-enabled.patch b/SOURCES/0148-Don-t-clear-screen-when-debugging-is-enabled.patch new file mode 100644 index 0000000..c35d8a3 --- /dev/null +++ b/SOURCES/0148-Don-t-clear-screen-when-debugging-is-enabled.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Sat, 23 Nov 2019 16:23:54 +0100 +Subject: [PATCH] Don't clear screen when debugging is enabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Renaud Métrich +[rharwood@redhat.com: rebase fuzz] +Signed-off-by: Robbie Harwood +--- + grub-core/normal/main.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index af9792c963..7de9e4c36d 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -215,8 +215,9 @@ grub_normal_init_page (struct grub_term_output *term, + char *msg_formatted; + grub_uint32_t *unicode_msg; + grub_uint32_t *last_position; +- +- grub_term_cls (term); ++ ++ if (! grub_debug_is_enabled ()) ++ grub_term_cls (term); + + msg_formatted = grub_xasprintf (_("GRUB version %s"), PACKAGE_VERSION); + if (!msg_formatted) diff --git a/SOURCES/0148-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch b/SOURCES/0148-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch deleted file mode 100644 index f92dee4..0000000 --- a/SOURCES/0148-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 9 Mar 2020 15:30:05 +0100 -Subject: [PATCH] efi/ip4_config: Improve check to detect literal IPv6 - addresses - -The grub_efi_string_to_ip4_address() function wrongly assumes that an IPv6 -address is an IPv4 address, because it doesn't take into account the case -of a caller passing an IPv6 address as a string. - -This leads to the grub_efi_net_parse_address() function to fail and print -the following error message: - -error: net/efi/net.c:785:unrecognised network address '2000:dead:beef:a::1' - -Resolves: rhbz#1732765 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/net/efi/ip4_config.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c -index b711a5d9457..313c818b184 100644 ---- a/grub-core/net/efi/ip4_config.c -+++ b/grub-core/net/efi/ip4_config.c -@@ -56,9 +56,20 @@ int - grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest) - { - grub_uint32_t newip = 0; -- int i; -+ int i, ncolon = 0; - const char *ptr = val; - -+ /* Check that is not an IPv6 address */ -+ for (i = 0; i < grub_strlen(ptr); i++) -+ { -+ if (ptr[i] == '[' && i == 0) -+ return 0; -+ -+ if (ptr[i] == ':') -+ if (i == 0 || ++ncolon == 2) -+ return 0; -+ } -+ - for (i = 0; i < 4; i++) - { - unsigned long t; diff --git a/SOURCES/0149-efi-net-Print-a-debug-message-if-parsing-the-address.patch b/SOURCES/0149-efi-net-Print-a-debug-message-if-parsing-the-address.patch deleted file mode 100644 index 33d8f88..0000000 --- a/SOURCES/0149-efi-net-Print-a-debug-message-if-parsing-the-address.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 10 Mar 2020 11:23:49 +0100 -Subject: [PATCH] efi/net: Print a debug message if parsing the address fails - -Currently if parsing the address fails an error message is printed. But in -most cases this isn't a fatal error since the grub_efi_net_parse_address() -function is only used to match an address with a network interface to use. - -And if this fails, the default interface is used which is good enough for -most cases. So instead of printing an error that would pollute the console -just print a debug message if the address is not parsed correctly. - -A user can enable debug messages for the efinet driver to have information -about the failure and the fact that the default interface is being used. - -Related: rhbz#1732765 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/net/efi/net.c | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c -index 84573937b18..a3f0535d43c 100644 ---- a/grub-core/net/efi/net.c -+++ b/grub-core/net/efi/net.c -@@ -778,9 +778,9 @@ grub_efi_net_parse_address (const char *address, - } - } - -- return grub_error (GRUB_ERR_NET_BAD_ADDRESS, -- N_("unrecognised network address `%s'"), -- address); -+ grub_dprintf ("efinet", "unrecognised network address '%s'\n", address); -+ -+ return GRUB_ERR_NET_BAD_ADDRESS; - } - - static grub_efi_net_interface_t * -@@ -795,10 +795,7 @@ match_route (const char *server) - err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0); - - if (err) -- { -- grub_print_error (); - return NULL; -- } - - if (is_ip6) - { -@@ -1233,8 +1230,15 @@ grub_net_open_real (const char *name __attribute__ ((unused))) - /*FIXME: Use DNS translate name to address */ - net_interface = match_route (server); - -+ if (!net_interface && net_default_interface) -+ { -+ net_interface = net_default_interface; -+ grub_dprintf ("efinet", "interface lookup failed, using default '%s'\n", -+ net_interface->name); -+ } -+ - /*XXX: should we check device with default gateway ? */ -- if (!net_interface && !(net_interface = net_default_interface)) -+ if (!net_interface) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"), - name); diff --git a/SOURCES/0149-kern-file-Fix-error-handling-in-grub_file_open.patch b/SOURCES/0149-kern-file-Fix-error-handling-in-grub_file_open.patch new file mode 100644 index 0000000..e444325 --- /dev/null +++ b/SOURCES/0149-kern-file-Fix-error-handling-in-grub_file_open.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Steve McIntyre +Date: Tue, 6 Dec 2022 01:45:11 +0000 +Subject: [PATCH] kern/file: Fix error handling in grub_file_open() + +grub_file_open() calls grub_file_get_device_name(), but doesn't check +the return. Instead, it checks if grub_errno is set. + +However, nothing initialises grub_errno here when grub_file_open() +starts. This means that trying to open one file that doesn't exist and +then trying to open another file that does will (incorrectly) also +fail to open that second file. + +Let's fix that. + +Signed-off-by: Steve McIntyre +--- + grub-core/kern/file.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c +index 58454458c4..5b58f45cfd 100644 +--- a/grub-core/kern/file.c ++++ b/grub-core/kern/file.c +@@ -66,6 +66,9 @@ grub_file_open (const char *name, enum grub_file_type type) + const char *file_name; + grub_file_filter_id_t filter; + ++ /* Reset grub_errno before we start */ ++ grub_errno = GRUB_ERR_NONE; ++ + device_name = grub_file_get_device_name (name); + if (grub_errno) + goto fail; diff --git a/SOURCES/0150-grub_file_-instrumentation-new-file-debug-tag.patch b/SOURCES/0150-grub_file_-instrumentation-new-file-debug-tag.patch new file mode 100644 index 0000000..6327899 --- /dev/null +++ b/SOURCES/0150-grub_file_-instrumentation-new-file-debug-tag.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Fri, 29 Nov 2019 11:02:00 +0100 +Subject: [PATCH] grub_file_* instrumentation (new 'file' debug tag) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Renaud Métrich +--- + grub-core/kern/file.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c +index 5b58f45cfd..ec10e54fc0 100644 +--- a/grub-core/kern/file.c ++++ b/grub-core/kern/file.c +@@ -66,6 +66,8 @@ grub_file_open (const char *name, enum grub_file_type type) + const char *file_name; + grub_file_filter_id_t filter; + ++ grub_dprintf ("file", "Opening `%s' ...\n", name); ++ + /* Reset grub_errno before we start */ + grub_errno = GRUB_ERR_NONE; + +@@ -131,6 +133,8 @@ grub_file_open (const char *name, enum grub_file_type type) + if (!file) + grub_file_close (last_file); + ++ grub_dprintf ("file", "Opening `%s' succeeded.\n", name); ++ + return file; + + fail: +@@ -141,6 +145,8 @@ grub_file_open (const char *name, enum grub_file_type type) + + grub_free (file); + ++ grub_dprintf ("file", "Opening `%s' failed.\n", name); ++ + return 0; + } + +@@ -172,6 +178,7 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) + + if (len == 0) + return 0; ++ + read_hook = file->read_hook; + read_hook_data = file->read_hook_data; + if (!file->read_hook) +@@ -192,11 +199,18 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) + grub_err_t + grub_file_close (grub_file_t file) + { ++ grub_dprintf ("file", "Closing `%s' ...\n", file->name); + if (file->fs->fs_close) + (file->fs->fs_close) (file); + + if (file->device) + grub_device_close (file->device); ++ ++ if (grub_errno == GRUB_ERR_NONE) ++ grub_dprintf ("file", "Closing `%s' succeeded.\n", file->name); ++ else ++ grub_dprintf ("file", "Closing `%s' failed with %d.\n", file->name, grub_errno); ++ + grub_free (file->name); + grub_free (file); + return grub_errno; diff --git a/SOURCES/0150-kern-term-Also-accept-F8-as-a-user-interrupt-key.patch b/SOURCES/0150-kern-term-Also-accept-F8-as-a-user-interrupt-key.patch deleted file mode 100644 index 3dd525a..0000000 --- a/SOURCES/0150-kern-term-Also-accept-F8-as-a-user-interrupt-key.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Wed, 22 Apr 2020 12:41:52 +0200 -Subject: [PATCH] kern/term: Also accept F8 as a user interrupt key - -Make F8, which used to be the hotkey to show the Windows boot menu during -boot for a long long time, also interrupt sleeps / stop the menu countdown. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/kern/term.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c -index 14d59649832..4d61f4e9790 100644 ---- a/grub-core/kern/term.c -+++ b/grub-core/kern/term.c -@@ -144,9 +144,10 @@ grub_key_is_interrupt (int key) - /* - * ESC sometimes is the BIOS setup hotkey and may be hard to discover, also - * check F4, which was chosen because is not used as a hotkey to enter the -- * BIOS setup by any vendor. -+ * BIOS setup by any vendor. Also, F8 which was the key to get the Windows -+ * bootmenu for a long time. - */ -- if (key == GRUB_TERM_ESC || key == GRUB_TERM_KEY_F4) -+ if (key == GRUB_TERM_ESC || key == GRUB_TERM_KEY_F4 || key == GRUB_TERM_KEY_F8) - return 1; - - /* diff --git a/SOURCES/0151-efi-Set-image-base-address-before-jumping-to-the-PE-.patch b/SOURCES/0151-efi-Set-image-base-address-before-jumping-to-the-PE-.patch deleted file mode 100644 index 336bcf1..0000000 --- a/SOURCES/0151-efi-Set-image-base-address-before-jumping-to-the-PE-.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Thu, 23 Apr 2020 15:06:46 +0200 -Subject: [PATCH] efi: Set image base address before jumping to the PE/COFF - entry point - -Upstream GRUB uses the EFI LoadImage() and StartImage() to boot the Linux -kernel. But our custom EFI loader that supports Secure Boot instead uses -the EFI handover protocol (for x86) or jumping directly to the PE/COFF -entry point (for aarch64). - -This is done to allow the bootloader to verify the images using the shim -lock protocol to avoid booting untrusted binaries. - -Since the bootloader loads the kernel from the boot media instead of using -LoadImage(), it is responsible to set the Loaded Image base address before -booting the kernel. - -Otherwise the kernel EFI stub will complain that it was not set correctly -and print the following warning message: - -EFI stub: ERROR: FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value - -Resolves: rhbz#1814690 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/loader/efi/linux.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c -index 0622dfa48d4..e8b9ecb17f6 100644 ---- a/grub-core/loader/efi/linux.c -+++ b/grub-core/loader/efi/linux.c -@@ -72,6 +72,7 @@ grub_err_t - grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, - void *kernel_params) - { -+ grub_efi_loaded_image_t *loaded_image = NULL; - handover_func hf; - int offset = 0; - -@@ -79,6 +80,19 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, - offset = 512; - #endif - -+ /* -+ * Since the EFI loader is not calling the LoadImage() and StartImage() -+ * services for loading the kernel and booting respectively, it has to -+ * set the Loaded Image base address. -+ */ -+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); -+ if (loaded_image) -+ loaded_image->image_base = kernel_addr; -+ else -+ grub_dprintf ("linux", "Loaded Image base address could not be set\n"); -+ -+ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", -+ kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); - hf = (handover_func)((char *)kernel_addr + handover_offset + offset); - hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); - diff --git a/SOURCES/0151-ieee1275-Avoiding-many-unecessary-open-close.patch b/SOURCES/0151-ieee1275-Avoiding-many-unecessary-open-close.patch new file mode 100644 index 0000000..f6c5244 --- /dev/null +++ b/SOURCES/0151-ieee1275-Avoiding-many-unecessary-open-close.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Mon, 14 Dec 2020 17:42:45 +0100 +Subject: [PATCH] ieee1275: Avoiding many unecessary open/close + +Signed-off-by: Diego Domingos +--- + grub-core/disk/ieee1275/ofdisk.c | 64 ++++++++++++++++++++++------------------ + 1 file changed, 35 insertions(+), 29 deletions(-) + +diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c +index 03674cb477..ea7f78ac7d 100644 +--- a/grub-core/disk/ieee1275/ofdisk.c ++++ b/grub-core/disk/ieee1275/ofdisk.c +@@ -44,7 +44,7 @@ struct ofdisk_hash_ent + }; + + static grub_err_t +-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, ++grub_ofdisk_get_block_size (grub_uint32_t *block_size, + struct ofdisk_hash_ent *op); + + #define OFDISK_HASH_SZ 8 +@@ -461,6 +461,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) + grub_ssize_t actual; + grub_uint32_t block_size = 0; + grub_err_t err; ++ struct ofdisk_hash_ent *op; + + if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, +@@ -471,6 +472,35 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) + + grub_dprintf ("disk", "Opening `%s'.\n", devpath); + ++ op = ofdisk_hash_find (devpath); ++ if (!op) ++ op = ofdisk_hash_add (devpath, NULL); ++ if (!op) ++ { ++ grub_free (devpath); ++ return grub_errno; ++ } ++ ++ /* Check if the call to open is the same to the last disk already opened */ ++ if (last_devpath && !grub_strcmp(op->open_path,last_devpath)) ++ { ++ goto finish; ++ } ++ ++ /* If not, we need to close the previous disk and open the new one */ ++ else { ++ if (last_ihandle){ ++ grub_ieee1275_close (last_ihandle); ++ } ++ last_ihandle = 0; ++ last_devpath = NULL; ++ ++ grub_ieee1275_open (op->open_path, &last_ihandle); ++ if (! last_ihandle) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); ++ last_devpath = op->open_path; ++ } ++ + if (grub_ieee1275_finddevice (devpath, &dev)) + { + grub_free (devpath); +@@ -491,25 +521,18 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device"); + } + ++ ++ finish: + /* XXX: There is no property to read the number of blocks. There + should be a property `#blocks', but it is not there. Perhaps it + is possible to use seek for this. */ + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; + + { +- struct ofdisk_hash_ent *op; +- op = ofdisk_hash_find (devpath); +- if (!op) +- op = ofdisk_hash_add (devpath, NULL); +- if (!op) +- { +- grub_free (devpath); +- return grub_errno; +- } + disk->id = (unsigned long) op; + disk->data = op->open_path; + +- err = grub_ofdisk_get_block_size (devpath, &block_size, op); ++ err = grub_ofdisk_get_block_size (&block_size, op); + if (err) + { + grub_free (devpath); +@@ -532,13 +555,6 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) + static void + grub_ofdisk_close (grub_disk_t disk) + { +- if (disk->data == last_devpath) +- { +- if (last_ihandle) +- grub_ieee1275_close (last_ihandle); +- last_ihandle = 0; +- last_devpath = NULL; +- } + disk->data = 0; + } + +@@ -685,7 +701,7 @@ grub_ofdisk_init (void) + } + + static grub_err_t +-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, ++grub_ofdisk_get_block_size (grub_uint32_t *block_size, + struct ofdisk_hash_ent *op) + { + struct size_args_ieee1275 +@@ -698,16 +714,6 @@ grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, + grub_ieee1275_cell_t size2; + } args_ieee1275; + +- if (last_ihandle) +- grub_ieee1275_close (last_ihandle); +- +- last_ihandle = 0; +- last_devpath = NULL; +- +- grub_ieee1275_open (device, &last_ihandle); +- if (! last_ihandle) +- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); +- + *block_size = 0; + + if (op->block_size_fails >= 2) diff --git a/SOURCES/0152-ieee1275-powerpc-implements-fibre-channel-discovery-.patch b/SOURCES/0152-ieee1275-powerpc-implements-fibre-channel-discovery-.patch new file mode 100644 index 0000000..04c5c32 --- /dev/null +++ b/SOURCES/0152-ieee1275-powerpc-implements-fibre-channel-discovery-.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Mon, 14 Dec 2020 17:45:28 +0100 +Subject: [PATCH] ieee1275/powerpc: implements fibre channel discovery for + ofpathname + +grub-ofpathname doesn't work with fibre channel because there is no +function currently implemented for it. +This patch enables it by prividing a function that looks for the port +name, building the entire path for OF devices. + +Signed-off-by: Diego Domingos +--- + grub-core/osdep/linux/ofpath.c | 49 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c +index a6153d3595..0f5d54e9f2 100644 +--- a/grub-core/osdep/linux/ofpath.c ++++ b/grub-core/osdep/linux/ofpath.c +@@ -350,6 +350,38 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi + return ret; + } + ++ ++static void ++of_fc_port_name(const char *path, const char *subpath, char *port_name) ++{ ++ char *bname, *basepath, *p; ++ int fd; ++ ++ bname = xmalloc(sizeof(char)*150); ++ basepath = xmalloc(strlen(path)); ++ ++ /* Generate the path to get port name information from the drive */ ++ strncpy(basepath,path,subpath-path); ++ basepath[subpath-path-1] = '\0'; ++ p = get_basename(basepath); ++ snprintf(bname,sizeof(char)*150,"%s/fc_transport/%s/port_name",basepath,p); ++ ++ /* Read the information from the port name */ ++ fd = open (bname, O_RDONLY); ++ if (fd < 0) ++ grub_util_error (_("cannot open `%s': %s"), bname, strerror (errno)); ++ ++ if (read(fd,port_name,sizeof(char)*19) < 0) ++ grub_util_error (_("cannot read `%s': %s"), bname, strerror (errno)); ++ ++ sscanf(port_name,"0x%s",port_name); ++ ++ close(fd); ++ ++ free(bname); ++ free(basepath); ++} ++ + #ifdef __sparc__ + static char * + of_path_of_nvme(const char *sys_devname __attribute__((unused)), +@@ -577,6 +609,16 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev + digit_string = trailing_digits (device); + if (strncmp (of_path, "/vdevice/", sizeof ("/vdevice/") - 1) == 0) + { ++ if(strstr(of_path,"vfc-client")) ++ { ++ char * port_name = xmalloc(sizeof(char)*17); ++ of_fc_port_name(sysfs_path, p, port_name); ++ ++ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name); ++ free(port_name); ++ } ++ else ++ { + unsigned long id = 0x8000 | (tgt << 8) | (bus << 5) | lun; + if (*digit_string == '\0') + { +@@ -590,6 +632,13 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev + snprintf(disk, sizeof (disk), + "/%s@%04lx000000000000:%c", disk_name, id, 'a' + (part - 1)); + } ++ } ++ } else if (strstr(of_path,"fibre-channel")||(strstr(of_path,"vfc-client"))){ ++ char * port_name = xmalloc(sizeof(char)*17); ++ of_fc_port_name(sysfs_path, p, port_name); ++ ++ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name); ++ free(port_name); + } + else + { diff --git a/SOURCES/0152-tpm-Don-t-propagate-TPM-measurement-errors-to-the-ve.patch b/SOURCES/0152-tpm-Don-t-propagate-TPM-measurement-errors-to-the-ve.patch deleted file mode 100644 index 747773d..0000000 --- a/SOURCES/0152-tpm-Don-t-propagate-TPM-measurement-errors-to-the-ve.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Sat, 16 May 2020 11:33:18 +0200 -Subject: [PATCH] tpm: Don't propagate TPM measurement errors to the verifiers - layer - -Currently if the EFI firmware fails to do a TPM measurement for a file, -the error will be propagated to the verifiers framework and so opening -the file will not succeed. - -This mean that buggy firmwares will prevent the system to boot since the -loader won't be able to open any file. But failing to do TPM measurements -shouldn't be a fatal error and the system should still be able to boot. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/commands/tpm.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm.c -index 2052c36eaba..e287d042e6b 100644 ---- a/grub-core/commands/tpm.c -+++ b/grub-core/commands/tpm.c -@@ -42,7 +42,8 @@ grub_tpm_verify_init (grub_file_t io, - static grub_err_t - grub_tpm_verify_write (void *context, void *buf, grub_size_t size) - { -- return grub_tpm_measure (buf, size, GRUB_BINARY_PCR, context); -+ grub_tpm_measure (buf, size, GRUB_BINARY_PCR, context); -+ return GRUB_ERR_NONE; - } - - static grub_err_t -@@ -50,7 +51,6 @@ grub_tpm_verify_string (char *str, enum grub_verify_string_type type) - { - const char *prefix = NULL; - char *description; -- grub_err_t status; - - switch (type) - { -@@ -66,15 +66,15 @@ grub_tpm_verify_string (char *str, enum grub_verify_string_type type) - } - description = grub_malloc (grub_strlen (str) + grub_strlen (prefix) + 1); - if (!description) -- return grub_errno; -+ return GRUB_ERR_NONE; - grub_memcpy (description, prefix, grub_strlen (prefix)); - grub_memcpy (description + grub_strlen (prefix), str, - grub_strlen (str) + 1); -- status = -- grub_tpm_measure ((unsigned char *) str, grub_strlen (str), -- GRUB_STRING_PCR, description); -+ -+ grub_tpm_measure ((unsigned char *) str, grub_strlen (str), GRUB_STRING_PCR, -+ description); - grub_free (description); -- return status; -+ return GRUB_ERR_NONE; - } - - struct grub_file_verifier grub_tpm_verifier = { diff --git a/SOURCES/0153-ieee1275-powerpc-enables-device-mapper-discovery.patch b/SOURCES/0153-ieee1275-powerpc-enables-device-mapper-discovery.patch new file mode 100644 index 0000000..85dbde7 --- /dev/null +++ b/SOURCES/0153-ieee1275-powerpc-enables-device-mapper-discovery.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Mon, 14 Dec 2020 17:47:16 +0100 +Subject: [PATCH] ieee1275/powerpc: enables device mapper discovery + +this patch enables the device mapper discovery on ofpath.c. Currently, +when we are dealing with a device like /dev/dm-* the ofpath returns null +since there is no function implemented to handle this case. + +This patch implements a function that will look into /sys/block/dm-* +devices and search recursively inside slaves directory to find the root +disk. + +Signed-off-by: Diego Domingos +--- + grub-core/osdep/linux/ofpath.c | 64 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 63 insertions(+), 1 deletion(-) + +diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c +index 0f5d54e9f2..cc849d9c94 100644 +--- a/grub-core/osdep/linux/ofpath.c ++++ b/grub-core/osdep/linux/ofpath.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #ifdef __sparc__ + typedef enum +@@ -755,13 +756,74 @@ strip_trailing_digits (const char *p) + return new; + } + ++static char * ++get_slave_from_dm(const char * device){ ++ char *curr_device, *tmp; ++ char *directory; ++ char *ret = NULL; ++ ++ directory = grub_strdup (device); ++ tmp = get_basename(directory); ++ curr_device = grub_strdup (tmp); ++ *tmp = '\0'; ++ ++ /* Recursively check for slaves devices so we can find the root device */ ++ while ((curr_device[0] == 'd') && (curr_device[1] == 'm') && (curr_device[2] == '-')){ ++ DIR *dp; ++ struct dirent *ep; ++ char* device_path; ++ ++ device_path = grub_xasprintf ("/sys/block/%s/slaves", curr_device); ++ dp = opendir(device_path); ++ free(device_path); ++ ++ if (dp != NULL) ++ { ++ ep = readdir (dp); ++ while (ep != NULL){ ++ ++ /* avoid some system directories */ ++ if (!strcmp(ep->d_name,".")) ++ goto next_dir; ++ if (!strcmp(ep->d_name,"..")) ++ goto next_dir; ++ ++ free (curr_device); ++ free (ret); ++ curr_device = grub_strdup (ep->d_name); ++ ret = grub_xasprintf ("%s%s", directory, curr_device); ++ break; ++ ++ next_dir: ++ ep = readdir (dp); ++ continue; ++ } ++ closedir (dp); ++ } ++ else ++ grub_util_warn (_("cannot open directory `%s'"), device_path); ++ } ++ ++ free (directory); ++ free (curr_device); ++ ++ return ret; ++} ++ + char * + grub_util_devname_to_ofpath (const char *sys_devname) + { +- char *name_buf, *device, *devnode, *devicenode, *ofpath; ++ char *name_buf, *device, *devnode, *devicenode, *ofpath, *realname; + + name_buf = xrealpath (sys_devname); + ++ realname = get_slave_from_dm (name_buf); ++ if (realname) ++ { ++ free (name_buf); ++ name_buf = realname; ++ } ++ + device = get_basename (name_buf); + devnode = strip_trailing_digits (name_buf); + devicenode = strip_trailing_digits (device); diff --git a/SOURCES/0153-x86-efi-Reduce-maximum-bounce-buffer-size-to-16-MiB.patch b/SOURCES/0153-x86-efi-Reduce-maximum-bounce-buffer-size-to-16-MiB.patch deleted file mode 100644 index 825d0f7..0000000 --- a/SOURCES/0153-x86-efi-Reduce-maximum-bounce-buffer-size-to-16-MiB.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 26 May 2020 16:59:28 +0200 -Subject: [PATCH] x86-efi: Reduce maximum bounce buffer size to 16 MiB - -The EFI linux loader allocates a bounce buffer to copy the initrd since in -some machines doing DMA on addresses above 4GB is not possible during EFI. - -But the verifiers framework also allocates a buffer to copy the initrd in -its grub_file_open() handler. It does this since the data to verify has to -be passed as a single chunk to modules that use the verifiers framework. - -If the initrd image size is big there may not be enough memory in the heap -to allocate two buffers of that size. This causes an allocation failure in -the verifiers framework and leads to the initrd not being read. - -To prevent these allocation failures, let's reduce the maximum size of the -bounce buffer used in the EFI loader. Since the data read can be copied to -the actual initrd address in multilple chunks. - -Resolves: rhbz#1838633 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/loader/i386/efi/linux.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 6bc18d5aef5..15d40d6e35b 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -144,7 +144,7 @@ grub_linuxefi_unload (void) - return GRUB_ERR_NONE; - } - --#define BOUNCE_BUFFER_MAX 0x10000000ull -+#define BOUNCE_BUFFER_MAX 0x1000000ull - - static grub_ssize_t - read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) diff --git a/SOURCES/0154-Add-at_keyboard_fallback_set-var-to-force-the-set-ma.patch b/SOURCES/0154-Add-at_keyboard_fallback_set-var-to-force-the-set-ma.patch new file mode 100644 index 0000000..f938fd1 --- /dev/null +++ b/SOURCES/0154-Add-at_keyboard_fallback_set-var-to-force-the-set-ma.patch @@ -0,0 +1,245 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Fri, 18 Dec 2020 15:39:26 +0100 +Subject: [PATCH] Add 'at_keyboard_fallback_set' var to force the set manually +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This seems required with HP DL380p Gen 8 systems. +Indeed, with this system, we can see the following sequence: + +1. controller is queried to get current configuration (returns 0x30 which is quite standard) +2. controller is queried to get the current keyboard set in used, using code 0xf0 (first part) +3. controller answers with 0xfa which means "ACK" (== ok) +4. then we send "0" to tell "we want to know which set your are supporting" +5. controller answers with 0xfa ("ACK") +6. controller should then give us 1, 2, 3 or 0x43, 0x41, 0x3f, but here it gives us 0xfe which means "NACK" + +Since there seems no way to determine the current set, and in fact the +controller expects set2 to be used, we need to rely on an environment +variable. +Everything has been tested on this system: using 0xFE (resend command), +making sure we wait for ACK in the 2 steps "write_mode", etc. + +Below is litterature I used to come up with "there is no other +solution": +- https://wiki.osdev.org/%228042%22_PS/2_Controller +- http://www-ug.eecg.toronto.edu/msl/nios_devices/datasheets/PS2%20Keyboard%20Protocol.htm +- http://www.s100computers.com/My%20System%20Pages/MSDOS%20Board/PC%20Keyboard.pdf + +Signed-off-by: Renaud Métrich +Signed-off-by: Robbie Harwood +--- + grub-core/term/at_keyboard.c | 121 ++++++++++++++++++++++++++++++++++--------- + 1 file changed, 96 insertions(+), 25 deletions(-) + +diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c +index 2601438260..dac0f946fe 100644 +--- a/grub-core/term/at_keyboard.c ++++ b/grub-core/term/at_keyboard.c +@@ -31,6 +31,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + static grub_uint8_t grub_keyboard_controller_orig; + static grub_uint8_t grub_keyboard_orig_set; + struct grub_ps2_state ps2_state; ++static int fallback_set; + + static int ping_sent; + +@@ -76,6 +77,8 @@ at_command (grub_uint8_t data) + break; + return 0; + } ++ if (i == GRUB_AT_TRIES) ++ grub_dprintf ("atkeyb", "at_command() timed out! (stopped after %d tries)\n", i); + return (i != GRUB_AT_TRIES); + } + +@@ -105,6 +108,21 @@ grub_keyboard_controller_read (void) + + #endif + ++static int ++resend_last_result (void) ++{ ++ grub_uint8_t ret; ++ keyboard_controller_wait_until_ready (); ++ grub_dprintf ("atkeyb", "resend_last_result: sending 0xfe\n"); ++ grub_outb (0xfe, KEYBOARD_REG_DATA); ++ ret = wait_ack (); ++ grub_dprintf ("atkeyb", "resend_last_result: wait_ack() returned 0x%x\n", ret); ++ keyboard_controller_wait_until_ready (); ++ ret = grub_inb (KEYBOARD_REG_DATA); ++ grub_dprintf ("atkeyb", "resend_last_result: read 0x%x from controller\n", ret); ++ return ret; ++} ++ + static int + write_mode (int mode) + { +@@ -113,11 +131,14 @@ write_mode (int mode) + { + grub_uint8_t ack; + keyboard_controller_wait_until_ready (); ++ grub_dprintf ("atkeyb", "write_mode: sending 0xf0\n"); + grub_outb (0xf0, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); ++ grub_dprintf ("atkeyb", "write_mode: sending mode %d\n", mode); + grub_outb (mode, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + ack = wait_ack (); ++ grub_dprintf ("atkeyb", "write_mode: wait_ack() returned 0x%x\n", ack); + if (ack == GRUB_AT_NACK) + continue; + if (ack == GRUB_AT_ACK) +@@ -125,6 +146,9 @@ write_mode (int mode) + return 0; + } + ++ if (i == GRUB_AT_TRIES) ++ grub_dprintf ("atkeyb", "write_mode() timed out! (stopped after %d tries)\n", i); ++ + return (i != GRUB_AT_TRIES); + } + +@@ -132,31 +156,66 @@ static int + query_mode (void) + { + grub_uint8_t ret; ++ grub_uint64_t endtime; ++ unsigned i; + int e; ++ char *envvar; + +- e = write_mode (0); +- if (!e) { +- grub_dprintf("atkeyb", "query_mode: write_mode(0) failed\n"); +- return 0; +- } ++ for (i = 0; i < GRUB_AT_TRIES; i++) { ++ grub_dprintf ("atkeyb", "query_mode: sending command to controller\n"); ++ e = write_mode (0); ++ if (!e) { ++ grub_dprintf ("atkeyb", "query_mode: write_mode(0) failed\n"); ++ return 0; ++ } + +- do { +- keyboard_controller_wait_until_ready (); +- ret = grub_inb (KEYBOARD_REG_DATA); +- } while (ret == GRUB_AT_ACK); +- /* QEMU translates the set even in no-translate mode. */ +- if (ret == 0x43 || ret == 1) { +- grub_dprintf("atkeyb", "query_mode: returning 1 (ret=0x%x)\n", ret); +- return 1; +- } +- if (ret == 0x41 || ret == 2) { +- grub_dprintf("atkeyb", "query_mode: returning 2 (ret=0x%x)\n", ret); +- return 2; ++ endtime = grub_get_time_ms () + 20; ++ do { ++ keyboard_controller_wait_until_ready (); ++ ret = grub_inb (KEYBOARD_REG_DATA); ++ grub_dprintf ("atkeyb", "query_mode/loop: read 0x%x from controller\n", ret); ++ } while ((ret == GRUB_AT_ACK || ret == GRUB_AT_NACK) && grub_get_time_ms () < endtime); ++ if (ret == 0xfe) { ++ grub_dprintf ("atkeyb", "query_mode: asking controller to resend last result\n"); ++ ret = resend_last_result(); ++ grub_dprintf ("atkeyb", "query_mode: read 0x%x from controller\n", ret); ++ } ++ /* QEMU translates the set even in no-translate mode. */ ++ if (ret == 0x43 || ret == 1) { ++ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 1\n", ret); ++ return 1; ++ } ++ if (ret == 0x41 || ret == 2) { ++ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 2\n", ret); ++ return 2; ++ } ++ if (ret == 0x3f || ret == 3) { ++ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 3\n", ret); ++ return 3; ++ } ++ grub_dprintf ("atkeyb", "query_mode: controller returned unexpected value 0x%x, retrying\n", ret); + } +- if (ret == 0x3f || ret == 3) { +- grub_dprintf("atkeyb", "query_mode: returning 3 (ret=0x%x)\n", ret); +- return 3; ++ ++ /* ++ * Falling here means we tried querying and the controller returned something ++ * we don't understand, try to use 'at_keyboard_fallback_set' if it exists, ++ * otherwise return 0. ++ */ ++ envvar = grub_env_get ("at_keyboard_fallback_set"); ++ if (envvar) { ++ fallback_set = grub_strtoul (envvar, 0, 10); ++ if ((grub_errno) || (fallback_set < 1) || (fallback_set > 3)) { ++ grub_dprintf ("atkeyb", "WARNING: ignoring unexpected value '%s' for '%s' variable\n", ++ envvar, "at_keyboard_fallback_set"); ++ fallback_set = 0; ++ } else { ++ grub_dprintf ("atkeyb", "query_mode: '%s' specified in environment, returning %d\n", ++ "at_keyboard_fallback_set", fallback_set); ++ } ++ return fallback_set; + } ++ grub_dprintf ("atkeyb", "WARNING: no '%s' specified in environment, returning 0\n", ++ "at_keyboard_fallback_set"); + return 0; + } + +@@ -165,14 +224,25 @@ set_scancodes (void) + { + /* You must have visited computer museum. Keyboard without scancode set + knowledge. Assume XT. */ +- if (!grub_keyboard_orig_set) +- { +- grub_dprintf ("atkeyb", "No sets support assumed\n"); +- ps2_state.current_set = 1; ++ if (!grub_keyboard_orig_set) { ++ if (fallback_set) { ++ grub_dprintf ("atkeyb", "No sets support assumed but set forced to %d\n", fallback_set); ++ ps2_state.current_set = fallback_set; + return; + } ++ grub_dprintf ("atkeyb", "No sets support assumed, forcing to set 1\n"); ++ ps2_state.current_set = 1; ++ return; ++ } + + #if !USE_SCANCODE_SET ++ if (fallback_set) { ++ grub_dprintf ("atkeyb", "queried set is %d but set forced to %d\n", ++ grub_keyboard_orig_set, fallback_set); ++ ps2_state.current_set = fallback_set; ++ return; ++ } ++ + if ((grub_keyboard_controller_orig & KEYBOARD_AT_TRANSLATE) == KEYBOARD_AT_TRANSLATE) { + grub_dprintf ("atkeyb", "queried set is %d but keyboard in Translate mode, so actually in set 1\n", grub_keyboard_orig_set); + ps2_state.current_set = 1; +@@ -261,6 +331,7 @@ grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) + static void + grub_keyboard_controller_init (void) + { ++ grub_dprintf ("atkeyb", "initializing the controller\n"); + ps2_state.at_keyboard_status = 0; + /* Drain input buffer. */ + while (1) +@@ -282,6 +353,7 @@ grub_keyboard_controller_init (void) + grub_keyboard_controller_orig = grub_keyboard_controller_read (); + grub_dprintf ("atkeyb", "grub_keyboard_controller_orig = 0x%x\n", grub_keyboard_controller_orig); + grub_keyboard_orig_set = query_mode (); ++ grub_dprintf ("atkeyb", "grub_keyboard_orig_set = %d\n", grub_keyboard_orig_set); + #endif + set_scancodes (); + keyboard_controller_led (ps2_state.led_status); +@@ -329,7 +401,6 @@ grub_at_restore_hw (void) + return GRUB_ERR_NONE; + } + +- + static struct grub_term_input grub_at_keyboard_term = + { + .name = "at_keyboard", diff --git a/SOURCES/0154-http-Prepend-prefix-when-the-HTTP-path-is-relative-a.patch b/SOURCES/0154-http-Prepend-prefix-when-the-HTTP-path-is-relative-a.patch deleted file mode 100644 index 97d2e06..0000000 --- a/SOURCES/0154-http-Prepend-prefix-when-the-HTTP-path-is-relative-a.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 2 Jun 2020 13:25:01 +0200 -Subject: [PATCH] http: Prepend prefix when the HTTP path is relative as done - in efi/http - -There are two different HTTP drivers that can be used when requesting an -HTTP resource: the efi/http that uses the EFI_HTTP_PROTOCOL and the http -that uses GRUB's HTTP and TCP/IP implementation. - -The efi/http driver appends a prefix that is defined in the variable -http_path, but the http driver doesn't. - -So using this driver and attempting to fetch a resource using a relative -path fails. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/net/http.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index b52b558d631..7f878b56157 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -501,13 +501,20 @@ http_open (struct grub_file *file, const char *filename) - { - grub_err_t err; - struct http_data *data; -+ const char *http_path; - - data = grub_zalloc (sizeof (*data)); - if (!data) - return grub_errno; - file->size = GRUB_FILE_SIZE_UNKNOWN; - -- data->filename = grub_strdup (filename); -+ /* If path is relative, prepend http_path */ -+ http_path = grub_env_get ("http_path"); -+ if (http_path && filename[0] != '/') -+ data->filename = grub_xasprintf ("%s/%s", http_path, filename); -+ else -+ data->filename = grub_strdup (filename); -+ - if (!data->filename) - { - grub_free (data); diff --git a/SOURCES/0155-Add-suport-for-signing-grub-with-an-appended-signatu.patch b/SOURCES/0155-Add-suport-for-signing-grub-with-an-appended-signatu.patch new file mode 100644 index 0000000..81660d4 --- /dev/null +++ b/SOURCES/0155-Add-suport-for-signing-grub-with-an-appended-signatu.patch @@ -0,0 +1,309 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Rashmica Gupta +Date: Thu, 11 Jun 2020 11:26:23 +1000 +Subject: [PATCH] Add suport for signing grub with an appended signature + +Add infrastructure to allow firmware to verify the integrity of grub +by use of a Linux-kernel-module-style appended signature. We initially +target powerpc-ieee1275, but the code should be extensible to other +platforms. + +Usually these signatures are appended to a file without modifying the +ELF file itself. (This is what the 'sign-file' tool does, for example.) +The verifier loads the signed file from the file system and looks at the +end of the file for the appended signature. However, on powerpc-ieee1275 +platforms, the bootloader is often stored directly in the PReP partition +as raw bytes without a file-system. This makes determining the location +of an appended signature more difficult. + +To address this, we add a new ELF note. + +The name field of shall be the string "Appended-Signature", zero-padded +to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values +for the string "ASig"). It must be the final section in the ELF binary. + +The description shall contain the appended signature structure as defined +by the Linux kernel. The description will also be padded to be a multiple +of 4 bytes. The padding shall be added before the appended signature +structure (not at the end) so that the final bytes of a signed ELF file +are the appended signature magic. + +A subsequent patch documents how to create a grub core.img validly signed +under this scheme. + +Signed-off-by: Daniel Axtens +Signed-off-by: Rashmica Gupta +--- + util/grub-install-common.c | 18 ++++++++++++++---- + util/grub-mkimage.c | 15 +++++++++++++-- + util/grub-mkimagexx.c | 39 ++++++++++++++++++++++++++++++++++++++- + util/mkimage.c | 13 +++++++------ + include/grub/util/install.h | 8 ++++++-- + include/grub/util/mkimage.h | 4 ++-- + 6 files changed, 80 insertions(+), 17 deletions(-) + +diff --git a/util/grub-install-common.c b/util/grub-install-common.c +index 4e212e690c..a74fee16e2 100644 +--- a/util/grub-install-common.c ++++ b/util/grub-install-common.c +@@ -461,10 +461,12 @@ static size_t npubkeys; + static char *sbat; + static int disable_shim_lock; + static grub_compression_t compression; ++static size_t appsig_size; + + int + grub_install_parse (int key, char *arg) + { ++ const char *end; + switch (key) + { + case 'C': +@@ -562,6 +564,12 @@ grub_install_parse (int key, char *arg) + grub_util_error (_("Unrecognized compression `%s'"), arg); + case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE: + return 1; ++ case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE: ++ grub_errno = 0; ++ appsig_size = grub_strtol(arg, &end, 10); ++ if (grub_errno) ++ return 0; ++ return 1; + default: + return 0; + } +@@ -661,11 +669,13 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, + " --output '%s' " + " --dtb '%s' " + "--sbat '%s' " +- "--format '%s' --compression '%s' %s %s %s\n", ++ "--format '%s' --compression '%s' " ++ "--appended-signature-size %zu %s %s %s\n", + dir, prefix, + outname, dtb ? : "", sbat ? : "", mkimage_target, +- compnames[compression], note ? "--note" : "", +- disable_shim_lock ? "--disable-shim-lock" : "", s); ++ compnames[compression], appsig_size, ++ disable_shim_lock ? "--disable-shim-lock" : "", ++ note ? "--note" : "", s); + free (s); + + tgt = grub_install_get_image_target (mkimage_target); +@@ -675,7 +685,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, + grub_install_generate_image (dir, prefix, fp, outname, + modules.entries, memdisk_path, + pubkeys, npubkeys, config_path, tgt, +- note, compression, dtb, sbat, ++ note, appsig_size, compression, dtb, sbat, + disable_shim_lock); + while (dc--) + grub_install_pop_module (); +diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c +index c0d5599370..8a53310548 100644 +--- a/util/grub-mkimage.c ++++ b/util/grub-mkimage.c +@@ -84,6 +84,7 @@ static struct argp_option options[] = { + {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0}, + {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, ++ {"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0}, + { 0, 0, 0, 0, 0, 0 } + }; + +@@ -128,6 +129,7 @@ struct arguments + char *sbat; + int note; + int disable_shim_lock; ++ size_t appsig_size; + const struct grub_install_image_target_desc *image_target; + grub_compression_t comp; + }; +@@ -138,6 +140,7 @@ argp_parser (int key, char *arg, struct argp_state *state) + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; ++ const char* end; + + switch (key) + { +@@ -170,6 +173,13 @@ argp_parser (int key, char *arg, struct argp_state *state) + arguments->note = 1; + break; + ++ case 'S': ++ grub_errno = 0; ++ arguments->appsig_size = grub_strtol(arg, &end, 10); ++ if (grub_errno) ++ return 0; ++ break; ++ + case 'm': + if (arguments->memdisk) + free (arguments->memdisk); +@@ -324,8 +334,9 @@ main (int argc, char *argv[]) + arguments.memdisk, arguments.pubkeys, + arguments.npubkeys, arguments.config, + arguments.image_target, arguments.note, +- arguments.comp, arguments.dtb, +- arguments.sbat, arguments.disable_shim_lock); ++ arguments.appsig_size, arguments.comp, ++ arguments.dtb, arguments.sbat, ++ arguments.disable_shim_lock); + + if (grub_util_file_sync (fp) < 0) + grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout", +diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c +index d78fa3e533..393119486d 100644 +--- a/util/grub-mkimagexx.c ++++ b/util/grub-mkimagexx.c +@@ -84,6 +84,15 @@ struct grub_ieee1275_note + struct grub_ieee1275_note_desc descriptor; + }; + ++#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature" ++#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */ ++ ++struct grub_appended_signature_note ++{ ++ Elf32_Nhdr header; ++ char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)]; ++}; ++ + #define GRUB_XEN_NOTE_NAME "Xen" + + struct fixup_block_list +@@ -207,7 +216,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr) + + void + SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target, +- int note, char **core_img, size_t *core_size, ++ int note, size_t appsig_size, char **core_img, size_t *core_size, + Elf_Addr target_addr, + struct grub_mkimage_layout *layout) + { +@@ -221,6 +230,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc + int shnum = 4; + int string_size = sizeof (".text") + sizeof ("mods") + 1; + ++ if (appsig_size) ++ { ++ phnum++; ++ footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4); ++ } ++ + if (image_target->id != IMAGE_LOONGSON_ELF) + phnum += 2; + +@@ -484,6 +499,28 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc + phdr->p_offset = grub_host_to_target32 (header_size + program_size); + } + ++ if (appsig_size) { ++ int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4); ++ struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *) ++ (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0)); ++ ++ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME)); ++ /* needs to sit at the end, so we round this up and sign some zero padding */ ++ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4)); ++ note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE); ++ strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME); ++ ++ phdr++; ++ phdr->p_type = grub_host_to_target32 (PT_NOTE); ++ phdr->p_flags = grub_host_to_target32 (PF_R); ++ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof); ++ phdr->p_vaddr = 0; ++ phdr->p_paddr = 0; ++ phdr->p_filesz = grub_host_to_target32 (note_size); ++ phdr->p_memsz = 0; ++ phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0)); ++ } ++ + { + char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr) + + shnum * sizeof (*shdr)); +diff --git a/util/mkimage.c b/util/mkimage.c +index a26cf76f72..bab1227601 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -869,8 +869,9 @@ grub_install_generate_image (const char *dir, const char *prefix, + char *memdisk_path, char **pubkey_paths, + size_t npubkeys, char *config_path, + const struct grub_install_image_target_desc *image_target, +- int note, grub_compression_t comp, const char *dtb_path, +- const char *sbat_path, int disable_shim_lock) ++ int note, size_t appsig_size, grub_compression_t comp, ++ const char *dtb_path, const char *sbat_path, ++ int disable_shim_lock) + { + char *kernel_img, *core_img; + size_t total_module_size, core_size; +@@ -1773,11 +1774,11 @@ grub_install_generate_image (const char *dir, const char *prefix, + else + target_addr = image_target->link_addr; + if (image_target->voidp_sizeof == 4) +- grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size, +- target_addr, &layout); ++ grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img, ++ &core_size, target_addr, &layout); + else +- grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size, +- target_addr, &layout); ++ grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img, ++ &core_size, target_addr, &layout); + } + break; + } +diff --git a/include/grub/util/install.h b/include/grub/util/install.h +index 7df3191f47..cf4531e02b 100644 +--- a/include/grub/util/install.h ++++ b/include/grub/util/install.h +@@ -67,6 +67,9 @@ + N_("SBAT metadata"), 0 }, \ + { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \ + N_("disable shim_lock verifier"), 0 }, \ ++ { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\ ++ "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \ ++ 1}, \ + { "verbose", 'v', 0, 0, \ + N_("print verbose messages."), 1 } + +@@ -128,7 +131,8 @@ enum grub_install_options { + GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS, + GRUB_INSTALL_OPTIONS_DTB, + GRUB_INSTALL_OPTIONS_SBAT, +- GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK ++ GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, ++ GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE + }; + + extern char *grub_install_source_directory; +@@ -188,7 +192,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + size_t npubkeys, + char *config_path, + const struct grub_install_image_target_desc *image_target, +- int note, ++ int note, size_t appsig_size, + grub_compression_t comp, const char *dtb_file, + const char *sbat_path, const int disable_shim_lock); + +diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h +index 3819a67441..6f1da89b9b 100644 +--- a/include/grub/util/mkimage.h ++++ b/include/grub/util/mkimage.h +@@ -51,12 +51,12 @@ grub_mkimage_load_image64 (const char *kernel_path, + const struct grub_install_image_target_desc *image_target); + void + grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target, +- int note, char **core_img, size_t *core_size, ++ int note, size_t appsig_size, char **core_img, size_t *core_size, + Elf32_Addr target_addr, + struct grub_mkimage_layout *layout); + void + grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target, +- int note, char **core_img, size_t *core_size, ++ int note, size_t appsig_size, char **core_img, size_t *core_size, + Elf64_Addr target_addr, + struct grub_mkimage_layout *layout); + diff --git a/SOURCES/0155-Fix-a-missing-return-in-efi-export-env-and-efi-load-.patch b/SOURCES/0155-Fix-a-missing-return-in-efi-export-env-and-efi-load-.patch deleted file mode 100644 index 1657d7a..0000000 --- a/SOURCES/0155-Fix-a-missing-return-in-efi-export-env-and-efi-load-.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 16 Jan 2019 13:21:46 -0500 -Subject: [PATCH] Fix a missing return in efi-export-env and efi-load-env - commands - -Somewhere along the way this got mis-merged to include a return without -a value. Fix it up. - -Signed-off-by: Peter Jones ---- - grub-core/commands/efi/env.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/grub-core/commands/efi/env.c b/grub-core/commands/efi/env.c -index cbd13e03e81..977edb6b065 100644 ---- a/grub-core/commands/efi/env.c -+++ b/grub-core/commands/efi/env.c -@@ -149,6 +149,8 @@ grub_efi_load_env(grub_command_t cmd __attribute__ ((unused)), - - grub_envblk_iterate (envblk, NULL, set_var); - grub_free (envblk_s.buf); -+ -+ return GRUB_ERR_NONE; - } - - static grub_command_t export_cmd, loadenv_cmd; diff --git a/SOURCES/0156-docs-grub-Document-signing-grub-under-UEFI.patch b/SOURCES/0156-docs-grub-Document-signing-grub-under-UEFI.patch new file mode 100644 index 0000000..f2b5c17 --- /dev/null +++ b/SOURCES/0156-docs-grub-Document-signing-grub-under-UEFI.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Sat, 15 Aug 2020 02:00:57 +1000 +Subject: [PATCH] docs/grub: Document signing grub under UEFI + +Before adding information about how grub is signed with an appended +signature scheme, it's worth adding some information about how it +can currently be signed for UEFI. + +Signed-off-by: Daniel Axtens +--- + docs/grub.texi | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/docs/grub.texi b/docs/grub.texi +index 4870faaa00..365d1d6931 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -5817,6 +5817,7 @@ environment variables and commands are listed in the same order. + * Secure Boot Advanced Targeting:: Embedded information for generation number based revocation + * Measured Boot:: Measuring boot components + * Lockdown:: Lockdown when booting on a secure setup ++* Signing GRUB itself:: Ensuring the integrity of the GRUB core image + @end menu + + @node Authentication and authorisation +@@ -5895,7 +5896,7 @@ commands. + + GRUB's @file{core.img} can optionally provide enforcement that all files + subsequently read from disk are covered by a valid digital signature. +-This document does @strong{not} cover how to ensure that your ++This section does @strong{not} cover how to ensure that your + platform's firmware (e.g., Coreboot) validates @file{core.img}. + + If environment variable @code{check_signatures} +@@ -6067,6 +6068,25 @@ be restricted and some operations/commands cannot be executed. + The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down. + Otherwise it does not exit. + ++@node Signing GRUB itself ++@section Signing GRUB itself ++ ++To ensure a complete secure-boot chain, there must be a way for the code that ++loads GRUB to verify the integrity of the core image. ++ ++This is ultimately platform-specific and individual platforms can define their ++own mechanisms. However, there are general-purpose mechanisms that can be used ++with GRUB. ++ ++@section Signing GRUB for UEFI secure boot ++ ++On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed ++with a tool such as @command{pesign} or @command{sbsign}. Refer to the ++suggestions in @pxref{UEFI secure boot and shim} to ensure that the final ++image works under UEFI secure boot and can maintain the secure-boot chain. It ++will also be necessary to enrol the public key used into a relevant firmware ++key database. ++ + @node Platform limitations + @chapter Platform limitations + diff --git a/SOURCES/0156-efi-dhcp-fix-some-allocation-error-checking.patch b/SOURCES/0156-efi-dhcp-fix-some-allocation-error-checking.patch deleted file mode 100644 index 7549733..0000000 --- a/SOURCES/0156-efi-dhcp-fix-some-allocation-error-checking.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Sun, 19 Jul 2020 17:11:06 -0400 -Subject: [PATCH] efi+dhcp: fix some allocation error checking. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/dhcp.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c -index dbef63d8c08..e5c79b748b0 100644 ---- a/grub-core/net/efi/dhcp.c -+++ b/grub-core/net/efi/dhcp.c -@@ -80,7 +80,7 @@ grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packe - if (status != GRUB_EFI_BUFFER_TOO_SMALL) - return NULL; - -- option_list = grub_malloc (option_count * sizeof(*option_list)); -+ option_list = grub_calloc (option_count, sizeof(*option_list)); - if (!option_list) - return NULL; - -@@ -360,8 +360,11 @@ grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)), - - if (status == GRUB_EFI_BUFFER_TOO_SMALL && count) - { -- options = grub_malloc (count * sizeof(*options)); -- status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options); -+ options = grub_calloc (count, sizeof(*options)); -+ if (options) -+ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options); -+ else -+ status = GRUB_EFI_OUT_OF_RESOURCES; - } - - if (status != GRUB_EFI_SUCCESS) diff --git a/SOURCES/0157-docs-grub-Document-signing-grub-with-an-appended-sig.patch b/SOURCES/0157-docs-grub-Document-signing-grub-with-an-appended-sig.patch new file mode 100644 index 0000000..ee3d659 --- /dev/null +++ b/SOURCES/0157-docs-grub-Document-signing-grub-with-an-appended-sig.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Sat, 15 Aug 2020 02:19:36 +1000 +Subject: [PATCH] docs/grub: Document signing grub with an appended signature + +Signing grub for firmware that verifies an appended signature is a +bit fiddly. I don't want people to have to figure it out from scratch +so document it here. + +Signed-off-by: Daniel Axtens +--- + docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/docs/grub.texi b/docs/grub.texi +index 365d1d6931..afbde7c1f7 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -6087,6 +6087,48 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It + will also be necessary to enrol the public key used into a relevant firmware + key database. + ++@section Signing GRUB with an appended signature ++ ++The @file{core.elf} itself can be signed with a Linux kernel module-style ++appended signature. ++ ++To support IEEE1275 platforms where the boot image is often loaded directly ++from a disk partition rather than from a file system, the @file{core.elf} ++can specify the size and location of the appended signature with an ELF ++note added by @command{grub-install}. ++ ++An image can be signed this way using the @command{sign-file} command from ++the Linux kernel: ++ ++@example ++@group ++# grub.key is your private key and certificate.der is your public key ++ ++# Determine the size of the appended signature. It depends on the signing ++# certificate and the hash algorithm ++touch empty ++sign-file SHA256 grub.key certificate.der empty empty.sig ++SIG_SIZE=`stat -c '%s' empty.sig` ++rm empty empty.sig ++ ++# Build a grub image with $SIG_SIZE reserved for the signature ++grub-install --appended-signature-size $SIG_SIZE --modules="..." ... ++ ++# Replace the reserved size with a signature: ++# cut off the last $SIG_SIZE bytes with truncate's minus modifier ++truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned ++# sign the trimmed file with an appended signature, restoring the correct size ++sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed ++ ++# Don't forget to install the signed image as required ++# (e.g. on powerpc-ieee1275, to the PReP partition) ++@end group ++@end example ++ ++As with UEFI secure boot, it is necessary to build in the required modules, ++or sign them separately. ++ ++ + @node Platform limitations + @chapter Platform limitations + diff --git a/SOURCES/0157-efi-http-fix-some-allocation-error-checking.patch b/SOURCES/0157-efi-http-fix-some-allocation-error-checking.patch deleted file mode 100644 index 4dffab9..0000000 --- a/SOURCES/0157-efi-http-fix-some-allocation-error-checking.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Sun, 19 Jul 2020 17:14:15 -0400 -Subject: [PATCH] efi+http: fix some allocation error checking. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/http.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c -index fc8cb25ae0a..26647a50fa4 100644 ---- a/grub-core/net/efi/http.c -+++ b/grub-core/net/efi/http.c -@@ -412,8 +412,8 @@ grub_efihttp_open (struct grub_efi_net_device *dev, - int type) - { - grub_err_t err; -- grub_off_t size; -- char *buf; -+ grub_off_t size = 0; -+ char *buf = NULL; - char *file_name = NULL; - const char *http_path; - -@@ -441,8 +441,11 @@ grub_efihttp_open (struct grub_efi_net_device *dev, - return err; - } - -- buf = grub_malloc (size); -- efihttp_read (dev, buf, size); -+ if (size) -+ { -+ buf = grub_malloc (size); -+ efihttp_read (dev, buf, size); -+ } - - file->size = size; - file->data = buf; diff --git a/SOURCES/0158-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch b/SOURCES/0158-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch new file mode 100644 index 0000000..b23ce49 --- /dev/null +++ b/SOURCES/0158-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 30 Jul 2020 00:13:21 +1000 +Subject: [PATCH] dl: provide a fake grub_dl_set_persistent for the emu target + +Trying to start grub-emu with a module that calls grub_dl_set_persistent +will crash because grub-emu fakes modules and passes NULL to the module +init function. + +Provide an empty function for the emu case. + +Fixes: ee7808e2197c (dl: Add support for persistent modules) +Signed-off-by: Daniel Axtens +--- + include/grub/dl.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 2f76e6b043..20d870f2a4 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -245,11 +245,22 @@ grub_dl_get (const char *name) + return 0; + } + ++#ifdef GRUB_MACHINE_EMU ++/* ++ * Under grub-emu, modules are faked and NULL is passed to GRUB_MOD_INIT. ++ * So we fake this out to avoid a NULL deref. ++ */ ++static inline void ++grub_dl_set_persistent (grub_dl_t mod __attribute__((unused))) ++{ ++} ++#else + static inline void + grub_dl_set_persistent (grub_dl_t mod) + { + mod->persistent = 1; + } ++#endif + + static inline int + grub_dl_is_persistent (grub_dl_t mod) diff --git a/SOURCES/0158-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch b/SOURCES/0158-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch deleted file mode 100644 index 30c21a5..0000000 --- a/SOURCES/0158-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Sun, 19 Jul 2020 17:27:00 -0400 -Subject: [PATCH] efi/ip[46]_config.c: fix some potential allocation overflows - -In theory all of this data comes from the firmware stack and it should -be safe, but it's better to be paranoid. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/ip4_config.c | 25 ++++++++++++++++++------- - grub-core/net/efi/ip6_config.c | 13 ++++++++++--- - 2 files changed, 28 insertions(+), 10 deletions(-) - -diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c -index 313c818b184..9725e928f7e 100644 ---- a/grub-core/net/efi/ip4_config.c -+++ b/grub-core/net/efi/ip4_config.c -@@ -4,15 +4,20 @@ - #include - #include - #include -+#include - - char * - grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address) - { - char *hw_addr, *p; -- int sz, s; -- int i; -+ grub_size_t sz, s, i; - -- sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1; -+ if (grub_mul (hw_address_size, sizeof ("XX:") - 1, &sz) || -+ grub_add (sz, 1, &sz)) -+ { -+ grub_errno = GRUB_ERR_OUT_OF_RANGE; -+ return NULL; -+ } - - hw_addr = grub_malloc (sz); - if (!hw_addr) -@@ -20,7 +25,7 @@ grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_a - - p = hw_addr; - s = sz; -- for (i = 0; i < (int)hw_address_size; i++) -+ for (i = 0; i < hw_address_size; i++) - { - grub_snprintf (p, sz, "%02x:", hw_address[i]); - p += sizeof ("XX:") - 1; -@@ -238,14 +243,20 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev) - { - grub_efi_ip4_config2_interface_info_t *interface_info; - char **ret; -- int i, id; -+ int id; -+ grub_size_t i, nmemb; - - interface_info = efi_ip4_config_interface_info (dev->ip4_config); - if (!interface_info) - return NULL; - -- ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1)); -+ if (grub_add (interface_info->route_table_size, 1, &nmemb)) -+ { -+ grub_errno = GRUB_ERR_OUT_OF_RANGE; -+ return NULL; -+ } - -+ ret = grub_calloc (nmemb, sizeof (*ret)); - if (!ret) - { - grub_free (interface_info); -@@ -253,7 +264,7 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev) - } - - id = 0; -- for (i = 0; i < (int)interface_info->route_table_size; i++) -+ for (i = 0; i < interface_info->route_table_size; i++) - { - char *subnet, *gateway, *mask; - grub_uint32_t u32_subnet, u32_gateway; -diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c -index 017c4d05bc7..a46f6f9b685 100644 ---- a/grub-core/net/efi/ip6_config.c -+++ b/grub-core/net/efi/ip6_config.c -@@ -3,6 +3,7 @@ - #include - #include - #include -+#include - - char * - grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address) -@@ -228,14 +229,20 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev) - { - grub_efi_ip6_config_interface_info_t *interface_info; - char **ret; -- int i, id; -+ int id; -+ grub_size_t i, nmemb; - - interface_info = efi_ip6_config_interface_info (dev->ip6_config); - if (!interface_info) - return NULL; - -- ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1)); -+ if (grub_add (interface_info->route_count, 1, &nmemb)) -+ { -+ grub_errno = GRUB_ERR_OUT_OF_RANGE; -+ return NULL; -+ } - -+ ret = grub_calloc (nmemb, sizeof (*ret)); - if (!ret) - { - grub_free (interface_info); -@@ -243,7 +250,7 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev) - } - - id = 0; -- for (i = 0; i < (int)interface_info->route_count ; i++) -+ for (i = 0; i < interface_info->route_count ; i++) - { - char *gateway, *destination; - grub_uint64_t u64_gateway[2]; diff --git a/SOURCES/0159-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch b/SOURCES/0159-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch deleted file mode 100644 index 95f7e20..0000000 --- a/SOURCES/0159-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Colin Watson -Date: Fri, 24 Jul 2020 17:18:09 +0100 -Subject: [PATCH] efilinux: Fix integer overflows in grub_cmd_initrd - -These could be triggered by an extremely large number of arguments to -the initrd command on 32-bit architectures, or a crafted filesystem with -very large files on any architecture. - -Signed-off-by: Colin Watson ---- - grub-core/loader/i386/efi/linux.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 15d40d6e35b..f992ceeef20 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -28,6 +28,8 @@ - #include - #include - #include -+#include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -206,7 +208,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- files = grub_zalloc (argc * sizeof (files[0])); -+ files = grub_calloc (argc, sizeof (files[0])); - if (!files) - goto fail; - -@@ -216,7 +218,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - if (! files[i]) - goto fail; - nfiles++; -- size += ALIGN_UP (grub_file_size (files[i]), 4); -+ if (grub_add (size, ALIGN_UP (grub_file_size (files[i]), 4), &size)) -+ { -+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); -+ goto fail; -+ } - } - - initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); diff --git a/SOURCES/0159-pgp-factor-out-rsa_pad.patch b/SOURCES/0159-pgp-factor-out-rsa_pad.patch new file mode 100644 index 0000000..43fd882 --- /dev/null +++ b/SOURCES/0159-pgp-factor-out-rsa_pad.patch @@ -0,0 +1,191 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 1 Oct 2020 20:23:48 +1000 +Subject: [PATCH] pgp: factor out rsa_pad + +rsa_pad does the PKCS#1 v1.5 padding for the RSA signature scheme. +We want to use it in other RSA signature verification applications. + +I considered and rejected putting it in lib/crypto.c. That file doesn't +currently require any MPI functions, but rsa_pad does. That's not so +much of a problem for the grub kernel and modules, but crypto.c also +gets built into all the grub utilities. So - despite the utils not +using any asymmetric ciphers - we would need to built the entire MPI +infrastructure in to them. + +A better and simpler solution is just to spin rsa_pad out into its own +PKCS#1 v1.5 module. + +Signed-off-by: Daniel Axtens +--- + grub-core/Makefile.core.def | 8 ++++++ + grub-core/commands/pgp.c | 28 ++------------------- + grub-core/lib/pkcs1_v15.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ + include/grub/pkcs1_v15.h | 27 +++++++++++++++++++++ + 4 files changed, 96 insertions(+), 26 deletions(-) + create mode 100644 grub-core/lib/pkcs1_v15.c + create mode 100644 include/grub/pkcs1_v15.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index dc9fea6f44..64cc758835 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2511,6 +2511,14 @@ module = { + cppflags = '$(CPPFLAGS_GCRY)'; + }; + ++module = { ++ name = pkcs1_v15; ++ common = lib/pkcs1_v15.c; ++ ++ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; ++ cppflags = '$(CPPFLAGS_GCRY)'; ++}; ++ + module = { + name = all_video; + common = lib/fake_module.c; +diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c +index 5daa1e9d00..2408db4994 100644 +--- a/grub-core/commands/pgp.c ++++ b/grub-core/commands/pgp.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -411,32 +412,7 @@ static int + rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk) + { +- grub_size_t tlen, emlen, fflen; +- grub_uint8_t *em, *emptr; +- unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]); +- int ret; +- tlen = hash->mdlen + hash->asnlen; +- emlen = (nbits + 7) / 8; +- if (emlen < tlen + 11) +- return 1; +- +- em = grub_malloc (emlen); +- if (!em) +- return 1; +- +- em[0] = 0x00; +- em[1] = 0x01; +- fflen = emlen - tlen - 3; +- for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) +- *emptr = 0xff; +- *emptr++ = 0x00; +- grub_memcpy (emptr, hash->asnoid, hash->asnlen); +- emptr += hash->asnlen; +- grub_memcpy (emptr, hval, hash->mdlen); +- +- ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); +- grub_free (em); +- return ret; ++ return grub_crypto_rsa_pad(hmpi, hval, hash, sk->mpis[0]); + } + + struct grub_pubkey_context +diff --git a/grub-core/lib/pkcs1_v15.c b/grub-core/lib/pkcs1_v15.c +new file mode 100644 +index 0000000000..dbacd563d0 +--- /dev/null ++++ b/grub-core/lib/pkcs1_v15.c +@@ -0,0 +1,59 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2013 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++/* ++ * Given a hash value 'hval', of hash specification 'hash', perform ++ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod' ++ * (see RFC 8017 s 9.2) and place the result in 'hmpi'. ++ */ ++gcry_err_code_t ++grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval, ++ const gcry_md_spec_t * hash, gcry_mpi_t mod) ++{ ++ grub_size_t tlen, emlen, fflen; ++ grub_uint8_t *em, *emptr; ++ unsigned nbits = gcry_mpi_get_nbits (mod); ++ int ret; ++ tlen = hash->mdlen + hash->asnlen; ++ emlen = (nbits + 7) / 8; ++ if (emlen < tlen + 11) ++ return GPG_ERR_TOO_SHORT; ++ ++ em = grub_malloc (emlen); ++ if (!em) ++ return 1; ++ ++ em[0] = 0x00; ++ em[1] = 0x01; ++ fflen = emlen - tlen - 3; ++ for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) ++ *emptr = 0xff; ++ *emptr++ = 0x00; ++ grub_memcpy (emptr, hash->asnoid, hash->asnlen); ++ emptr += hash->asnlen; ++ grub_memcpy (emptr, hval, hash->mdlen); ++ ++ ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); ++ grub_free (em); ++ return ret; ++} +diff --git a/include/grub/pkcs1_v15.h b/include/grub/pkcs1_v15.h +new file mode 100644 +index 0000000000..5c338c84a1 +--- /dev/null ++++ b/include/grub/pkcs1_v15.h +@@ -0,0 +1,27 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2013 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++/* ++ * Given a hash value 'hval', of hash specification 'hash', perform ++ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod' ++ * (See RFC 8017 s 9.2) ++ */ ++gcry_err_code_t ++grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval, ++ const gcry_md_spec_t * hash, gcry_mpi_t mod); ++ diff --git a/SOURCES/0160-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch b/SOURCES/0160-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch new file mode 100644 index 0000000..541474e --- /dev/null +++ b/SOURCES/0160-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 2 Oct 2020 10:49:26 +1000 +Subject: [PATCH] crypto: move storage for grub_crypto_pk_* to crypto.c + +The way gcry_rsa and friends (the asymmetric ciphers) are loaded for the +pgp module is a bit quirky. + +include/grub/crypto.h contains: + extern struct gcry_pk_spec *grub_crypto_pk_rsa; + +commands/pgp.c contains the actual storage: + struct gcry_pk_spec *grub_crypto_pk_rsa; + +And the module itself saves to the storage in pgp.c: + GRUB_MOD_INIT(gcry_rsa) + { + grub_crypto_pk_rsa = &_gcry_pubkey_spec_rsa; + } + +This is annoying: gcry_rsa now has a dependency on pgp! + +We want to be able to bring in gcry_rsa without bringing in PGP, +so move the storage to crypto.c. + +Previously, gcry_rsa depended on pgp and mpi. Now it depends on +crypto and mpi. As pgp depends on crypto, this doesn't add any new +module dependencies using the PGP verfier. + +[FWIW, the story is different for the symmetric ciphers. cryptodisk +and friends (zfs encryption etc) use grub_crypto_lookup_cipher_by_name() +to get a cipher handle. That depends on grub_ciphers being populated +by people calling grub_cipher_register. import_gcry.py ensures that the +symmetric ciphers call it.] + +Signed-off-by: Daniel Axtens +--- + grub-core/commands/pgp.c | 4 ---- + grub-core/lib/crypto.c | 4 ++++ + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c +index 2408db4994..355a43844a 100644 +--- a/grub-core/commands/pgp.c ++++ b/grub-core/commands/pgp.c +@@ -147,10 +147,6 @@ const char *hashes[] = { + [0x0b] = "sha224" + }; + +-struct gcry_pk_spec *grub_crypto_pk_dsa; +-struct gcry_pk_spec *grub_crypto_pk_ecdsa; +-struct gcry_pk_spec *grub_crypto_pk_rsa; +- + static int + dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk); +diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c +index ca334d5a40..c578128a59 100644 +--- a/grub-core/lib/crypto.c ++++ b/grub-core/lib/crypto.c +@@ -121,6 +121,10 @@ grub_md_unregister (gcry_md_spec_t *cipher) + } + } + ++struct gcry_pk_spec *grub_crypto_pk_dsa; ++struct gcry_pk_spec *grub_crypto_pk_ecdsa; ++struct gcry_pk_spec *grub_crypto_pk_rsa; ++ + void + grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, + grub_size_t inlen) diff --git a/SOURCES/0160-linuxefi-fail-kernel-validation-without-shim-protoco.patch b/SOURCES/0160-linuxefi-fail-kernel-validation-without-shim-protoco.patch deleted file mode 100644 index 20fc786..0000000 --- a/SOURCES/0160-linuxefi-fail-kernel-validation-without-shim-protoco.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dimitri John Ledkov -Date: Wed, 22 Jul 2020 11:31:43 +0100 -Subject: [PATCH] linuxefi: fail kernel validation without shim protocol. - -If certificates that signed grub are installed into db, grub can be -booted directly. It will then boot any kernel without signature -validation. The booted kernel will think it was booted in secureboot -mode and will implement lockdown, yet it could have been tampered. - -This version of the patch skips calling verification, when booted -without secureboot. And is indented with gnu ident. - -CVE-2020-15705 - -Reported-by: Mathieu Trudel-Lapierre -Signed-off-by: Dimitri John Ledkov ---- - grub-core/loader/arm64/linux.c | 13 +++++++++---- - grub-core/loader/efi/chainloader.c | 1 + - grub-core/loader/efi/linux.c | 1 + - grub-core/loader/i386/efi/linux.c | 17 +++++++++++------ - 4 files changed, 22 insertions(+), 10 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index 70a0075ec5e..47f8cf0d84b 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -363,11 +364,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); - -- rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); -- if (rc < 0) -+ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) - { -- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); -- goto fail; -+ rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); -+ if (rc <= 0) -+ { -+ grub_error (GRUB_ERR_INVALID_COMMAND, -+ N_("%s has invalid signature"), argv[0]); -+ goto fail; -+ } - } - - pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index ac8dfd40c61..d41e8ea14a8 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -1084,6 +1084,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - - return 0; - } -+ // -1 fall-through to fail - - fail: - if (dev) -diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c -index e8b9ecb17f6..9260731c107 100644 ---- a/grub-core/loader/efi/linux.c -+++ b/grub-core/loader/efi/linux.c -@@ -33,6 +33,7 @@ struct grub_efi_shim_lock - }; - typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; - -+// Returns 1 on success, -1 on error, 0 when not available - int - grub_linuxefi_secure_validate (void *data, grub_uint32_t size) - { -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index f992ceeef20..3cf0f9b330b 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -101,7 +102,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) - - pages = BYTES_TO_PAGES(size); - grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", -- pages, (void *)max); -+ (unsigned long)pages, (void *)(unsigned long)max); - - prev_max = max; - addr = grub_efi_allocate_pages_real (max, pages, -@@ -307,12 +308,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- rc = grub_linuxefi_secure_validate (kernel, filelen); -- if (rc < 0) -+ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) - { -- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), -- argv[0]); -- goto fail; -+ rc = grub_linuxefi_secure_validate (kernel, filelen); -+ if (rc <= 0) -+ { -+ grub_error (GRUB_ERR_INVALID_COMMAND, -+ N_("%s has invalid signature"), argv[0]); -+ goto fail; -+ } - } - - lh = (struct linux_i386_kernel_header *)kernel; -@@ -386,6 +390,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); - grub_dprintf ("linux", "copying %lu bytes from %p to %p\n", -+ (unsigned long) - MIN((grub_size_t)0x202+setup_header_end_offset, - sizeof (*params)) - 0x1f1, - (grub_uint8_t *)kernel + 0x1f1, diff --git a/SOURCES/0161-Fix-const-char-pointers-in-grub-core-net-bootp.c.patch b/SOURCES/0161-Fix-const-char-pointers-in-grub-core-net-bootp.c.patch deleted file mode 100644 index 9b0db5f..0000000 --- a/SOURCES/0161-Fix-const-char-pointers-in-grub-core-net-bootp.c.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 20 Jul 2020 12:24:02 -0400 -Subject: [PATCH] Fix const char ** pointers in grub-core/net/bootp.c - -This will need to get folded back in the right place on the next rebase, -but it's before "Make grub_strtol() "end" pointers have safer const -qualifiers" currently, so for now I'm leaving it here instead of merging -it back with the original patch. - -Signed-off-by: Peter Jones ---- - grub-core/net/bootp.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c -index 8fb8918ae7e..7baf3540c81 100644 ---- a/grub-core/net/bootp.c -+++ b/grub-core/net/bootp.c -@@ -329,7 +329,7 @@ grub_net_configure_by_dhcp_ack (const char *name, - struct grub_net_network_level_interface *inter; - int mask = -1; - char server_ip[sizeof ("xxx.xxx.xxx.xxx")]; -- const grub_uint8_t *opt; -+ const char *opt; - grub_uint8_t opt_len, overload = 0; - const char *boot_file = 0, *server_name = 0; - grub_size_t boot_file_len, server_name_len; -@@ -505,7 +505,7 @@ grub_net_configure_by_dhcp_ack (const char *name, - if (opt && opt_len) - { - grub_env_set_net_property (name, "vendor_class_identifier", (const char *) opt, opt_len); -- if (opt && grub_strcmp (opt, "HTTPClient") == 0) -+ if (opt && grub_strcmp ((char *)opt, "HTTPClient") == 0) - { - char *proto, *ip, *pa; - diff --git a/SOURCES/0161-posix_wrap-tweaks-in-preparation-for-libtasn1.patch b/SOURCES/0161-posix_wrap-tweaks-in-preparation-for-libtasn1.patch new file mode 100644 index 0000000..3176f1b --- /dev/null +++ b/SOURCES/0161-posix_wrap-tweaks-in-preparation-for-libtasn1.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Sat, 2 May 2020 00:27:57 +1000 +Subject: [PATCH] posix_wrap: tweaks in preparation for libtasn1 + + - Define SIZEOF_UNSIGNED_LONG_INT, it's the same as + SIZEOF_UNSIGNED_LONG. + + - Define WORD_BIT, the size in bits of an int. This is a defined + in the Single Unix Specification and in gnulib's limits.h. gnulib + assumes it's 32 bits on all our platforms, including 64 bit + platforms, so we also use that value. + + - Provide strto[u]l[l] preprocessor macros that resolve to + grub_strto[u]l[l]. To avoid gcrypt redefining strtoul, we + also define HAVE_STRTOUL here. + +Signed-off-by: Daniel Axtens +--- + grub-core/lib/posix_wrap/limits.h | 1 + + grub-core/lib/posix_wrap/stdlib.h | 8 ++++++++ + grub-core/lib/posix_wrap/sys/types.h | 1 + + 3 files changed, 10 insertions(+) + +diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h +index 7217138ffd..591dbf3289 100644 +--- a/grub-core/lib/posix_wrap/limits.h ++++ b/grub-core/lib/posix_wrap/limits.h +@@ -37,5 +37,6 @@ + #define LONG_MAX GRUB_LONG_MAX + + #define CHAR_BIT 8 ++#define WORD_BIT 32 + + #endif +diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h +index 7a8d385e97..4634db09f2 100644 +--- a/grub-core/lib/posix_wrap/stdlib.h ++++ b/grub-core/lib/posix_wrap/stdlib.h +@@ -58,4 +58,12 @@ abs (int c) + return (c >= 0) ? c : -c; + } + ++#define strtol grub_strtol ++ ++/* for libgcrypt */ ++#define HAVE_STRTOUL ++#define strtoul grub_strtoul ++ ++#define strtoull grub_strtoull ++ + #endif +diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h +index 854eb0122e..f63412c8da 100644 +--- a/grub-core/lib/posix_wrap/sys/types.h ++++ b/grub-core/lib/posix_wrap/sys/types.h +@@ -51,6 +51,7 @@ typedef grub_uint8_t byte; + typedef grub_addr_t uintptr_t; + + #define SIZEOF_UNSIGNED_LONG GRUB_CPU_SIZEOF_LONG ++#define SIZEOF_UNSIGNED_LONG_INT GRUB_CPU_SIZEOF_LONG + #define SIZEOF_UNSIGNED_INT 4 + #define SIZEOF_UNSIGNED_LONG_LONG 8 + #define SIZEOF_UNSIGNED_SHORT 2 diff --git a/SOURCES/0162-Fix-const-char-pointers-in-grub-core-net-efi-ip4_con.patch b/SOURCES/0162-Fix-const-char-pointers-in-grub-core-net-efi-ip4_con.patch deleted file mode 100644 index 6c16e9e..0000000 --- a/SOURCES/0162-Fix-const-char-pointers-in-grub-core-net-efi-ip4_con.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 20 Jul 2020 12:24:02 -0400 -Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/ip4_config.c - -This will need to get folded back in the right place on the next rebase, -but it's before "Make grub_strtol() "end" pointers have safer const -qualifiers" currently, so for now I'm leaving it here instead of merging -it back with the original patch. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/ip4_config.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c -index 9725e928f7e..cb880fc3e8f 100644 ---- a/grub-core/net/efi/ip4_config.c -+++ b/grub-core/net/efi/ip4_config.c -@@ -61,7 +61,8 @@ int - grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest) - { - grub_uint32_t newip = 0; -- int i, ncolon = 0; -+ grub_size_t i; -+ int ncolon = 0; - const char *ptr = val; - - /* Check that is not an IPv6 address */ -@@ -78,7 +79,7 @@ grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *addres - for (i = 0; i < 4; i++) - { - unsigned long t; -- t = grub_strtoul (ptr, (char **) &ptr, 0); -+ t = grub_strtoul (ptr, &ptr, 0); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; diff --git a/SOURCES/0162-libtasn1-import-libtasn1-4.16.0.patch b/SOURCES/0162-libtasn1-import-libtasn1-4.16.0.patch new file mode 100644 index 0000000..9587661 --- /dev/null +++ b/SOURCES/0162-libtasn1-import-libtasn1-4.16.0.patch @@ -0,0 +1,8934 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Wed, 10 Jun 2020 16:31:22 +1000 +Subject: [PATCH] libtasn1: import libtasn1-4.16.0 + +Import a very trimmed-down set of libtasn1 files: + +pushd /tmp +wget https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.16.0.tar.gz +popd +pushd grub-core/lib +mkdir libtasn1 +cp /tmp/libtasn1-4.16.0/{README.md,LICENSE} libtasn1/ +mkdir libtasn1/lib +cp /tmp/libtasn1-4.16.0/lib/{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h} libtasn1/lib +cp /tmp/libtasn1-4.16.0/lib/includes/libtasn1.h ../../include/grub/ +git add libtasn1/ ../../include/grub/libtasn1.h +popd + +Signed-off-by: Daniel Axtens +--- + grub-core/lib/libtasn1/lib/coding.c | 1415 ++++++++++++++++++ + grub-core/lib/libtasn1/lib/decoding.c | 2478 +++++++++++++++++++++++++++++++ + grub-core/lib/libtasn1/lib/element.c | 1111 ++++++++++++++ + grub-core/lib/libtasn1/lib/errors.c | 100 ++ + grub-core/lib/libtasn1/lib/gstr.c | 74 + + grub-core/lib/libtasn1/lib/parser_aux.c | 1173 +++++++++++++++ + grub-core/lib/libtasn1/lib/structure.c | 1220 +++++++++++++++ + grub-core/lib/libtasn1/lib/element.h | 40 + + grub-core/lib/libtasn1/lib/gstr.h | 47 + + grub-core/lib/libtasn1/lib/int.h | 221 +++ + grub-core/lib/libtasn1/lib/parser_aux.h | 172 +++ + grub-core/lib/libtasn1/lib/structure.h | 45 + + include/grub/libtasn1.h | 588 ++++++++ + grub-core/lib/libtasn1/LICENSE | 16 + + grub-core/lib/libtasn1/README.md | 91 ++ + 15 files changed, 8791 insertions(+) + create mode 100644 grub-core/lib/libtasn1/lib/coding.c + create mode 100644 grub-core/lib/libtasn1/lib/decoding.c + create mode 100644 grub-core/lib/libtasn1/lib/element.c + create mode 100644 grub-core/lib/libtasn1/lib/errors.c + create mode 100644 grub-core/lib/libtasn1/lib/gstr.c + create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.c + create mode 100644 grub-core/lib/libtasn1/lib/structure.c + create mode 100644 grub-core/lib/libtasn1/lib/element.h + create mode 100644 grub-core/lib/libtasn1/lib/gstr.h + create mode 100644 grub-core/lib/libtasn1/lib/int.h + create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.h + create mode 100644 grub-core/lib/libtasn1/lib/structure.h + create mode 100644 include/grub/libtasn1.h + create mode 100644 grub-core/lib/libtasn1/LICENSE + create mode 100644 grub-core/lib/libtasn1/README.md + +diff --git a/grub-core/lib/libtasn1/lib/coding.c b/grub-core/lib/libtasn1/lib/coding.c +new file mode 100644 +index 0000000000..245ea64cf0 +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/coding.c +@@ -0,0 +1,1415 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++ ++/*****************************************************/ ++/* File: coding.c */ ++/* Description: Functions to create a DER coding of */ ++/* an ASN1 type. */ ++/*****************************************************/ ++ ++#include ++#include "parser_aux.h" ++#include ++#include "element.h" ++#include "minmax.h" ++#include ++ ++#define MAX_TAG_LEN 16 ++ ++/******************************************************/ ++/* Function : _asn1_error_description_value_not_found */ ++/* Description: creates the ErrorDescription string */ ++/* for the ASN1_VALUE_NOT_FOUND error. */ ++/* Parameters: */ ++/* node: node of the tree where the value is NULL. */ ++/* ErrorDescription: string returned. */ ++/* Return: */ ++/******************************************************/ ++static void ++_asn1_error_description_value_not_found (asn1_node node, ++ char *ErrorDescription) ++{ ++ ++ if (ErrorDescription == NULL) ++ return; ++ ++ Estrcpy (ErrorDescription, ":: value of element '"); ++ _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), ++ ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); ++ Estrcat (ErrorDescription, "' not found"); ++ ++} ++ ++/** ++ * asn1_length_der: ++ * @len: value to convert. ++ * @der: buffer to hold the returned encoding (may be %NULL). ++ * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]). ++ * ++ * Creates the DER encoding of the provided length value. ++ * The @der buffer must have enough room for the output. The maximum ++ * length this function will encode is %ASN1_MAX_LENGTH_SIZE. ++ * ++ * To know the size of the DER encoding use a %NULL value for @der. ++ **/ ++void ++asn1_length_der (unsigned long int len, unsigned char *der, int *der_len) ++{ ++ int k; ++ unsigned char temp[ASN1_MAX_LENGTH_SIZE]; ++#if SIZEOF_UNSIGNED_LONG_INT > 8 ++ len &= 0xFFFFFFFFFFFFFFFF; ++#endif ++ ++ if (len < 128) ++ { ++ /* short form */ ++ if (der != NULL) ++ der[0] = (unsigned char) len; ++ *der_len = 1; ++ } ++ else ++ { ++ /* Long form */ ++ k = 0; ++ while (len) ++ { ++ temp[k++] = len & 0xFF; ++ len = len >> 8; ++ } ++ *der_len = k + 1; ++ if (der != NULL) ++ { ++ der[0] = ((unsigned char) k & 0x7F) + 128; ++ while (k--) ++ der[*der_len - 1 - k] = temp[k]; ++ } ++ } ++} ++ ++/******************************************************/ ++/* Function : _asn1_tag_der */ ++/* Description: creates the DER coding for the CLASS */ ++/* and TAG parameters. */ ++/* It is limited by the ASN1_MAX_TAG_SIZE variable */ ++/* Parameters: */ ++/* class: value to convert. */ ++/* tag_value: value to convert. */ ++/* ans: string returned. */ ++/* ans_len: number of meaningful bytes of ANS */ ++/* (ans[0]..ans[ans_len-1]). */ ++/* Return: */ ++/******************************************************/ ++static void ++_asn1_tag_der (unsigned char class, unsigned int tag_value, ++ unsigned char ans[ASN1_MAX_TAG_SIZE], int *ans_len) ++{ ++ int k; ++ unsigned char temp[ASN1_MAX_TAG_SIZE]; ++ ++ if (tag_value < 31) ++ { ++ /* short form */ ++ ans[0] = (class & 0xE0) + ((unsigned char) (tag_value & 0x1F)); ++ *ans_len = 1; ++ } ++ else ++ { ++ /* Long form */ ++ ans[0] = (class & 0xE0) + 31; ++ k = 0; ++ while (tag_value != 0) ++ { ++ temp[k++] = tag_value & 0x7F; ++ tag_value >>= 7; ++ ++ if (k > ASN1_MAX_TAG_SIZE - 1) ++ break; /* will not encode larger tags */ ++ } ++ *ans_len = k + 1; ++ while (k--) ++ ans[*ans_len - 1 - k] = temp[k] + 128; ++ ans[*ans_len - 1] -= 128; ++ } ++} ++ ++/** ++ * asn1_octet_der: ++ * @str: the input data. ++ * @str_len: STR length (str[0]..str[*str_len-1]). ++ * @der: encoded string returned. ++ * @der_len: number of meaningful bytes of DER (der[0]..der[der_len-1]). ++ * ++ * Creates a length-value DER encoding for the input data. ++ * The DER encoding of the input data will be placed in the @der variable. ++ * ++ * Note that the OCTET STRING tag is not included in the output. ++ * ++ * This function does not return any value because it is expected ++ * that @der_len will contain enough bytes to store the string ++ * plus the DER encoding. The DER encoding size can be obtained using ++ * asn1_length_der(). ++ **/ ++void ++asn1_octet_der (const unsigned char *str, int str_len, ++ unsigned char *der, int *der_len) ++{ ++ int len_len; ++ ++ if (der == NULL || str_len < 0) ++ return; ++ ++ asn1_length_der (str_len, der, &len_len); ++ memcpy (der + len_len, str, str_len); ++ *der_len = str_len + len_len; ++} ++ ++ ++/** ++ * asn1_encode_simple_der: ++ * @etype: The type of the string to be encoded (ASN1_ETYPE_) ++ * @str: the string data. ++ * @str_len: the string length ++ * @tl: the encoded tag and length ++ * @tl_len: the bytes of the @tl field ++ * ++ * Creates the DER encoding for various simple ASN.1 types like strings etc. ++ * It stores the tag and length in @tl, which should have space for at least ++ * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl. ++ * ++ * The complete DER encoding should consist of the value in @tl appended ++ * with the provided @str. ++ * ++ * Returns: %ASN1_SUCCESS if successful or an error value. ++ **/ ++int ++asn1_encode_simple_der (unsigned int etype, const unsigned char *str, ++ unsigned int str_len, unsigned char *tl, ++ unsigned int *tl_len) ++{ ++ int tag_len, len_len; ++ unsigned tlen; ++ unsigned char der_tag[ASN1_MAX_TAG_SIZE]; ++ unsigned char der_length[ASN1_MAX_LENGTH_SIZE]; ++ unsigned char *p; ++ ++ if (str == NULL) ++ return ASN1_VALUE_NOT_VALID; ++ ++ if (ETYPE_OK (etype) == 0) ++ return ASN1_VALUE_NOT_VALID; ++ ++ /* doesn't handle constructed classes */ ++ if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL) ++ return ASN1_VALUE_NOT_VALID; ++ ++ _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len); ++ ++ asn1_length_der (str_len, der_length, &len_len); ++ ++ if (tag_len <= 0 || len_len <= 0) ++ return ASN1_VALUE_NOT_VALID; ++ ++ tlen = tag_len + len_len; ++ ++ if (*tl_len < tlen) ++ return ASN1_MEM_ERROR; ++ ++ p = tl; ++ memcpy (p, der_tag, tag_len); ++ p += tag_len; ++ memcpy (p, der_length, len_len); ++ ++ *tl_len = tlen; ++ ++ return ASN1_SUCCESS; ++} ++ ++/******************************************************/ ++/* Function : _asn1_time_der */ ++/* Description: creates the DER coding for a TIME */ ++/* type (length included). */ ++/* Parameters: */ ++/* str: TIME null-terminated string. */ ++/* der: string returned. */ ++/* der_len: number of meaningful bytes of DER */ ++/* (der[0]..der[ans_len-1]). Initially it */ ++/* if must store the lenght of DER. */ ++/* Return: */ ++/* ASN1_MEM_ERROR when DER isn't big enough */ ++/* ASN1_SUCCESS otherwise */ ++/******************************************************/ ++static int ++_asn1_time_der (unsigned char *str, int str_len, unsigned char *der, ++ int *der_len) ++{ ++ int len_len; ++ int max_len; ++ ++ if (der == NULL) ++ return ASN1_VALUE_NOT_VALID; ++ ++ max_len = *der_len; ++ ++ asn1_length_der (str_len, (max_len > 0) ? der : NULL, &len_len); ++ ++ if ((len_len + str_len) <= max_len) ++ memcpy (der + len_len, str, str_len); ++ *der_len = len_len + str_len; ++ ++ if ((*der_len) > max_len) ++ return ASN1_MEM_ERROR; ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/* ++void ++_asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str) ++{ ++ int len_len,str_len; ++ char temp[20]; ++ ++ if(str==NULL) return; ++ str_len=asn1_get_length_der(der,*der_len,&len_len); ++ if (str_len<0) return; ++ memcpy(temp,der+len_len,str_len); ++ *der_len=str_len+len_len; ++ switch(str_len) ++ { ++ case 11: ++ temp[10]=0; ++ strcat(temp,"00+0000"); ++ break; ++ case 13: ++ temp[12]=0; ++ strcat(temp,"+0000"); ++ break; ++ case 15: ++ temp[15]=0; ++ memmove(temp+12,temp+10,6); ++ temp[10]=temp[11]='0'; ++ break; ++ case 17: ++ temp[17]=0; ++ break; ++ default: ++ return; ++ } ++ strcpy(str,temp); ++} ++*/ ++ ++static ++void encode_val(uint64_t val, unsigned char *der, int max_len, int *der_len) ++{ ++ int first, k; ++ unsigned char bit7; ++ ++ first = 0; ++ for (k = sizeof(val); k >= 0; k--) ++ { ++ bit7 = (val >> (k * 7)) & 0x7F; ++ if (bit7 || first || !k) ++ { ++ if (k) ++ bit7 |= 0x80; ++ if (max_len > (*der_len)) ++ der[*der_len] = bit7; ++ (*der_len)++; ++ first = 1; ++ } ++ } ++} ++ ++/******************************************************/ ++/* Function : _asn1_object_id_der */ ++/* Description: creates the DER coding for an */ ++/* OBJECT IDENTIFIER type (length included). */ ++/* Parameters: */ ++/* str: OBJECT IDENTIFIER null-terminated string. */ ++/* der: string returned. */ ++/* der_len: number of meaningful bytes of DER */ ++/* (der[0]..der[ans_len-1]). Initially it */ ++/* must store the length of DER. */ ++/* Return: */ ++/* ASN1_MEM_ERROR when DER isn't big enough */ ++/* ASN1_SUCCESS if succesful */ ++/* or an error value. */ ++/******************************************************/ ++static int ++_asn1_object_id_der (const char *str, unsigned char *der, int *der_len) ++{ ++ int len_len, counter, max_len; ++ char *temp, *n_end, *n_start; ++ uint64_t val, val1 = 0; ++ int str_len = _asn1_strlen (str); ++ ++ max_len = *der_len; ++ *der_len = 0; ++ ++ if (der == NULL && max_len > 0) ++ return ASN1_VALUE_NOT_VALID; ++ ++ temp = malloc (str_len + 2); ++ if (temp == NULL) ++ return ASN1_MEM_ALLOC_ERROR; ++ ++ memcpy (temp, str, str_len); ++ temp[str_len] = '.'; ++ temp[str_len + 1] = 0; ++ ++ counter = 0; ++ n_start = temp; ++ while ((n_end = strchr (n_start, '.'))) ++ { ++ *n_end = 0; ++ val = _asn1_strtou64 (n_start, NULL, 10); ++ counter++; ++ ++ if (counter == 1) ++ { ++ val1 = val; ++ } ++ else if (counter == 2) ++ { ++ uint64_t val0; ++ ++ if (val1 > 2) ++ { ++ free(temp); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ else if ((val1 == 0 || val1 == 1) && val > 39) ++ { ++ free(temp); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ ++ val0 = 40 * val1 + val; ++ encode_val(val0, der, max_len, der_len); ++ } ++ else ++ { ++ encode_val(val, der, max_len, der_len); ++ } ++ n_start = n_end + 1; ++ } ++ ++ asn1_length_der (*der_len, NULL, &len_len); ++ if (max_len >= (*der_len + len_len)) ++ { ++ memmove (der + len_len, der, *der_len); ++ asn1_length_der (*der_len, der, &len_len); ++ } ++ *der_len += len_len; ++ ++ free (temp); ++ ++ if (max_len < (*der_len)) ++ return ASN1_MEM_ERROR; ++ ++ return ASN1_SUCCESS; ++} ++ ++/** ++ * asn1_object_id_der: ++ * @str: An object identifier in numeric, dot format. ++ * @der: buffer to hold the returned encoding (may be %NULL). ++ * @der_len: initially the size of @der; will hold the final size. ++ * @flags: must be zero ++ * ++ * Creates the DER encoding of the provided object identifier. ++ * ++ * Returns: %ASN1_SUCCESS if DER encoding was OK, %ASN1_VALUE_NOT_VALID ++ * if @str is not a valid OID, %ASN1_MEM_ERROR if the @der ++ * vector isn't big enough and in this case @der_len will contain the ++ * length needed. ++ **/ ++int asn1_object_id_der(const char *str, unsigned char *der, int *der_len, unsigned flags) ++{ ++ unsigned char tag_der[MAX_TAG_LEN]; ++ int tag_len = 0, r; ++ int max_len = *der_len; ++ ++ *der_len = 0; ++ ++ _asn1_tag_der (ETYPE_CLASS (ASN1_ETYPE_OBJECT_ID), ETYPE_TAG (ASN1_ETYPE_OBJECT_ID), ++ tag_der, &tag_len); ++ ++ if (max_len > tag_len) ++ { ++ memcpy(der, tag_der, tag_len); ++ } ++ max_len -= tag_len; ++ der += tag_len; ++ ++ r = _asn1_object_id_der (str, der, &max_len); ++ if (r == ASN1_MEM_ERROR || r == ASN1_SUCCESS) ++ { ++ *der_len = max_len + tag_len; ++ } ++ ++ return r; ++} ++ ++static const unsigned char bit_mask[] = ++ { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 }; ++ ++/** ++ * asn1_bit_der: ++ * @str: BIT string. ++ * @bit_len: number of meaningful bits in STR. ++ * @der: string returned. ++ * @der_len: number of meaningful bytes of DER ++ * (der[0]..der[ans_len-1]). ++ * ++ * Creates a length-value DER encoding for the input data ++ * as it would have been for a BIT STRING. ++ * The DER encoded data will be copied in @der. ++ * ++ * Note that the BIT STRING tag is not included in the output. ++ * ++ * This function does not return any value because it is expected ++ * that @der_len will contain enough bytes to store the string ++ * plus the DER encoding. The DER encoding size can be obtained using ++ * asn1_length_der(). ++ **/ ++void ++asn1_bit_der (const unsigned char *str, int bit_len, ++ unsigned char *der, int *der_len) ++{ ++ int len_len, len_byte, len_pad; ++ ++ if (der == NULL) ++ return; ++ ++ len_byte = bit_len >> 3; ++ len_pad = 8 - (bit_len & 7); ++ if (len_pad == 8) ++ len_pad = 0; ++ else ++ len_byte++; ++ asn1_length_der (len_byte + 1, der, &len_len); ++ der[len_len] = len_pad; ++ ++ if (str) ++ memcpy (der + len_len + 1, str, len_byte); ++ der[len_len + len_byte] &= bit_mask[len_pad]; ++ *der_len = len_byte + len_len + 1; ++} ++ ++ ++/******************************************************/ ++/* Function : _asn1_complete_explicit_tag */ ++/* Description: add the length coding to the EXPLICIT */ ++/* tags. */ ++/* Parameters: */ ++/* node: pointer to the tree element. */ ++/* der: string with the DER coding of the whole tree*/ ++/* counter: number of meaningful bytes of DER */ ++/* (der[0]..der[*counter-1]). */ ++/* max_len: size of der vector */ ++/* Return: */ ++/* ASN1_MEM_ERROR if der vector isn't big enough, */ ++/* otherwise ASN1_SUCCESS. */ ++/******************************************************/ ++static int ++_asn1_complete_explicit_tag (asn1_node node, unsigned char *der, ++ int *counter, int *max_len) ++{ ++ asn1_node p; ++ int is_tag_implicit, len2, len3; ++ unsigned char temp[SIZEOF_UNSIGNED_INT]; ++ ++ if (der == NULL && *max_len > 0) ++ return ASN1_VALUE_NOT_VALID; ++ ++ is_tag_implicit = 0; ++ ++ if (node->type & CONST_TAG) ++ { ++ p = node->down; ++ if (p == NULL) ++ return ASN1_DER_ERROR; ++ /* When there are nested tags we must complete them reverse to ++ the order they were created. This is because completing a tag ++ modifies all data within it, including the incomplete tags ++ which store buffer positions -- simon@josefsson.org 2002-09-06 ++ */ ++ while (p->right) ++ p = p->right; ++ while (p && p != node->down->left) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_TAG) ++ { ++ if (p->type & CONST_EXPLICIT) ++ { ++ len2 = strtol (p->name, NULL, 10); ++ _asn1_set_name (p, NULL); ++ ++ asn1_length_der (*counter - len2, temp, &len3); ++ if (len3 <= (*max_len)) ++ { ++ memmove (der + len2 + len3, der + len2, ++ *counter - len2); ++ memcpy (der + len2, temp, len3); ++ } ++ *max_len -= len3; ++ *counter += len3; ++ is_tag_implicit = 0; ++ } ++ else ++ { /* CONST_IMPLICIT */ ++ if (!is_tag_implicit) ++ { ++ is_tag_implicit = 1; ++ } ++ } ++ } ++ p = p->left; ++ } ++ } ++ ++ if (*max_len < 0) ++ return ASN1_MEM_ERROR; ++ ++ return ASN1_SUCCESS; ++} ++ ++const tag_and_class_st _asn1_tags[] = { ++ [ASN1_ETYPE_GENERALSTRING] = ++ {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"}, ++ [ASN1_ETYPE_NUMERIC_STRING] = ++ {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"}, ++ [ASN1_ETYPE_IA5_STRING] = ++ {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"}, ++ [ASN1_ETYPE_TELETEX_STRING] = ++ {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"}, ++ [ASN1_ETYPE_PRINTABLE_STRING] = ++ {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"}, ++ [ASN1_ETYPE_UNIVERSAL_STRING] = ++ {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"}, ++ [ASN1_ETYPE_BMP_STRING] = ++ {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, ++ [ASN1_ETYPE_UTF8_STRING] = ++ {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, ++ [ASN1_ETYPE_VISIBLE_STRING] = ++ {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, ++ [ASN1_ETYPE_OCTET_STRING] = ++ {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, ++ [ASN1_ETYPE_BIT_STRING] = ++ {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"}, ++ [ASN1_ETYPE_OBJECT_ID] = ++ {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"}, ++ [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"}, ++ [ASN1_ETYPE_BOOLEAN] = ++ {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"}, ++ [ASN1_ETYPE_INTEGER] = ++ {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"}, ++ [ASN1_ETYPE_ENUMERATED] = ++ {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"}, ++ [ASN1_ETYPE_SEQUENCE] = ++ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, ++ "type:SEQUENCE"}, ++ [ASN1_ETYPE_SEQUENCE_OF] = ++ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, ++ "type:SEQ_OF"}, ++ [ASN1_ETYPE_SET] = ++ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"}, ++ [ASN1_ETYPE_SET_OF] = ++ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, ++ "type:SET_OF"}, ++ [ASN1_ETYPE_GENERALIZED_TIME] = ++ {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"}, ++ [ASN1_ETYPE_UTC_TIME] = ++ {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"}, ++}; ++ ++unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]); ++ ++/******************************************************/ ++/* Function : _asn1_insert_tag_der */ ++/* Description: creates the DER coding of tags of one */ ++/* NODE. */ ++/* Parameters: */ ++/* node: pointer to the tree element. */ ++/* der: string returned */ ++/* counter: number of meaningful bytes of DER */ ++/* (counter[0]..der[*counter-1]). */ ++/* max_len: size of der vector */ ++/* Return: */ ++/* ASN1_GENERIC_ERROR if the type is unknown, */ ++/* ASN1_MEM_ERROR if der vector isn't big enough, */ ++/* otherwise ASN1_SUCCESS. */ ++/******************************************************/ ++static int ++_asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, ++ int *max_len) ++{ ++ asn1_node p; ++ int tag_len, is_tag_implicit; ++ unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)]; ++ unsigned long tag_implicit = 0; ++ unsigned char tag_der[MAX_TAG_LEN]; ++ ++ is_tag_implicit = 0; ++ ++ if (node->type & CONST_TAG) ++ { ++ p = node->down; ++ while (p) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_TAG) ++ { ++ if (p->type & CONST_APPLICATION) ++ class = ASN1_CLASS_APPLICATION; ++ else if (p->type & CONST_UNIVERSAL) ++ class = ASN1_CLASS_UNIVERSAL; ++ else if (p->type & CONST_PRIVATE) ++ class = ASN1_CLASS_PRIVATE; ++ else ++ class = ASN1_CLASS_CONTEXT_SPECIFIC; ++ ++ if (p->type & CONST_EXPLICIT) ++ { ++ if (is_tag_implicit) ++ _asn1_tag_der (class_implicit, tag_implicit, tag_der, ++ &tag_len); ++ else ++ _asn1_tag_der (class | ASN1_CLASS_STRUCTURED, ++ _asn1_strtoul (p->value, NULL, 10), ++ tag_der, &tag_len); ++ ++ *max_len -= tag_len; ++ if (der && *max_len >= 0) ++ memcpy (der + *counter, tag_der, tag_len); ++ *counter += tag_len; ++ ++ _asn1_ltostr (*counter, (char *) temp); ++ _asn1_set_name (p, (const char *) temp); ++ ++ is_tag_implicit = 0; ++ } ++ else ++ { /* CONST_IMPLICIT */ ++ if (!is_tag_implicit) ++ { ++ if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || ++ (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) ++ || (type_field (node->type) == ASN1_ETYPE_SET) ++ || (type_field (node->type) == ASN1_ETYPE_SET_OF)) ++ class |= ASN1_CLASS_STRUCTURED; ++ class_implicit = class; ++ tag_implicit = _asn1_strtoul (p->value, NULL, 10); ++ is_tag_implicit = 1; ++ } ++ } ++ } ++ p = p->right; ++ } ++ } ++ ++ if (is_tag_implicit) ++ { ++ _asn1_tag_der (class_implicit, tag_implicit, tag_der, &tag_len); ++ } ++ else ++ { ++ unsigned type = type_field (node->type); ++ switch (type) ++ { ++ CASE_HANDLED_ETYPES: ++ _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag, ++ tag_der, &tag_len); ++ break; ++ case ASN1_ETYPE_TAG: ++ case ASN1_ETYPE_CHOICE: ++ case ASN1_ETYPE_ANY: ++ tag_len = 0; ++ break; ++ default: ++ return ASN1_GENERIC_ERROR; ++ } ++ } ++ ++ *max_len -= tag_len; ++ if (der && *max_len >= 0) ++ memcpy (der + *counter, tag_der, tag_len); ++ *counter += tag_len; ++ ++ if (*max_len < 0) ++ return ASN1_MEM_ERROR; ++ ++ return ASN1_SUCCESS; ++} ++ ++/******************************************************/ ++/* Function : _asn1_ordering_set */ ++/* Description: puts the elements of a SET type in */ ++/* the correct order according to DER rules. */ ++/* Parameters: */ ++/* der: string with the DER coding. */ ++/* node: pointer to the SET element. */ ++/* Return: */ ++/* ASN1_SUCCESS if successful */ ++/* or an error value. */ ++/******************************************************/ ++static int ++_asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) ++{ ++ struct vet ++ { ++ int end; ++ unsigned long value; ++ struct vet *next, *prev; ++ }; ++ ++ int counter, len, len2; ++ struct vet *first, *last, *p_vet, *p2_vet; ++ asn1_node p; ++ unsigned char class, *temp; ++ unsigned long tag, t; ++ int err; ++ ++ counter = 0; ++ ++ if (type_field (node->type) != ASN1_ETYPE_SET) ++ return ASN1_VALUE_NOT_VALID; ++ ++ p = node->down; ++ while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || ++ (type_field (p->type) == ASN1_ETYPE_SIZE))) ++ p = p->right; ++ ++ if ((p == NULL) || (p->right == NULL)) ++ return ASN1_SUCCESS; ++ ++ first = last = NULL; ++ while (p) ++ { ++ p_vet = malloc (sizeof (struct vet)); ++ if (p_vet == NULL) ++ { ++ err = ASN1_MEM_ALLOC_ERROR; ++ goto error; ++ } ++ ++ p_vet->next = NULL; ++ p_vet->prev = last; ++ if (first == NULL) ++ first = p_vet; ++ else ++ last->next = p_vet; ++ last = p_vet; ++ ++ /* tag value calculation */ ++ err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2, ++ &tag); ++ if (err != ASN1_SUCCESS) ++ goto error; ++ ++ t = ((unsigned int)class) << 24; ++ p_vet->value = t | tag; ++ counter += len2; ++ ++ /* extraction and length */ ++ len2 = asn1_get_length_der (der + counter, der_len - counter, &len); ++ if (len2 < 0) ++ { ++ err = ASN1_DER_ERROR; ++ goto error; ++ } ++ counter += len + len2; ++ ++ p_vet->end = counter; ++ p = p->right; ++ } ++ ++ p_vet = first; ++ ++ while (p_vet) ++ { ++ p2_vet = p_vet->next; ++ counter = 0; ++ while (p2_vet) ++ { ++ if (p_vet->value > p2_vet->value) ++ { ++ /* change position */ ++ temp = malloc (p_vet->end - counter); ++ if (temp == NULL) ++ { ++ err = ASN1_MEM_ALLOC_ERROR; ++ goto error; ++ } ++ ++ memcpy (temp, der + counter, p_vet->end - counter); ++ memcpy (der + counter, der + p_vet->end, ++ p2_vet->end - p_vet->end); ++ memcpy (der + counter + p2_vet->end - p_vet->end, temp, ++ p_vet->end - counter); ++ free (temp); ++ ++ tag = p_vet->value; ++ p_vet->value = p2_vet->value; ++ p2_vet->value = tag; ++ ++ p_vet->end = counter + (p2_vet->end - p_vet->end); ++ } ++ counter = p_vet->end; ++ ++ p2_vet = p2_vet->next; ++ p_vet = p_vet->next; ++ } ++ ++ if (p_vet != first) ++ p_vet->prev->next = NULL; ++ else ++ first = NULL; ++ free (p_vet); ++ p_vet = first; ++ } ++ return ASN1_SUCCESS; ++ ++error: ++ while (first != NULL) ++ { ++ p_vet = first; ++ first = first->next; ++ free(p_vet); ++ } ++ return err; ++} ++ ++struct vet ++{ ++ unsigned char *ptr; ++ int size; ++}; ++ ++static int setof_compar(const void *_e1, const void *_e2) ++{ ++ unsigned length; ++ const struct vet *e1 = _e1, *e2 = _e2; ++ int rval; ++ ++ /* The encodings of the component values of a set-of value shall ++ * appear in ascending order, the encodings being compared ++ * as octet strings with the shorter components being ++ * padded at their trailing end with 0-octets. ++ * The padding octets are for comparison purposes and ++ * do not appear in the encodings. ++ */ ++ length = MIN(e1->size, e2->size); ++ ++ rval = memcmp(e1->ptr, e2->ptr, length); ++ if (rval == 0 && e1->size != e2->size) ++ { ++ if (e1->size > e2->size) ++ rval = 1; ++ else if (e2->size > e1->size) ++ rval = -1; ++ } ++ ++ return rval; ++} ++ ++/******************************************************/ ++/* Function : _asn1_ordering_set_of */ ++/* Description: puts the elements of a SET OF type in */ ++/* the correct order according to DER rules. */ ++/* Parameters: */ ++/* der: string with the DER coding. */ ++/* node: pointer to the SET OF element. */ ++/* Return: */ ++/* ASN1_SUCCESS if successful */ ++/* or an error value. */ ++/******************************************************/ ++static int ++_asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) ++{ ++ int counter, len, len2; ++ struct vet *list = NULL, *tlist; ++ unsigned list_size = 0; ++ struct vet *p_vet; ++ asn1_node p; ++ unsigned char class; ++ unsigned i; ++ unsigned char *out = NULL; ++ int err; ++ ++ if (der == NULL) ++ return ASN1_VALUE_NOT_VALID; ++ ++ counter = 0; ++ ++ if (type_field (node->type) != ASN1_ETYPE_SET_OF) ++ return ASN1_VALUE_NOT_VALID; ++ ++ p = node->down; ++ while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || ++ (type_field (p->type) == ASN1_ETYPE_SIZE))) ++ p = p->right; ++ if (p == NULL) ++ return ASN1_VALUE_NOT_VALID; ++ p = p->right; ++ ++ if ((p == NULL) || (p->right == NULL)) ++ return ASN1_SUCCESS; ++ ++ while (p) ++ { ++ list_size++; ++ tlist = realloc (list, list_size*sizeof(struct vet)); ++ if (tlist == NULL) ++ { ++ err = ASN1_MEM_ALLOC_ERROR; ++ goto error; ++ } ++ list = tlist; ++ p_vet = &list[list_size-1]; ++ ++ p_vet->ptr = der+counter; ++ p_vet->size = 0; ++ ++ /* extraction of tag and length */ ++ if (der_len - counter > 0) ++ { ++ err = asn1_get_tag_der (der + counter, der_len - counter, &class, ++ &len, NULL); ++ if (err != ASN1_SUCCESS) ++ goto error; ++ counter += len; ++ p_vet->size += len; ++ ++ len2 = asn1_get_length_der (der + counter, der_len - counter, &len); ++ if (len2 < 0) ++ { ++ err = ASN1_DER_ERROR; ++ goto error; ++ } ++ counter += len + len2; ++ p_vet->size += len + len2; ++ ++ } ++ else ++ { ++ err = ASN1_DER_ERROR; ++ goto error; ++ } ++ p = p->right; ++ } ++ ++ if (counter > der_len) ++ { ++ err = ASN1_DER_ERROR; ++ goto error; ++ } ++ ++ qsort(list, list_size, sizeof(struct vet), setof_compar); ++ ++ out = malloc(der_len); ++ if (out == NULL) ++ { ++ err = ASN1_MEM_ERROR; ++ goto error; ++ } ++ ++ /* the sum of p_vet->size == der_len */ ++ counter = 0; ++ for (i = 0; i < list_size; i++) ++ { ++ p_vet = &list[i]; ++ memcpy(out+counter, p_vet->ptr, p_vet->size); ++ counter += p_vet->size; ++ } ++ memcpy(der, out, der_len); ++ free(out); ++ ++ err = ASN1_SUCCESS; ++ ++error: ++ free(list); ++ return err; ++} ++ ++/** ++ * asn1_der_coding: ++ * @element: pointer to an ASN1 element ++ * @name: the name of the structure you want to encode (it must be ++ * inside *POINTER). ++ * @ider: vector that will contain the DER encoding. DER must be a ++ * pointer to memory cells already allocated. ++ * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy ++ * holds the sizeof of der vector. ++ * @ErrorDescription: return the error description or an empty ++ * string if success. ++ * ++ * Creates the DER encoding for the NAME structure (inside *POINTER ++ * structure). ++ * ++ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND ++ * if @name is not a valid element, %ASN1_VALUE_NOT_FOUND if there ++ * is an element without a value, %ASN1_MEM_ERROR if the @ider ++ * vector isn't big enough and in this case @len will contain the ++ * length needed. ++ **/ ++int ++asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len, ++ char *ErrorDescription) ++{ ++ asn1_node node, p, p2; ++ unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)]; ++ int counter, counter_old, len2, len3, move, max_len, max_len_old; ++ int err; ++ unsigned char *der = ider; ++ ++ if (ErrorDescription) ++ ErrorDescription[0] = 0; ++ ++ node = asn1_find_node (element, name); ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ /* Node is now a locally allocated variable. ++ * That is because in some point we modify the ++ * structure, and I don't know why! --nmav ++ */ ++ node = _asn1_copy_structure3 (node); ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ max_len = *len; ++ ++ if (der == NULL && max_len > 0) ++ return ASN1_VALUE_NOT_VALID; ++ ++ counter = 0; ++ move = DOWN; ++ p = node; ++ ++ while (1) ++ { ++ ++ counter_old = counter; ++ max_len_old = max_len; ++ if (move != UP) ++ { ++ p->start = counter; ++ err = _asn1_insert_tag_der (p, der, &counter, &max_len); ++ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) ++ goto error; ++ } ++ switch (type_field (p->type)) ++ { ++ case ASN1_ETYPE_NULL: ++ max_len--; ++ if (der != NULL && max_len >= 0) ++ der[counter] = 0; ++ counter++; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_BOOLEAN: ++ if ((p->type & CONST_DEFAULT) && (p->value == NULL)) ++ { ++ counter = counter_old; ++ max_len = max_len_old; ++ } ++ else ++ { ++ if (p->value == NULL) ++ { ++ _asn1_error_description_value_not_found (p, ++ ErrorDescription); ++ err = ASN1_VALUE_NOT_FOUND; ++ goto error; ++ } ++ max_len -= 2; ++ if (der != NULL && max_len >= 0) ++ { ++ der[counter++] = 1; ++ if (p->value[0] == 'F') ++ der[counter++] = 0; ++ else ++ der[counter++] = 0xFF; ++ } ++ else ++ counter += 2; ++ } ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_INTEGER: ++ case ASN1_ETYPE_ENUMERATED: ++ if ((p->type & CONST_DEFAULT) && (p->value == NULL)) ++ { ++ counter = counter_old; ++ max_len = max_len_old; ++ } ++ else ++ { ++ if (p->value == NULL) ++ { ++ _asn1_error_description_value_not_found (p, ++ ErrorDescription); ++ err = ASN1_VALUE_NOT_FOUND; ++ goto error; ++ } ++ len2 = asn1_get_length_der (p->value, p->value_len, &len3); ++ if (len2 < 0) ++ { ++ err = ASN1_DER_ERROR; ++ goto error; ++ } ++ max_len -= len2 + len3; ++ if (der != NULL && max_len >= 0) ++ memcpy (der + counter, p->value, len3 + len2); ++ counter += len3 + len2; ++ } ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_OBJECT_ID: ++ if ((p->type & CONST_DEFAULT) && (p->value == NULL)) ++ { ++ counter = counter_old; ++ max_len = max_len_old; ++ } ++ else ++ { ++ if (p->value == NULL) ++ { ++ _asn1_error_description_value_not_found (p, ++ ErrorDescription); ++ err = ASN1_VALUE_NOT_FOUND; ++ goto error; ++ } ++ len2 = max_len; ++ err = _asn1_object_id_der ((char*)p->value, der + counter, &len2); ++ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) ++ goto error; ++ ++ max_len -= len2; ++ counter += len2; ++ } ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_GENERALIZED_TIME: ++ case ASN1_ETYPE_UTC_TIME: ++ if (p->value == NULL) ++ { ++ _asn1_error_description_value_not_found (p, ErrorDescription); ++ err = ASN1_VALUE_NOT_FOUND; ++ goto error; ++ } ++ len2 = max_len; ++ err = _asn1_time_der (p->value, p->value_len, der + counter, &len2); ++ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) ++ goto error; ++ ++ max_len -= len2; ++ counter += len2; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_OCTET_STRING: ++ case ASN1_ETYPE_GENERALSTRING: ++ case ASN1_ETYPE_NUMERIC_STRING: ++ case ASN1_ETYPE_IA5_STRING: ++ case ASN1_ETYPE_TELETEX_STRING: ++ case ASN1_ETYPE_PRINTABLE_STRING: ++ case ASN1_ETYPE_UNIVERSAL_STRING: ++ case ASN1_ETYPE_BMP_STRING: ++ case ASN1_ETYPE_UTF8_STRING: ++ case ASN1_ETYPE_VISIBLE_STRING: ++ case ASN1_ETYPE_BIT_STRING: ++ if (p->value == NULL) ++ { ++ _asn1_error_description_value_not_found (p, ErrorDescription); ++ err = ASN1_VALUE_NOT_FOUND; ++ goto error; ++ } ++ len2 = asn1_get_length_der (p->value, p->value_len, &len3); ++ if (len2 < 0) ++ { ++ err = ASN1_DER_ERROR; ++ goto error; ++ } ++ max_len -= len2 + len3; ++ if (der != NULL && max_len >= 0) ++ memcpy (der + counter, p->value, len3 + len2); ++ counter += len3 + len2; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_SEQUENCE: ++ case ASN1_ETYPE_SET: ++ if (move != UP) ++ { ++ p->tmp_ival = counter; ++ if (p->down == NULL) ++ { ++ move = UP; ++ continue; ++ } ++ else ++ { ++ p2 = p->down; ++ while (p2 && (type_field (p2->type) == ASN1_ETYPE_TAG)) ++ p2 = p2->right; ++ if (p2) ++ { ++ p = p2; ++ move = RIGHT; ++ continue; ++ } ++ move = UP; ++ continue; ++ } ++ } ++ else ++ { /* move==UP */ ++ len2 = p->tmp_ival; ++ p->tmp_ival = 0; ++ if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0)) ++ { ++ err = _asn1_ordering_set (der + len2, counter - len2, p); ++ if (err != ASN1_SUCCESS) ++ goto error; ++ } ++ asn1_length_der (counter - len2, temp, &len3); ++ max_len -= len3; ++ if (der != NULL && max_len >= 0) ++ { ++ memmove (der + len2 + len3, der + len2, counter - len2); ++ memcpy (der + len2, temp, len3); ++ } ++ counter += len3; ++ move = RIGHT; ++ } ++ break; ++ case ASN1_ETYPE_SEQUENCE_OF: ++ case ASN1_ETYPE_SET_OF: ++ if (move != UP) ++ { ++ p->tmp_ival = counter; ++ p = p->down; ++ while ((type_field (p->type) == ASN1_ETYPE_TAG) ++ || (type_field (p->type) == ASN1_ETYPE_SIZE)) ++ p = p->right; ++ if (p->right) ++ { ++ p = p->right; ++ move = RIGHT; ++ continue; ++ } ++ else ++ p = _asn1_find_up (p); ++ move = UP; ++ } ++ if (move == UP) ++ { ++ len2 = p->tmp_ival; ++ p->tmp_ival = 0; ++ if ((type_field (p->type) == ASN1_ETYPE_SET_OF) ++ && (counter - len2 > 0) && (max_len >= 0)) ++ { ++ err = _asn1_ordering_set_of (der + len2, counter - len2, p); ++ if (err != ASN1_SUCCESS) ++ goto error; ++ } ++ asn1_length_der (counter - len2, temp, &len3); ++ max_len -= len3; ++ if (der != NULL && max_len >= 0) ++ { ++ memmove (der + len2 + len3, der + len2, counter - len2); ++ memcpy (der + len2, temp, len3); ++ } ++ counter += len3; ++ move = RIGHT; ++ } ++ break; ++ case ASN1_ETYPE_ANY: ++ if (p->value == NULL) ++ { ++ _asn1_error_description_value_not_found (p, ErrorDescription); ++ err = ASN1_VALUE_NOT_FOUND; ++ goto error; ++ } ++ len2 = asn1_get_length_der (p->value, p->value_len, &len3); ++ if (len2 < 0) ++ { ++ err = ASN1_DER_ERROR; ++ goto error; ++ } ++ max_len -= len2; ++ if (der != NULL && max_len >= 0) ++ memcpy (der + counter, p->value + len3, len2); ++ counter += len2; ++ move = RIGHT; ++ break; ++ default: ++ move = (move == UP) ? RIGHT : DOWN; ++ break; ++ } ++ ++ if ((move != DOWN) && (counter != counter_old)) ++ { ++ p->end = counter - 1; ++ err = _asn1_complete_explicit_tag (p, der, &counter, &max_len); ++ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) ++ goto error; ++ } ++ ++ if (p == node && move != DOWN) ++ break; ++ ++ if (move == DOWN) ++ { ++ if (p->down) ++ p = p->down; ++ else ++ move = RIGHT; ++ } ++ if (move == RIGHT) ++ { ++ if (p->right) ++ p = p->right; ++ else ++ move = UP; ++ } ++ if (move == UP) ++ p = _asn1_find_up (p); ++ } ++ ++ *len = counter; ++ ++ if (max_len < 0) ++ { ++ err = ASN1_MEM_ERROR; ++ goto error; ++ } ++ ++ err = ASN1_SUCCESS; ++ ++error: ++ asn1_delete_structure (&node); ++ return err; ++} +diff --git a/grub-core/lib/libtasn1/lib/decoding.c b/grub-core/lib/libtasn1/lib/decoding.c +new file mode 100644 +index 0000000000..ff04eb778c +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/decoding.c +@@ -0,0 +1,2478 @@ ++/* ++ * Copyright (C) 2002-2016 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++ ++/*****************************************************/ ++/* File: decoding.c */ ++/* Description: Functions to manage DER decoding */ ++/*****************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef DEBUG ++# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) ++#else ++# define warn() ++#endif ++ ++#define IS_ERR(len, flags) (len < -1 || ((flags & ASN1_DECODE_FLAG_STRICT_DER) && len < 0)) ++ ++#define HAVE_TWO(x) (x>=2?1:0) ++ ++/* Decoding flags (dflags) used in several decoding functions. ++ * DECODE_FLAG_HAVE_TAG: The provided buffer includes a tag ++ * DECODE_FLAG_CONSTRUCTED: The provided buffer is of indefinite encoding (useful ++ * when no tags are present). ++ * DECODE_FLAG_LEVEL1: Internal flag to indicate a level of recursion for BER strings. ++ * DECODE_FLAG_LEVEL2: Internal flag to indicate two levels of recursion for BER strings. ++ * DECODE_FLAG_LEVEL3: Internal flag to indicate three levels of recursion for BER strings. ++ * This is the maximum levels of recursion possible to prevent stack ++ * exhaustion. ++ */ ++ ++#define DECODE_FLAG_HAVE_TAG 1 ++#define DECODE_FLAG_CONSTRUCTED (1<<1) ++#define DECODE_FLAG_LEVEL1 (1<<2) ++#define DECODE_FLAG_LEVEL2 (1<<3) ++#define DECODE_FLAG_LEVEL3 (1<<4) ++ ++#define DECR_LEN(l, s) do { \ ++ l -= s; \ ++ if (l < 0) { \ ++ warn(); \ ++ result = ASN1_DER_ERROR; \ ++ goto cleanup; \ ++ } \ ++ } while (0) ++ ++static int ++_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len); ++ ++static int ++_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, unsigned char **str, ++ unsigned int *str_len, unsigned int *ber_len, ++ unsigned dflags); ++ ++static int ++_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, const unsigned char **str, ++ unsigned int *str_len, unsigned dflags); ++ ++static void ++_asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) ++{ ++ ++ Estrcpy (ErrorDescription, ":: tag error near element '"); ++ _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), ++ ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); ++ Estrcat (ErrorDescription, "'"); ++ ++} ++ ++/** ++ * asn1_get_length_der: ++ * @der: DER data to decode. ++ * @der_len: Length of DER data to decode. ++ * @len: Output variable containing the length of the DER length field. ++ * ++ * Extract a length field from DER data. ++ * ++ * Returns: Return the decoded length value, or -1 on indefinite ++ * length, or -2 when the value was too big to fit in a int, or -4 ++ * when the decoded length value plus @len would exceed @der_len. ++ **/ ++long ++asn1_get_length_der (const unsigned char *der, int der_len, int *len) ++{ ++ unsigned int ans; ++ int k, punt, sum; ++ ++ *len = 0; ++ if (der_len <= 0) ++ return 0; ++ ++ if (!(der[0] & 128)) ++ { ++ /* short form */ ++ *len = 1; ++ ans = der[0]; ++ } ++ else ++ { ++ /* Long form */ ++ k = der[0] & 0x7F; ++ punt = 1; ++ if (k) ++ { /* definite length method */ ++ ans = 0; ++ while (punt <= k && punt < der_len) ++ { ++ if (INT_MULTIPLY_OVERFLOW (ans, 256)) ++ return -2; ++ ans *= 256; ++ ++ if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt]))) ++ return -2; ++ ans += der[punt]; ++ punt++; ++ } ++ } ++ else ++ { /* indefinite length method */ ++ *len = punt; ++ return -1; ++ } ++ ++ *len = punt; ++ } ++ ++ sum = ans; ++ if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len))) ++ return -2; ++ sum += *len; ++ ++ if (sum > der_len) ++ return -4; ++ ++ return ans; ++} ++ ++/** ++ * asn1_get_tag_der: ++ * @der: DER data to decode. ++ * @der_len: Length of DER data to decode. ++ * @cls: Output variable containing decoded class. ++ * @len: Output variable containing the length of the DER TAG data. ++ * @tag: Output variable containing the decoded tag (may be %NULL). ++ * ++ * Decode the class and TAG from DER code. ++ * ++ * Returns: Returns %ASN1_SUCCESS on success, or an error. ++ **/ ++int ++asn1_get_tag_der (const unsigned char *der, int der_len, ++ unsigned char *cls, int *len, unsigned long *tag) ++{ ++ unsigned int ris; ++ int punt; ++ ++ if (der == NULL || der_len < 2 || len == NULL) ++ return ASN1_DER_ERROR; ++ ++ *cls = der[0] & 0xE0; ++ if ((der[0] & 0x1F) != 0x1F) ++ { ++ /* short form */ ++ *len = 1; ++ ris = der[0] & 0x1F; ++ } ++ else ++ { ++ /* Long form */ ++ punt = 1; ++ ris = 0; ++ while (punt < der_len && der[punt] & 128) ++ { ++ ++ if (INT_MULTIPLY_OVERFLOW (ris, 128)) ++ return ASN1_DER_ERROR; ++ ris *= 128; ++ ++ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) ++ return ASN1_DER_ERROR; ++ ris += (der[punt] & 0x7F); ++ punt++; ++ } ++ ++ if (punt >= der_len) ++ return ASN1_DER_ERROR; ++ ++ if (INT_MULTIPLY_OVERFLOW (ris, 128)) ++ return ASN1_DER_ERROR; ++ ris *= 128; ++ ++ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) ++ return ASN1_DER_ERROR; ++ ris += (der[punt] & 0x7F); ++ punt++; ++ ++ *len = punt; ++ } ++ ++ if (tag) ++ *tag = ris; ++ return ASN1_SUCCESS; ++} ++ ++/** ++ * asn1_get_length_ber: ++ * @ber: BER data to decode. ++ * @ber_len: Length of BER data to decode. ++ * @len: Output variable containing the length of the BER length field. ++ * ++ * Extract a length field from BER data. The difference to ++ * asn1_get_length_der() is that this function will return a length ++ * even if the value has indefinite encoding. ++ * ++ * Returns: Return the decoded length value, or negative value when ++ * the value was too big. ++ * ++ * Since: 2.0 ++ **/ ++long ++asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) ++{ ++ int ret; ++ long err; ++ ++ ret = asn1_get_length_der (ber, ber_len, len); ++ ++ if (ret == -1 && ber_len > 1) ++ { /* indefinite length method */ ++ err = _asn1_get_indefinite_length_string (ber + 1, ber_len-1, &ret); ++ if (err != ASN1_SUCCESS) ++ return -3; ++ } ++ ++ return ret; ++} ++ ++/** ++ * asn1_get_octet_der: ++ * @der: DER data to decode containing the OCTET SEQUENCE. ++ * @der_len: The length of the @der data to decode. ++ * @ret_len: Output variable containing the encoded length of the DER data. ++ * @str: Pre-allocated output buffer to put decoded OCTET SEQUENCE in. ++ * @str_size: Length of pre-allocated output buffer. ++ * @str_len: Output variable containing the length of the contents of the OCTET SEQUENCE. ++ * ++ * Extract an OCTET SEQUENCE from DER data. Note that this function ++ * expects the DER data past the tag field, i.e., the length and ++ * content octets. ++ * ++ * Returns: Returns %ASN1_SUCCESS on success, or an error. ++ **/ ++int ++asn1_get_octet_der (const unsigned char *der, int der_len, ++ int *ret_len, unsigned char *str, int str_size, ++ int *str_len) ++{ ++ int len_len = 0; ++ ++ if (der_len <= 0) ++ return ASN1_GENERIC_ERROR; ++ ++ *str_len = asn1_get_length_der (der, der_len, &len_len); ++ ++ if (*str_len < 0) ++ return ASN1_DER_ERROR; ++ ++ *ret_len = *str_len + len_len; ++ if (str_size >= *str_len) ++ { ++ if (*str_len > 0 && str != NULL) ++ memcpy (str, der + len_len, *str_len); ++ } ++ else ++ { ++ return ASN1_MEM_ERROR; ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/*- ++ * _asn1_get_time_der: ++ * @type: %ASN1_ETYPE_GENERALIZED_TIME or %ASN1_ETYPE_UTC_TIME ++ * @der: DER data to decode containing the time ++ * @der_len: Length of DER data to decode. ++ * @ret_len: Output variable containing the length of the DER data. ++ * @str: Pre-allocated output buffer to put the textual time in. ++ * @str_size: Length of pre-allocated output buffer. ++ * @flags: Zero or %ASN1_DECODE_FLAG_STRICT_DER ++ * ++ * Performs basic checks in the DER encoded time object and returns its textual form. ++ * The textual form will be in the YYYYMMDD000000Z format for GeneralizedTime ++ * and YYMMDD000000Z for UTCTime. ++ * ++ * Returns: %ASN1_SUCCESS on success, or an error. ++ -*/ ++static int ++_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *ret_len, ++ char *str, int str_size, unsigned flags) ++{ ++ int len_len, str_len; ++ unsigned i; ++ unsigned sign_count = 0; ++ unsigned dot_count = 0; ++ const unsigned char *p; ++ ++ if (der_len <= 0 || str == NULL) ++ return ASN1_DER_ERROR; ++ ++ str_len = asn1_get_length_der (der, der_len, &len_len); ++ if (str_len <= 0 || str_size < str_len) ++ return ASN1_DER_ERROR; ++ ++ /* perform some sanity checks on the data */ ++ if (str_len < 8) ++ { ++ warn(); ++ return ASN1_TIME_ENCODING_ERROR; ++ } ++ ++ if ((flags & ASN1_DECODE_FLAG_STRICT_DER) && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME)) ++ { ++ p = &der[len_len]; ++ for (i=0;i<(unsigned)(str_len-1);i++) ++ { ++ if (c_isdigit(p[i]) == 0) ++ { ++ if (type == ASN1_ETYPE_GENERALIZED_TIME) ++ { ++ /* tolerate lax encodings */ ++ if (p[i] == '.' && dot_count == 0) ++ { ++ dot_count++; ++ continue; ++ } ++ ++ /* This is not really valid DER, but there are ++ * structures using that */ ++ if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && ++ (p[i] == '+' || p[i] == '-') && sign_count == 0) ++ { ++ sign_count++; ++ continue; ++ } ++ } ++ ++ warn(); ++ return ASN1_TIME_ENCODING_ERROR; ++ } ++ } ++ ++ if (sign_count == 0 && p[str_len-1] != 'Z') ++ { ++ warn(); ++ return ASN1_TIME_ENCODING_ERROR; ++ } ++ } ++ memcpy (str, der + len_len, str_len); ++ str[str_len] = 0; ++ *ret_len = str_len + len_len; ++ ++ return ASN1_SUCCESS; ++} ++ ++/** ++ * asn1_get_object_id_der: ++ * @der: DER data to decode containing the OBJECT IDENTIFIER ++ * @der_len: Length of DER data to decode. ++ * @ret_len: Output variable containing the length of the DER data. ++ * @str: Pre-allocated output buffer to put the textual object id in. ++ * @str_size: Length of pre-allocated output buffer. ++ * ++ * Converts a DER encoded object identifier to its textual form. This ++ * function expects the DER object identifier without the tag. ++ * ++ * Returns: %ASN1_SUCCESS on success, or an error. ++ **/ ++int ++asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len, ++ char *str, int str_size) ++{ ++ int len_len, len, k; ++ int leading, parsed; ++ char temp[LTOSTR_MAX_SIZE]; ++ uint64_t val, val1, val0; ++ ++ *ret_len = 0; ++ if (str && str_size > 0) ++ str[0] = 0; /* no oid */ ++ ++ if (str == NULL || der_len <= 0) ++ return ASN1_GENERIC_ERROR; ++ ++ len = asn1_get_length_der (der, der_len, &len_len); ++ ++ if (len <= 0 || len + len_len > der_len) ++ return ASN1_DER_ERROR; ++ ++ /* leading octet can never be 0x80 */ ++ if (der[len_len] == 0x80) ++ return ASN1_DER_ERROR; ++ ++ val0 = 0; ++ ++ for (k = 0; k < len; k++) ++ { ++ if (INT_LEFT_SHIFT_OVERFLOW (val0, 7)) ++ return ASN1_DER_ERROR; ++ ++ val0 <<= 7; ++ val0 |= der[len_len + k] & 0x7F; ++ if (!(der[len_len + k] & 0x80)) ++ break; ++ } ++ parsed = ++k; ++ ++ /* val0 = (X*40) + Y, X={0,1,2}, Y<=39 when X={0,1} */ ++ /* X = val, Y = val1 */ ++ ++ /* check if X == 0 */ ++ val = 0; ++ val1 = val0; ++ if (val1 > 39) ++ { ++ val = 1; ++ val1 = val0 - 40; ++ if (val1 > 39) ++ { ++ val = 2; ++ val1 = val0 - 80; ++ } ++ } ++ ++ _asn1_str_cpy (str, str_size, _asn1_ltostr (val, temp)); ++ _asn1_str_cat (str, str_size, "."); ++ _asn1_str_cat (str, str_size, _asn1_ltostr (val1, temp)); ++ ++ val = 0; ++ leading = 1; ++ for (k = parsed; k < len; k++) ++ { ++ /* X.690 mandates that the leading byte must never be 0x80 ++ */ ++ if (leading != 0 && der[len_len + k] == 0x80) ++ return ASN1_DER_ERROR; ++ leading = 0; ++ ++ /* check for wrap around */ ++ if (INT_LEFT_SHIFT_OVERFLOW (val, 7)) ++ return ASN1_DER_ERROR; ++ ++ val = val << 7; ++ val |= der[len_len + k] & 0x7F; ++ ++ if (!(der[len_len + k] & 0x80)) ++ { ++ _asn1_str_cat (str, str_size, "."); ++ _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp)); ++ val = 0; ++ leading = 1; ++ } ++ } ++ ++ if (INT_ADD_OVERFLOW (len, len_len)) ++ return ASN1_DER_ERROR; ++ ++ *ret_len = len + len_len; ++ ++ return ASN1_SUCCESS; ++} ++ ++/** ++ * asn1_get_bit_der: ++ * @der: DER data to decode containing the BIT SEQUENCE. ++ * @der_len: Length of DER data to decode. ++ * @ret_len: Output variable containing the length of the DER data. ++ * @str: Pre-allocated output buffer to put decoded BIT SEQUENCE in. ++ * @str_size: Length of pre-allocated output buffer. ++ * @bit_len: Output variable containing the size of the BIT SEQUENCE. ++ * ++ * Extract a BIT SEQUENCE from DER data. ++ * ++ * Returns: %ASN1_SUCCESS on success, or an error. ++ **/ ++int ++asn1_get_bit_der (const unsigned char *der, int der_len, ++ int *ret_len, unsigned char *str, int str_size, ++ int *bit_len) ++{ ++ int len_len = 0, len_byte; ++ ++ if (der_len <= 0) ++ return ASN1_GENERIC_ERROR; ++ ++ len_byte = asn1_get_length_der (der, der_len, &len_len) - 1; ++ if (len_byte < 0) ++ return ASN1_DER_ERROR; ++ ++ *ret_len = len_byte + len_len + 1; ++ *bit_len = len_byte * 8 - der[len_len]; ++ ++ if (*bit_len < 0) ++ return ASN1_DER_ERROR; ++ ++ if (str_size >= len_byte) ++ { ++ if (len_byte > 0 && str) ++ memcpy (str, der + len_len + 1, len_byte); ++ } ++ else ++ { ++ return ASN1_MEM_ERROR; ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++/* tag_len: the total tag length (explicit+inner) ++ * inner_tag_len: the inner_tag length ++ */ ++static int ++_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, ++ int *tag_len, int *inner_tag_len, unsigned flags) ++{ ++ asn1_node p; ++ int counter, len2, len3, is_tag_implicit; ++ int result; ++ unsigned long tag, tag_implicit = 0; ++ unsigned char class, class2, class_implicit = 0; ++ ++ if (der_len <= 0) ++ return ASN1_GENERIC_ERROR; ++ ++ counter = is_tag_implicit = 0; ++ ++ if (node->type & CONST_TAG) ++ { ++ p = node->down; ++ while (p) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_TAG) ++ { ++ if (p->type & CONST_APPLICATION) ++ class2 = ASN1_CLASS_APPLICATION; ++ else if (p->type & CONST_UNIVERSAL) ++ class2 = ASN1_CLASS_UNIVERSAL; ++ else if (p->type & CONST_PRIVATE) ++ class2 = ASN1_CLASS_PRIVATE; ++ else ++ class2 = ASN1_CLASS_CONTEXT_SPECIFIC; ++ ++ if (p->type & CONST_EXPLICIT) ++ { ++ if (asn1_get_tag_der ++ (der + counter, der_len, &class, &len2, ++ &tag) != ASN1_SUCCESS) ++ return ASN1_DER_ERROR; ++ ++ DECR_LEN(der_len, len2); ++ counter += len2; ++ ++ if (flags & ASN1_DECODE_FLAG_STRICT_DER) ++ len3 = ++ asn1_get_length_der (der + counter, der_len, ++ &len2); ++ else ++ len3 = ++ asn1_get_length_ber (der + counter, der_len, ++ &len2); ++ if (len3 < 0) ++ return ASN1_DER_ERROR; ++ ++ DECR_LEN(der_len, len2); ++ counter += len2; ++ ++ if (!is_tag_implicit) ++ { ++ if ((class != (class2 | ASN1_CLASS_STRUCTURED)) || ++ (tag != strtoul ((char *) p->value, NULL, 10))) ++ return ASN1_TAG_ERROR; ++ } ++ else ++ { /* ASN1_TAG_IMPLICIT */ ++ if ((class != class_implicit) || (tag != tag_implicit)) ++ return ASN1_TAG_ERROR; ++ } ++ is_tag_implicit = 0; ++ } ++ else ++ { /* ASN1_TAG_IMPLICIT */ ++ if (!is_tag_implicit) ++ { ++ if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || ++ (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) ++ || (type_field (node->type) == ASN1_ETYPE_SET) ++ || (type_field (node->type) == ASN1_ETYPE_SET_OF)) ++ class2 |= ASN1_CLASS_STRUCTURED; ++ class_implicit = class2; ++ tag_implicit = strtoul ((char *) p->value, NULL, 10); ++ is_tag_implicit = 1; ++ } ++ } ++ } ++ p = p->right; ++ } ++ } ++ ++ if (is_tag_implicit) ++ { ++ if (asn1_get_tag_der ++ (der + counter, der_len, &class, &len2, ++ &tag) != ASN1_SUCCESS) ++ return ASN1_DER_ERROR; ++ ++ DECR_LEN(der_len, len2); ++ ++ if ((class != class_implicit) || (tag != tag_implicit)) ++ { ++ if (type_field (node->type) == ASN1_ETYPE_OCTET_STRING) ++ { ++ class_implicit |= ASN1_CLASS_STRUCTURED; ++ if ((class != class_implicit) || (tag != tag_implicit)) ++ return ASN1_TAG_ERROR; ++ } ++ else ++ return ASN1_TAG_ERROR; ++ } ++ } ++ else ++ { ++ unsigned type = type_field (node->type); ++ if (type == ASN1_ETYPE_TAG) ++ { ++ *tag_len = 0; ++ if (inner_tag_len) ++ *inner_tag_len = 0; ++ return ASN1_SUCCESS; ++ } ++ ++ if (asn1_get_tag_der ++ (der + counter, der_len, &class, &len2, ++ &tag) != ASN1_SUCCESS) ++ return ASN1_DER_ERROR; ++ ++ DECR_LEN(der_len, len2); ++ ++ switch (type) ++ { ++ case ASN1_ETYPE_NULL: ++ case ASN1_ETYPE_BOOLEAN: ++ case ASN1_ETYPE_INTEGER: ++ case ASN1_ETYPE_ENUMERATED: ++ case ASN1_ETYPE_OBJECT_ID: ++ case ASN1_ETYPE_GENERALSTRING: ++ case ASN1_ETYPE_NUMERIC_STRING: ++ case ASN1_ETYPE_IA5_STRING: ++ case ASN1_ETYPE_TELETEX_STRING: ++ case ASN1_ETYPE_PRINTABLE_STRING: ++ case ASN1_ETYPE_UNIVERSAL_STRING: ++ case ASN1_ETYPE_BMP_STRING: ++ case ASN1_ETYPE_UTF8_STRING: ++ case ASN1_ETYPE_VISIBLE_STRING: ++ case ASN1_ETYPE_BIT_STRING: ++ case ASN1_ETYPE_SEQUENCE: ++ case ASN1_ETYPE_SEQUENCE_OF: ++ case ASN1_ETYPE_SET: ++ case ASN1_ETYPE_SET_OF: ++ case ASN1_ETYPE_GENERALIZED_TIME: ++ case ASN1_ETYPE_UTC_TIME: ++ if ((class != _asn1_tags[type].class) ++ || (tag != _asn1_tags[type].tag)) ++ return ASN1_DER_ERROR; ++ break; ++ ++ case ASN1_ETYPE_OCTET_STRING: ++ /* OCTET STRING is handled differently to allow ++ * BER encodings (structured class). */ ++ if (((class != ASN1_CLASS_UNIVERSAL) ++ && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))) ++ || (tag != ASN1_TAG_OCTET_STRING)) ++ return ASN1_DER_ERROR; ++ break; ++ case ASN1_ETYPE_ANY: ++ counter -= len2; ++ break; ++ case ASN1_ETYPE_CHOICE: ++ counter -= len2; ++ break; ++ default: ++ return ASN1_DER_ERROR; ++ break; ++ } ++ } ++ ++ counter += len2; ++ *tag_len = counter; ++ if (inner_tag_len) ++ *inner_tag_len = len2; ++ return ASN1_SUCCESS; ++ ++cleanup: ++ return result; ++} ++ ++static int ++extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len, ++ int *ret_len, int *inner_len, unsigned flags) ++{ ++asn1_node p; ++int ris = ASN1_DER_ERROR; ++ ++ if (type_field (node->type) == ASN1_ETYPE_CHOICE) ++ { ++ p = node->down; ++ while (p) ++ { ++ ris = _asn1_extract_tag_der (p, der, der_len, ret_len, inner_len, flags); ++ if (ris == ASN1_SUCCESS) ++ break; ++ p = p->right; ++ } ++ ++ *ret_len = 0; ++ return ris; ++ } ++ else ++ return _asn1_extract_tag_der (node, der, der_len, ret_len, inner_len, flags); ++} ++ ++static int ++_asn1_delete_not_used (asn1_node node) ++{ ++ asn1_node p, p2; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node; ++ while (p) ++ { ++ if (p->type & CONST_NOT_USED) ++ { ++ p2 = NULL; ++ if (p != node) ++ { ++ p2 = _asn1_find_left (p); ++ if (!p2) ++ p2 = _asn1_find_up (p); ++ } ++ asn1_delete_structure (&p); ++ p = p2; ++ } ++ ++ if (!p) ++ break; /* reach node */ ++ ++ if (p->down) ++ { ++ p = p->down; ++ } ++ else ++ { ++ if (p == node) ++ p = NULL; ++ else if (p->right) ++ p = p->right; ++ else ++ { ++ while (1) ++ { ++ p = _asn1_find_up (p); ++ if (p == node) ++ { ++ p = NULL; ++ break; ++ } ++ if (p->right) ++ { ++ p = p->right; ++ break; ++ } ++ } ++ } ++ } ++ } ++ return ASN1_SUCCESS; ++} ++ ++static int ++_asn1_get_indefinite_length_string (const unsigned char *der, ++ int der_len, int *len) ++{ ++ int len2, len3, counter, indefinite; ++ int result; ++ unsigned long tag; ++ unsigned char class; ++ ++ counter = indefinite = 0; ++ ++ while (1) ++ { ++ if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0)) ++ { ++ counter += 2; ++ DECR_LEN(der_len, 2); ++ ++ indefinite--; ++ if (indefinite <= 0) ++ break; ++ else ++ continue; ++ } ++ ++ if (asn1_get_tag_der ++ (der + counter, der_len, &class, &len2, ++ &tag) != ASN1_SUCCESS) ++ return ASN1_DER_ERROR; ++ ++ DECR_LEN(der_len, len2); ++ counter += len2; ++ ++ len2 = asn1_get_length_der (der + counter, der_len, &len3); ++ if (len2 < -1) ++ return ASN1_DER_ERROR; ++ ++ if (len2 == -1) ++ { ++ indefinite++; ++ counter += 1; ++ DECR_LEN(der_len, 1); ++ } ++ else ++ { ++ counter += len2 + len3; ++ DECR_LEN(der_len, len2+len3); ++ } ++ } ++ ++ *len = counter; ++ return ASN1_SUCCESS; ++ ++cleanup: ++ return result; ++} ++ ++static void delete_unneeded_choice_fields(asn1_node p) ++{ ++ asn1_node p2; ++ ++ while (p->right) ++ { ++ p2 = p->right; ++ asn1_delete_structure (&p2); ++ } ++} ++ ++ ++/** ++ * asn1_der_decoding2 ++ * @element: pointer to an ASN1 structure. ++ * @ider: vector that contains the DER encoding. ++ * @max_ider_len: pointer to an integer giving the information about the ++ * maximal number of bytes occupied by *@ider. The real size of the DER ++ * encoding is returned through this pointer. ++ * @flags: flags controlling the behaviour of the function. ++ * @errorDescription: null-terminated string contains details when an ++ * error occurred. ++ * ++ * Fill the structure *@element with values of a DER encoding string. The ++ * structure must just be created with function asn1_create_element(). ++ * ++ * If %ASN1_DECODE_FLAG_ALLOW_PADDING flag is set then the function will ignore ++ * padding after the decoded DER data. Upon a successful return the value of ++ * *@max_ider_len will be set to the number of bytes decoded. ++ * ++ * If %ASN1_DECODE_FLAG_STRICT_DER flag is set then the function will ++ * not decode any BER-encoded elements. ++ * ++ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND ++ * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or ++ * %ASN1_DER_ERROR if the der encoding doesn't match the structure ++ * name (*@ELEMENT deleted). ++ **/ ++int ++asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, ++ unsigned int flags, char *errorDescription) ++{ ++ asn1_node node, p, p2, p3; ++ char temp[128]; ++ int counter, len2, len3, len4, move, ris, tlen; ++ struct node_tail_cache_st tcache = {NULL, NULL}; ++ unsigned char class; ++ unsigned long tag; ++ int tag_len; ++ int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len; ++ int inner_tag_len; ++ unsigned char *ptmp; ++ const unsigned char *ptag; ++ const unsigned char *der = ider; ++ ++ node = *element; ++ ++ if (errorDescription != NULL) ++ errorDescription[0] = 0; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ if (node->type & CONST_OPTION) ++ { ++ result = ASN1_GENERIC_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ counter = 0; ++ move = DOWN; ++ p = node; ++ while (1) ++ { ++ tag_len = 0; ++ inner_tag_len = 0; ++ ris = ASN1_SUCCESS; ++ if (move != UP) ++ { ++ if (p->type & CONST_SET) ++ { ++ p2 = _asn1_find_up (p); ++ len2 = p2->tmp_ival; ++ if (len2 == -1) ++ { ++ if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) ++ { ++ p = p2; ++ move = UP; ++ counter += 2; ++ DECR_LEN(ider_len, 2); ++ continue; ++ } ++ } ++ else if (counter == len2) ++ { ++ p = p2; ++ move = UP; ++ continue; ++ } ++ else if (counter > len2) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ p2 = p2->down; ++ while (p2) ++ { ++ if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) ++ { ++ ris = ++ extract_tag_der_recursive (p2, der + counter, ++ ider_len, &len2, NULL, flags); ++ if (ris == ASN1_SUCCESS) ++ { ++ p2->type &= ~CONST_NOT_USED; ++ p = p2; ++ break; ++ } ++ } ++ p2 = p2->right; ++ } ++ if (p2 == NULL) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ } ++ ++ /* the position in the DER structure this starts */ ++ p->start = counter; ++ p->end = total_len - 1; ++ ++ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) ++ { ++ p2 = _asn1_find_up (p); ++ len2 = p2->tmp_ival; ++ if (counter == len2) ++ { ++ if (p->right) ++ { ++ p2 = p->right; ++ move = RIGHT; ++ } ++ else ++ move = UP; ++ ++ if (p->type & CONST_OPTION) ++ asn1_delete_structure (&p); ++ ++ p = p2; ++ continue; ++ } ++ } ++ ++ if (type_field (p->type) == ASN1_ETYPE_CHOICE) ++ { ++ while (p->down) ++ { ++ ris = ++ extract_tag_der_recursive (p->down, der + counter, ++ ider_len, &len2, NULL, flags); ++ ++ if (ris == ASN1_SUCCESS) ++ { ++ delete_unneeded_choice_fields(p->down); ++ break; ++ } ++ else if (ris == ASN1_ERROR_TYPE_ANY) ++ { ++ result = ASN1_ERROR_TYPE_ANY; ++ warn(); ++ goto cleanup; ++ } ++ else ++ { ++ p2 = p->down; ++ asn1_delete_structure (&p2); ++ } ++ } ++ ++ if (p->down == NULL) ++ { ++ if (!(p->type & CONST_OPTION)) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ } ++ else if (type_field (p->type) != ASN1_ETYPE_CHOICE) ++ p = p->down; ++ ++ p->start = counter; ++ } ++ ++ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) ++ { ++ p2 = _asn1_find_up (p); ++ len2 = p2->tmp_ival; ++ ++ if ((len2 != -1) && (counter > len2)) ++ ris = ASN1_TAG_ERROR; ++ } ++ ++ if (ris == ASN1_SUCCESS) ++ ris = ++ extract_tag_der_recursive (p, der + counter, ider_len, ++ &tag_len, &inner_tag_len, flags); ++ ++ if (ris != ASN1_SUCCESS) ++ { ++ if (p->type & CONST_OPTION) ++ { ++ p->type |= CONST_NOT_USED; ++ move = RIGHT; ++ } ++ else if (p->type & CONST_DEFAULT) ++ { ++ _asn1_set_value (p, NULL, 0); ++ move = RIGHT; ++ } ++ else ++ { ++ if (errorDescription != NULL) ++ _asn1_error_description_tag_error (p, errorDescription); ++ ++ result = ASN1_TAG_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ } ++ else ++ { ++ DECR_LEN(ider_len, tag_len); ++ counter += tag_len; ++ } ++ } ++ ++ if (ris == ASN1_SUCCESS) ++ { ++ switch (type_field (p->type)) ++ { ++ case ASN1_ETYPE_NULL: ++ DECR_LEN(ider_len, 1); ++ if (der[counter]) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ counter++; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_BOOLEAN: ++ DECR_LEN(ider_len, 2); ++ ++ if (der[counter++] != 1) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ if (der[counter++] == 0) ++ _asn1_set_value (p, "F", 1); ++ else ++ _asn1_set_value (p, "T", 1); ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_INTEGER: ++ case ASN1_ETYPE_ENUMERATED: ++ len2 = ++ asn1_get_length_der (der + counter, ider_len, &len3); ++ if (len2 < 0) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len3+len2); ++ ++ _asn1_set_value (p, der + counter, len3 + len2); ++ counter += len3 + len2; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_OBJECT_ID: ++ result = ++ asn1_get_object_id_der (der + counter, ider_len, &len2, ++ temp, sizeof (temp)); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len2); ++ ++ tlen = strlen (temp); ++ if (tlen > 0) ++ _asn1_set_value (p, temp, tlen + 1); ++ ++ counter += len2; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_GENERALIZED_TIME: ++ case ASN1_ETYPE_UTC_TIME: ++ result = ++ _asn1_get_time_der (type_field (p->type), der + counter, ider_len, &len2, temp, ++ sizeof (temp) - 1, flags); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len2); ++ ++ tlen = strlen (temp); ++ if (tlen > 0) ++ _asn1_set_value (p, temp, tlen); ++ ++ counter += len2; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_OCTET_STRING: ++ if (counter < inner_tag_len) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ ptag = der + counter - inner_tag_len; ++ if ((flags & ASN1_DECODE_FLAG_STRICT_DER) || !(ptag[0] & ASN1_CLASS_STRUCTURED)) ++ { ++ if (ptag[0] & ASN1_CLASS_STRUCTURED) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ len2 = ++ asn1_get_length_der (der + counter, ider_len, &len3); ++ if (len2 < 0) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len3+len2); ++ ++ _asn1_set_value (p, der + counter, len3 + len2); ++ counter += len3 + len2; ++ } ++ else ++ { ++ unsigned dflags = 0, vlen, ber_len; ++ ++ if (ptag[0] & ASN1_CLASS_STRUCTURED) ++ dflags |= DECODE_FLAG_CONSTRUCTED; ++ ++ result = _asn1_decode_simple_ber(type_field (p->type), der+counter, ider_len, &ptmp, &vlen, &ber_len, dflags); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, ber_len); ++ ++ _asn1_set_value_lv (p, ptmp, vlen); ++ ++ counter += ber_len; ++ free(ptmp); ++ } ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_GENERALSTRING: ++ case ASN1_ETYPE_NUMERIC_STRING: ++ case ASN1_ETYPE_IA5_STRING: ++ case ASN1_ETYPE_TELETEX_STRING: ++ case ASN1_ETYPE_PRINTABLE_STRING: ++ case ASN1_ETYPE_UNIVERSAL_STRING: ++ case ASN1_ETYPE_BMP_STRING: ++ case ASN1_ETYPE_UTF8_STRING: ++ case ASN1_ETYPE_VISIBLE_STRING: ++ case ASN1_ETYPE_BIT_STRING: ++ len2 = ++ asn1_get_length_der (der + counter, ider_len, &len3); ++ if (len2 < 0) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len3+len2); ++ ++ _asn1_set_value (p, der + counter, len3 + len2); ++ counter += len3 + len2; ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_SEQUENCE: ++ case ASN1_ETYPE_SET: ++ if (move == UP) ++ { ++ len2 = p->tmp_ival; ++ p->tmp_ival = 0; ++ if (len2 == -1) ++ { /* indefinite length method */ ++ DECR_LEN(ider_len, 2); ++ if ((der[counter]) || der[counter + 1]) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ counter += 2; ++ } ++ else ++ { /* definite length method */ ++ if (len2 != counter) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ } ++ move = RIGHT; ++ } ++ else ++ { /* move==DOWN || move==RIGHT */ ++ len3 = ++ asn1_get_length_der (der + counter, ider_len, &len2); ++ if (IS_ERR(len3, flags)) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len2); ++ counter += len2; ++ ++ if (len3 > 0) ++ { ++ p->tmp_ival = counter + len3; ++ move = DOWN; ++ } ++ else if (len3 == 0) ++ { ++ p2 = p->down; ++ while (p2) ++ { ++ if (type_field (p2->type) != ASN1_ETYPE_TAG) ++ { ++ p3 = p2->right; ++ asn1_delete_structure (&p2); ++ p2 = p3; ++ } ++ else ++ p2 = p2->right; ++ } ++ move = RIGHT; ++ } ++ else ++ { /* indefinite length method */ ++ p->tmp_ival = -1; ++ move = DOWN; ++ } ++ } ++ break; ++ case ASN1_ETYPE_SEQUENCE_OF: ++ case ASN1_ETYPE_SET_OF: ++ if (move == UP) ++ { ++ len2 = p->tmp_ival; ++ if (len2 == -1) ++ { /* indefinite length method */ ++ if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1])) ++ { ++ result = _asn1_append_sequence_set (p, &tcache); ++ if (result != 0) ++ { ++ warn(); ++ goto cleanup; ++ } ++ p = tcache.tail; ++ move = RIGHT; ++ continue; ++ } ++ ++ p->tmp_ival = 0; ++ tcache.tail = NULL; /* finished decoding this structure */ ++ tcache.head = NULL; ++ DECR_LEN(ider_len, 2); ++ counter += 2; ++ } ++ else ++ { /* definite length method */ ++ if (len2 > counter) ++ { ++ result = _asn1_append_sequence_set (p, &tcache); ++ if (result != 0) ++ { ++ warn(); ++ goto cleanup; ++ } ++ p = tcache.tail; ++ move = RIGHT; ++ continue; ++ } ++ ++ p->tmp_ival = 0; ++ tcache.tail = NULL; /* finished decoding this structure */ ++ tcache.head = NULL; ++ ++ if (len2 != counter) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ } ++ } ++ else ++ { /* move==DOWN || move==RIGHT */ ++ len3 = ++ asn1_get_length_der (der + counter, ider_len, &len2); ++ if (IS_ERR(len3, flags)) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len2); ++ counter += len2; ++ if (len3) ++ { ++ if (len3 > 0) ++ { /* definite length method */ ++ p->tmp_ival = counter + len3; ++ } ++ else ++ { /* indefinite length method */ ++ p->tmp_ival = -1; ++ } ++ ++ p2 = p->down; ++ if (p2 == NULL) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ while ((type_field (p2->type) == ASN1_ETYPE_TAG) ++ || (type_field (p2->type) == ASN1_ETYPE_SIZE)) ++ p2 = p2->right; ++ if (p2->right == NULL) ++ { ++ result = _asn1_append_sequence_set (p, &tcache); ++ if (result != 0) ++ { ++ warn(); ++ goto cleanup; ++ } ++ } ++ p = p2; ++ } ++ } ++ move = RIGHT; ++ break; ++ case ASN1_ETYPE_ANY: ++ /* Check indefinite lenth method in an EXPLICIT TAG */ ++ ++ if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && (p->type & CONST_TAG) && ++ tag_len == 2 && (der[counter - 1] == 0x80)) ++ indefinite = 1; ++ else ++ indefinite = 0; ++ ++ if (asn1_get_tag_der ++ (der + counter, ider_len, &class, &len2, ++ &tag) != ASN1_SUCCESS) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len2); ++ ++ len4 = ++ asn1_get_length_der (der + counter + len2, ++ ider_len, &len3); ++ if (IS_ERR(len4, flags)) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ if (len4 != -1) /* definite */ ++ { ++ len2 += len4; ++ ++ DECR_LEN(ider_len, len4+len3); ++ _asn1_set_value_lv (p, der + counter, len2 + len3); ++ counter += len2 + len3; ++ } ++ else /* == -1 */ ++ { /* indefinite length */ ++ ider_len += len2; /* undo DECR_LEN */ ++ ++ if (counter == 0) ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ ++ result = ++ _asn1_get_indefinite_length_string (der + counter, ider_len, &len2); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ DECR_LEN(ider_len, len2); ++ _asn1_set_value_lv (p, der + counter, len2); ++ counter += len2; ++ ++ } ++ ++ /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with ++ an indefinite length method. */ ++ if (indefinite) ++ { ++ DECR_LEN(ider_len, 2); ++ if (!der[counter] && !der[counter + 1]) ++ { ++ counter += 2; ++ } ++ else ++ { ++ result = ASN1_DER_ERROR; ++ warn(); ++ goto cleanup; ++ } ++ } ++ ++ move = RIGHT; ++ break; ++ default: ++ move = (move == UP) ? RIGHT : DOWN; ++ break; ++ } ++ } ++ ++ if (p) ++ { ++ p->end = counter - 1; ++ } ++ ++ if (p == node && move != DOWN) ++ break; ++ ++ if (move == DOWN) ++ { ++ if (p->down) ++ p = p->down; ++ else ++ move = RIGHT; ++ } ++ if ((move == RIGHT) && !(p->type & CONST_SET)) ++ { ++ if (p->right) ++ p = p->right; ++ else ++ move = UP; ++ } ++ if (move == UP) ++ p = _asn1_find_up (p); ++ } ++ ++ _asn1_delete_not_used (*element); ++ ++ if ((ider_len < 0) || ++ (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0))) ++ { ++ warn(); ++ result = ASN1_DER_ERROR; ++ goto cleanup; ++ } ++ ++ *max_ider_len = total_len - ider_len; ++ ++ return ASN1_SUCCESS; ++ ++cleanup: ++ asn1_delete_structure (element); ++ return result; ++} ++ ++ ++/** ++ * asn1_der_decoding: ++ * @element: pointer to an ASN1 structure. ++ * @ider: vector that contains the DER encoding. ++ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]. ++ * @errorDescription: null-terminated string contains details when an ++ * error occurred. ++ * ++ * Fill the structure *@element with values of a DER encoding ++ * string. The structure must just be created with function ++ * asn1_create_element(). ++ * ++ * Note that the *@element variable is provided as a pointer for ++ * historical reasons. ++ * ++ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND ++ * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or ++ * %ASN1_DER_ERROR if the der encoding doesn't match the structure ++ * name (*@ELEMENT deleted). ++ **/ ++int ++asn1_der_decoding (asn1_node * element, const void *ider, int ider_len, ++ char *errorDescription) ++{ ++ return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription); ++} ++ ++/** ++ * asn1_der_decoding_element: ++ * @structure: pointer to an ASN1 structure ++ * @elementName: name of the element to fill ++ * @ider: vector that contains the DER encoding of the whole structure. ++ * @len: number of bytes of *der: der[0]..der[len-1] ++ * @errorDescription: null-terminated string contains details when an ++ * error occurred. ++ * ++ * Fill the element named @ELEMENTNAME with values of a DER encoding ++ * string. The structure must just be created with function ++ * asn1_create_element(). The DER vector must contain the encoding ++ * string of the whole @STRUCTURE. If an error occurs during the ++ * decoding procedure, the *@STRUCTURE is deleted and set equal to ++ * %NULL. ++ * ++ * This function is deprecated and may just be an alias to asn1_der_decoding ++ * in future versions. Use asn1_der_decoding() instead. ++ * ++ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND ++ * if ELEMENT is %NULL or @elementName == NULL, and ++ * %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't ++ * match the structure @structure (*ELEMENT deleted). ++ **/ ++int ++asn1_der_decoding_element (asn1_node * structure, const char *elementName, ++ const void *ider, int len, char *errorDescription) ++{ ++ return asn1_der_decoding(structure, ider, len, errorDescription); ++} ++ ++/** ++ * asn1_der_decoding_startEnd: ++ * @element: pointer to an ASN1 element ++ * @ider: vector that contains the DER encoding. ++ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1] ++ * @name_element: an element of NAME structure. ++ * @start: the position of the first byte of NAME_ELEMENT decoding ++ * (@ider[*start]) ++ * @end: the position of the last byte of NAME_ELEMENT decoding ++ * (@ider[*end]) ++ * ++ * Find the start and end point of an element in a DER encoding ++ * string. I mean that if you have a der encoding and you have already ++ * used the function asn1_der_decoding() to fill a structure, it may ++ * happen that you want to find the piece of string concerning an ++ * element of the structure. ++ * ++ * One example is the sequence "tbsCertificate" inside an X509 ++ * certificate. ++ * ++ * Note that since libtasn1 3.7 the @ider and @ider_len parameters ++ * can be omitted, if the element is already decoded using asn1_der_decoding(). ++ * ++ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND ++ * if ELEMENT is %asn1_node EMPTY or @name_element is not a valid ++ * element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding ++ * doesn't match the structure ELEMENT. ++ **/ ++int ++asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len, ++ const char *name_element, int *start, int *end) ++{ ++ asn1_node node, node_to_find; ++ int result = ASN1_DER_ERROR; ++ ++ node = element; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ node_to_find = asn1_find_node (node, name_element); ++ ++ if (node_to_find == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ *start = node_to_find->start; ++ *end = node_to_find->end; ++ ++ if (*start == 0 && *end == 0) ++ { ++ if (ider == NULL || ider_len == 0) ++ return ASN1_GENERIC_ERROR; ++ ++ /* it seems asn1_der_decoding() wasn't called before. Do it now */ ++ result = asn1_der_decoding (&node, ider, ider_len, NULL); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ return result; ++ } ++ ++ node_to_find = asn1_find_node (node, name_element); ++ if (node_to_find == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ *start = node_to_find->start; ++ *end = node_to_find->end; ++ } ++ ++ if (*end < *start) ++ return ASN1_GENERIC_ERROR; ++ ++ return ASN1_SUCCESS; ++} ++ ++/** ++ * asn1_expand_any_defined_by: ++ * @definitions: ASN1 definitions ++ * @element: pointer to an ASN1 structure ++ * ++ * Expands every "ANY DEFINED BY" element of a structure created from ++ * a DER decoding process (asn1_der_decoding function). The element ++ * ANY must be defined by an OBJECT IDENTIFIER. The type used to ++ * expand the element ANY is the first one following the definition of ++ * the actual value of the OBJECT IDENTIFIER. ++ * ++ * Returns: %ASN1_SUCCESS if Substitution OK, %ASN1_ERROR_TYPE_ANY if ++ * some "ANY DEFINED BY" element couldn't be expanded due to a ++ * problem in OBJECT_ID -> TYPE association, or other error codes ++ * depending on DER decoding. ++ **/ ++int ++asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element) ++{ ++ char name[2 * ASN1_MAX_NAME_SIZE + 2], ++ value[ASN1_MAX_NAME_SIZE]; ++ int retCode = ASN1_SUCCESS, result; ++ int len, len2, len3; ++ asn1_node_const p2; ++ asn1_node p, p3, aux = NULL; ++ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; ++ const char *definitionsName; ++ ++ if ((definitions == NULL) || (*element == NULL)) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ definitionsName = definitions->name; ++ ++ p = *element; ++ while (p) ++ { ++ ++ switch (type_field (p->type)) ++ { ++ case ASN1_ETYPE_ANY: ++ if ((p->type & CONST_DEFINED_BY) && (p->value)) ++ { ++ /* search the "DEF_BY" element */ ++ p2 = p->down; ++ while ((p2) && (type_field (p2->type) != ASN1_ETYPE_CONSTANT)) ++ p2 = p2->right; ++ ++ if (!p2) ++ { ++ retCode = ASN1_ERROR_TYPE_ANY; ++ break; ++ } ++ ++ p3 = _asn1_find_up (p); ++ ++ if (!p3) ++ { ++ retCode = ASN1_ERROR_TYPE_ANY; ++ break; ++ } ++ ++ p3 = p3->down; ++ while (p3) ++ { ++ if (!(strcmp (p3->name, p2->name))) ++ break; ++ p3 = p3->right; ++ } ++ ++ if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || ++ (p3->value == NULL)) ++ { ++ ++ p3 = _asn1_find_up (p); ++ p3 = _asn1_find_up (p3); ++ ++ if (!p3) ++ { ++ retCode = ASN1_ERROR_TYPE_ANY; ++ break; ++ } ++ ++ p3 = p3->down; ++ ++ while (p3) ++ { ++ if (!(strcmp (p3->name, p2->name))) ++ break; ++ p3 = p3->right; ++ } ++ ++ if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) ++ || (p3->value == NULL)) ++ { ++ retCode = ASN1_ERROR_TYPE_ANY; ++ break; ++ } ++ } ++ ++ /* search the OBJECT_ID into definitions */ ++ p2 = definitions->down; ++ while (p2) ++ { ++ if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && ++ (p2->type & CONST_ASSIGN)) ++ { ++ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); ++ ++ len = ASN1_MAX_NAME_SIZE; ++ result = ++ asn1_read_value (definitions, name, value, &len); ++ ++ if ((result == ASN1_SUCCESS) ++ && (!_asn1_strcmp (p3->value, value))) ++ { ++ p2 = p2->right; /* pointer to the structure to ++ use for expansion */ ++ while ((p2) && (p2->type & CONST_ASSIGN)) ++ p2 = p2->right; ++ ++ if (p2) ++ { ++ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); ++ ++ result = ++ asn1_create_element (definitions, name, &aux); ++ if (result == ASN1_SUCCESS) ++ { ++ _asn1_cpy_name (aux, p); ++ len2 = ++ asn1_get_length_der (p->value, ++ p->value_len, &len3); ++ if (len2 < 0) ++ return ASN1_DER_ERROR; ++ ++ result = ++ asn1_der_decoding (&aux, p->value + len3, ++ len2, ++ errorDescription); ++ if (result == ASN1_SUCCESS) ++ { ++ ++ _asn1_set_right (aux, p->right); ++ _asn1_set_right (p, aux); ++ ++ result = asn1_delete_structure (&p); ++ if (result == ASN1_SUCCESS) ++ { ++ p = aux; ++ aux = NULL; ++ break; ++ } ++ else ++ { /* error with asn1_delete_structure */ ++ asn1_delete_structure (&aux); ++ retCode = result; ++ break; ++ } ++ } ++ else ++ { /* error with asn1_der_decoding */ ++ retCode = result; ++ break; ++ } ++ } ++ else ++ { /* error with asn1_create_element */ ++ retCode = result; ++ break; ++ } ++ } ++ else ++ { /* error with the pointer to the structure to exapand */ ++ retCode = ASN1_ERROR_TYPE_ANY; ++ break; ++ } ++ } ++ } ++ p2 = p2->right; ++ } /* end while */ ++ ++ if (!p2) ++ { ++ retCode = ASN1_ERROR_TYPE_ANY; ++ break; ++ } ++ ++ } ++ break; ++ default: ++ break; ++ } ++ ++ ++ if (p->down) ++ { ++ p = p->down; ++ } ++ else if (p == *element) ++ { ++ p = NULL; ++ break; ++ } ++ else if (p->right) ++ p = p->right; ++ else ++ { ++ while (1) ++ { ++ p = _asn1_find_up (p); ++ if (p == *element) ++ { ++ p = NULL; ++ break; ++ } ++ if (p->right) ++ { ++ p = p->right; ++ break; ++ } ++ } ++ } ++ } ++ ++ return retCode; ++} ++ ++/** ++ * asn1_expand_octet_string: ++ * @definitions: ASN1 definitions ++ * @element: pointer to an ASN1 structure ++ * @octetName: name of the OCTECT STRING field to expand. ++ * @objectName: name of the OBJECT IDENTIFIER field to use to define ++ * the type for expansion. ++ * ++ * Expands an "OCTET STRING" element of a structure created from a DER ++ * decoding process (the asn1_der_decoding() function). The type used ++ * for expansion is the first one following the definition of the ++ * actual value of the OBJECT IDENTIFIER indicated by OBJECTNAME. ++ * ++ * Returns: %ASN1_SUCCESS if substitution OK, %ASN1_ELEMENT_NOT_FOUND ++ * if @objectName or @octetName are not correct, ++ * %ASN1_VALUE_NOT_VALID if it wasn't possible to find the type to ++ * use for expansion, or other errors depending on DER decoding. ++ **/ ++int ++asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, ++ const char *octetName, const char *objectName) ++{ ++ char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; ++ int retCode = ASN1_SUCCESS, result; ++ int len, len2, len3; ++ asn1_node_const p2; ++ asn1_node aux = NULL; ++ asn1_node octetNode = NULL, objectNode = NULL; ++ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; ++ ++ if ((definitions == NULL) || (*element == NULL)) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ octetNode = asn1_find_node (*element, octetName); ++ if (octetNode == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ if (type_field (octetNode->type) != ASN1_ETYPE_OCTET_STRING) ++ return ASN1_ELEMENT_NOT_FOUND; ++ if (octetNode->value == NULL) ++ return ASN1_VALUE_NOT_FOUND; ++ ++ objectNode = asn1_find_node (*element, objectName); ++ if (objectNode == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ if (type_field (objectNode->type) != ASN1_ETYPE_OBJECT_ID) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ if (objectNode->value == NULL) ++ return ASN1_VALUE_NOT_FOUND; ++ ++ ++ /* search the OBJECT_ID into definitions */ ++ p2 = definitions->down; ++ while (p2) ++ { ++ if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && ++ (p2->type & CONST_ASSIGN)) ++ { ++ strcpy (name, definitions->name); ++ strcat (name, "."); ++ strcat (name, p2->name); ++ ++ len = sizeof (value); ++ result = asn1_read_value (definitions, name, value, &len); ++ ++ if ((result == ASN1_SUCCESS) ++ && (!_asn1_strcmp (objectNode->value, value))) ++ { ++ ++ p2 = p2->right; /* pointer to the structure to ++ use for expansion */ ++ while ((p2) && (p2->type & CONST_ASSIGN)) ++ p2 = p2->right; ++ ++ if (p2) ++ { ++ strcpy (name, definitions->name); ++ strcat (name, "."); ++ strcat (name, p2->name); ++ ++ result = asn1_create_element (definitions, name, &aux); ++ if (result == ASN1_SUCCESS) ++ { ++ _asn1_cpy_name (aux, octetNode); ++ len2 = ++ asn1_get_length_der (octetNode->value, ++ octetNode->value_len, &len3); ++ if (len2 < 0) ++ return ASN1_DER_ERROR; ++ ++ result = ++ asn1_der_decoding (&aux, octetNode->value + len3, ++ len2, errorDescription); ++ if (result == ASN1_SUCCESS) ++ { ++ ++ _asn1_set_right (aux, octetNode->right); ++ _asn1_set_right (octetNode, aux); ++ ++ result = asn1_delete_structure (&octetNode); ++ if (result == ASN1_SUCCESS) ++ { ++ aux = NULL; ++ break; ++ } ++ else ++ { /* error with asn1_delete_structure */ ++ asn1_delete_structure (&aux); ++ retCode = result; ++ break; ++ } ++ } ++ else ++ { /* error with asn1_der_decoding */ ++ retCode = result; ++ break; ++ } ++ } ++ else ++ { /* error with asn1_create_element */ ++ retCode = result; ++ break; ++ } ++ } ++ else ++ { /* error with the pointer to the structure to exapand */ ++ retCode = ASN1_VALUE_NOT_VALID; ++ break; ++ } ++ } ++ } ++ ++ p2 = p2->right; ++ ++ } ++ ++ if (!p2) ++ retCode = ASN1_VALUE_NOT_VALID; ++ ++ return retCode; ++} ++ ++/*- ++ * _asn1_decode_simple_der: ++ * @etype: The type of the string to be encoded (ASN1_ETYPE_) ++ * @der: the encoded string ++ * @_der_len: the bytes of the encoded string ++ * @str: a pointer to the data ++ * @str_len: the length of the data ++ * @dflags: DECODE_FLAG_* ++ * ++ * Decodes a simple DER encoded type (e.g. a string, which is not constructed). ++ * The output is a pointer inside the @der. ++ * ++ * Returns: %ASN1_SUCCESS if successful or an error value. ++ -*/ ++static int ++_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, const unsigned char **str, ++ unsigned int *str_len, unsigned dflags) ++{ ++ int tag_len, len_len; ++ const unsigned char *p; ++ int der_len = _der_len; ++ unsigned char class; ++ unsigned long tag; ++ long ret; ++ ++ if (der == NULL || der_len == 0) ++ return ASN1_VALUE_NOT_VALID; ++ ++ if (ETYPE_OK (etype) == 0 || ETYPE_IS_STRING(etype) == 0) ++ return ASN1_VALUE_NOT_VALID; ++ ++ /* doesn't handle constructed classes */ ++ class = ETYPE_CLASS(etype); ++ if (class != ASN1_CLASS_UNIVERSAL) ++ return ASN1_VALUE_NOT_VALID; ++ ++ p = der; ++ ++ if (dflags & DECODE_FLAG_HAVE_TAG) ++ { ++ ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); ++ if (ret != ASN1_SUCCESS) ++ return ret; ++ ++ if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype)) ++ { ++ warn(); ++ return ASN1_DER_ERROR; ++ } ++ ++ p += tag_len; ++ der_len -= tag_len; ++ if (der_len <= 0) ++ return ASN1_DER_ERROR; ++ } ++ ++ ret = asn1_get_length_der (p, der_len, &len_len); ++ if (ret < 0) ++ return ASN1_DER_ERROR; ++ ++ p += len_len; ++ der_len -= len_len; ++ if (der_len <= 0) ++ return ASN1_DER_ERROR; ++ ++ *str_len = ret; ++ *str = p; ++ ++ return ASN1_SUCCESS; ++} ++ ++/** ++ * asn1_decode_simple_der: ++ * @etype: The type of the string to be encoded (ASN1_ETYPE_) ++ * @der: the encoded string ++ * @_der_len: the bytes of the encoded string ++ * @str: a pointer to the data ++ * @str_len: the length of the data ++ * ++ * Decodes a simple DER encoded type (e.g. a string, which is not constructed). ++ * The output is a pointer inside the @der. ++ * ++ * Returns: %ASN1_SUCCESS if successful or an error value. ++ **/ ++int ++asn1_decode_simple_der (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, const unsigned char **str, ++ unsigned int *str_len) ++{ ++ return _asn1_decode_simple_der(etype, der, _der_len, str, str_len, DECODE_FLAG_HAVE_TAG); ++} ++ ++static int append(uint8_t **dst, unsigned *dst_size, const unsigned char *src, unsigned src_size) ++{ ++ if (src_size == 0) ++ return ASN1_SUCCESS; ++ ++ *dst = _asn1_realloc(*dst, *dst_size+src_size); ++ if (*dst == NULL) ++ return ASN1_MEM_ALLOC_ERROR; ++ memcpy(*dst + *dst_size, src, src_size); ++ *dst_size += src_size; ++ return ASN1_SUCCESS; ++} ++ ++/*- ++ * _asn1_decode_simple_ber: ++ * @etype: The type of the string to be encoded (ASN1_ETYPE_) ++ * @der: the encoded string ++ * @_der_len: the bytes of the encoded string ++ * @str: a pointer to the data ++ * @str_len: the length of the data ++ * @ber_len: the total length occupied by BER (may be %NULL) ++ * @have_tag: whether a DER tag is included ++ * ++ * Decodes a BER encoded type. The output is an allocated value ++ * of the data. This decodes BER STRINGS only. Other types are ++ * decoded as DER. ++ * ++ * Returns: %ASN1_SUCCESS if successful or an error value. ++ -*/ ++static int ++_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, unsigned char **str, ++ unsigned int *str_len, unsigned int *ber_len, ++ unsigned dflags) ++{ ++ int tag_len, len_len; ++ const unsigned char *p; ++ int der_len = _der_len; ++ uint8_t *total = NULL; ++ unsigned total_size = 0; ++ unsigned char class; ++ unsigned long tag; ++ unsigned char *out = NULL; ++ const unsigned char *cout = NULL; ++ unsigned out_len; ++ long result; ++ ++ if (ber_len) *ber_len = 0; ++ ++ if (der == NULL || der_len == 0) ++ { ++ warn(); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ ++ if (ETYPE_OK (etype) == 0) ++ { ++ warn(); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ ++ /* doesn't handle constructed + definite classes */ ++ class = ETYPE_CLASS (etype); ++ if (class != ASN1_CLASS_UNIVERSAL) ++ { ++ warn(); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ ++ p = der; ++ ++ if (dflags & DECODE_FLAG_HAVE_TAG) ++ { ++ result = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ return result; ++ } ++ ++ if (tag != ETYPE_TAG (etype)) ++ { ++ warn(); ++ return ASN1_DER_ERROR; ++ } ++ ++ p += tag_len; ++ ++ DECR_LEN(der_len, tag_len); ++ ++ if (ber_len) *ber_len += tag_len; ++ } ++ ++ /* indefinite constructed */ ++ if ((((dflags & DECODE_FLAG_CONSTRUCTED) || class == ASN1_CLASS_STRUCTURED) && ETYPE_IS_STRING(etype)) && ++ !(dflags & DECODE_FLAG_LEVEL3)) ++ { ++ if (der_len == 0) ++ { ++ warn(); ++ result = ASN1_DER_ERROR; ++ goto cleanup; ++ } ++ ++ if (der_len > 0 && p[0] == 0x80) /* indefinite */ ++ { ++ len_len = 1; ++ DECR_LEN(der_len, len_len); ++ p += len_len; ++ ++ if (ber_len) *ber_len += len_len; ++ ++ /* decode the available octet strings */ ++ do ++ { ++ unsigned tmp_len; ++ unsigned flags = DECODE_FLAG_HAVE_TAG; ++ ++ if (dflags & DECODE_FLAG_LEVEL1) ++ flags |= DECODE_FLAG_LEVEL2; ++ else if (dflags & DECODE_FLAG_LEVEL2) ++ flags |= DECODE_FLAG_LEVEL3; ++ else ++ flags |= DECODE_FLAG_LEVEL1; ++ ++ result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, ++ flags); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ p += tmp_len; ++ DECR_LEN(der_len, tmp_len); ++ ++ if (ber_len) *ber_len += tmp_len; ++ ++ DECR_LEN(der_len, 2); /* we need the EOC */ ++ ++ result = append(&total, &total_size, out, out_len); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ free(out); ++ out = NULL; ++ ++ if (p[0] == 0 && p[1] == 0) /* EOC */ ++ { ++ if (ber_len) *ber_len += 2; ++ break; ++ } ++ ++ /* no EOC */ ++ der_len += 2; ++ ++ if (der_len == 2) ++ { ++ warn(); ++ result = ASN1_DER_ERROR; ++ goto cleanup; ++ } ++ } ++ while(1); ++ } ++ else /* constructed */ ++ { ++ long const_len; ++ ++ result = asn1_get_length_ber(p, der_len, &len_len); ++ if (result < 0) ++ { ++ warn(); ++ result = ASN1_DER_ERROR; ++ goto cleanup; ++ } ++ ++ DECR_LEN(der_len, len_len); ++ p += len_len; ++ ++ const_len = result; ++ ++ if (ber_len) *ber_len += len_len; ++ ++ /* decode the available octet strings */ ++ while(const_len > 0) ++ { ++ unsigned tmp_len; ++ unsigned flags = DECODE_FLAG_HAVE_TAG; ++ ++ if (dflags & DECODE_FLAG_LEVEL1) ++ flags |= DECODE_FLAG_LEVEL2; ++ else if (dflags & DECODE_FLAG_LEVEL2) ++ flags |= DECODE_FLAG_LEVEL3; ++ else ++ flags |= DECODE_FLAG_LEVEL1; ++ ++ result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, ++ flags); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ p += tmp_len; ++ DECR_LEN(der_len, tmp_len); ++ DECR_LEN(const_len, tmp_len); ++ ++ if (ber_len) *ber_len += tmp_len; ++ ++ result = append(&total, &total_size, out, out_len); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ free(out); ++ out = NULL; ++ } ++ } ++ } ++ else if (class == ETYPE_CLASS(etype)) ++ { ++ if (ber_len) ++ { ++ result = asn1_get_length_der (p, der_len, &len_len); ++ if (result < 0) ++ { ++ warn(); ++ result = ASN1_DER_ERROR; ++ goto cleanup; ++ } ++ *ber_len += result + len_len; ++ } ++ ++ /* non-string values are decoded as DER */ ++ result = _asn1_decode_simple_der(etype, der, _der_len, &cout, &out_len, dflags); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ ++ result = append(&total, &total_size, cout, out_len); ++ if (result != ASN1_SUCCESS) ++ { ++ warn(); ++ goto cleanup; ++ } ++ } ++ else ++ { ++ warn(); ++ result = ASN1_DER_ERROR; ++ goto cleanup; ++ } ++ ++ *str = total; ++ *str_len = total_size; ++ ++ return ASN1_SUCCESS; ++cleanup: ++ free(out); ++ free(total); ++ return result; ++} ++ ++/** ++ * asn1_decode_simple_ber: ++ * @etype: The type of the string to be encoded (ASN1_ETYPE_) ++ * @der: the encoded string ++ * @_der_len: the bytes of the encoded string ++ * @str: a pointer to the data ++ * @str_len: the length of the data ++ * @ber_len: the total length occupied by BER (may be %NULL) ++ * ++ * Decodes a BER encoded type. The output is an allocated value ++ * of the data. This decodes BER STRINGS only. Other types are ++ * decoded as DER. ++ * ++ * Returns: %ASN1_SUCCESS if successful or an error value. ++ **/ ++int ++asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, unsigned char **str, ++ unsigned int *str_len, unsigned int *ber_len) ++{ ++ return _asn1_decode_simple_ber(etype, der, _der_len, str, str_len, ber_len, DECODE_FLAG_HAVE_TAG); ++} +diff --git a/grub-core/lib/libtasn1/lib/element.c b/grub-core/lib/libtasn1/lib/element.c +new file mode 100644 +index 0000000000..997eb2725d +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/element.c +@@ -0,0 +1,1111 @@ ++/* ++ * Copyright (C) 2000-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++/*****************************************************/ ++/* File: element.c */ ++/* Description: Functions with the read and write */ ++/* functions. */ ++/*****************************************************/ ++ ++ ++#include ++#include "parser_aux.h" ++#include ++#include "structure.h" ++#include "c-ctype.h" ++#include "element.h" ++ ++void ++_asn1_hierarchical_name (asn1_node_const node, char *name, int name_size) ++{ ++ asn1_node_const p; ++ char tmp_name[64]; ++ ++ p = node; ++ ++ name[0] = 0; ++ ++ while (p != NULL) ++ { ++ if (p->name[0] != 0) ++ { ++ _asn1_str_cpy (tmp_name, sizeof (tmp_name), name), ++ _asn1_str_cpy (name, name_size, p->name); ++ _asn1_str_cat (name, name_size, "."); ++ _asn1_str_cat (name, name_size, tmp_name); ++ } ++ p = _asn1_find_up (p); ++ } ++ ++ if (name[0] == 0) ++ _asn1_str_cpy (name, name_size, "ROOT"); ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_convert_integer */ ++/* Description: converts an integer from a null terminated string */ ++/* to der decoding. The convertion from a null */ ++/* terminated string to an integer is made with */ ++/* the 'strtol' function. */ ++/* Parameters: */ ++/* value: null terminated string to convert. */ ++/* value_out: convertion result (memory must be already */ ++/* allocated). */ ++/* value_out_size: number of bytes of value_out. */ ++/* len: number of significant byte of value_out. */ ++/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */ ++/******************************************************************/ ++int ++_asn1_convert_integer (const unsigned char *value, unsigned char *value_out, ++ int value_out_size, int *len) ++{ ++ char negative; ++ unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; ++ long valtmp; ++ int k, k2; ++ ++ valtmp = _asn1_strtol (value, NULL, 10); ++ ++ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) ++ { ++ val[SIZEOF_UNSIGNED_LONG_INT - k - 1] = (valtmp >> (8 * k)) & 0xFF; ++ } ++ ++ if (val[0] & 0x80) ++ negative = 1; ++ else ++ negative = 0; ++ ++ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT - 1; k++) ++ { ++ if (negative && (val[k] != 0xFF)) ++ break; ++ else if (!negative && val[k]) ++ break; ++ } ++ ++ if ((negative && !(val[k] & 0x80)) || (!negative && (val[k] & 0x80))) ++ k--; ++ ++ *len = SIZEOF_UNSIGNED_LONG_INT - k; ++ ++ if (SIZEOF_UNSIGNED_LONG_INT - k > value_out_size) ++ /* VALUE_OUT is too short to contain the value conversion */ ++ return ASN1_MEM_ERROR; ++ ++ if (value_out != NULL) ++ { ++ for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++) ++ value_out[k2 - k] = val[k2]; ++ } ++ ++#if 0 ++ printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len); ++ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) ++ printf (", vOut[%d]=%d", k, value_out[k]); ++ printf ("\n"); ++#endif ++ ++ return ASN1_SUCCESS; ++} ++ ++/* Appends a new element into the sequence (or set) defined by this ++ * node. The new element will have a name of '?number', where number ++ * is a monotonically increased serial number. ++ * ++ * The last element in the list may be provided in @pcache, to avoid ++ * traversing the list, an expensive operation in long lists. ++ * ++ * On success it returns in @pcache the added element (which is the ++ * tail in the list of added elements). ++ */ ++int ++_asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) ++{ ++ asn1_node p, p2; ++ char temp[LTOSTR_MAX_SIZE]; ++ long n; ++ ++ if (!node || !(node->down)) ++ return ASN1_GENERIC_ERROR; ++ ++ p = node->down; ++ while ((type_field (p->type) == ASN1_ETYPE_TAG) ++ || (type_field (p->type) == ASN1_ETYPE_SIZE)) ++ p = p->right; ++ ++ p2 = _asn1_copy_structure3 (p); ++ if (p2 == NULL) ++ return ASN1_GENERIC_ERROR; ++ ++ if (pcache == NULL || pcache->tail == NULL || pcache->head != node) ++ { ++ while (p->right) ++ { ++ p = p->right; ++ } ++ } ++ else ++ { ++ p = pcache->tail; ++ } ++ ++ _asn1_set_right (p, p2); ++ if (pcache) ++ { ++ pcache->head = node; ++ pcache->tail = p2; ++ } ++ ++ if (p->name[0] == 0) ++ _asn1_str_cpy (temp, sizeof (temp), "?1"); ++ else ++ { ++ n = strtol (p->name + 1, NULL, 0); ++ n++; ++ temp[0] = '?'; ++ _asn1_ltostr (n, temp + 1); ++ } ++ _asn1_set_name (p2, temp); ++ /* p2->type |= CONST_OPTION; */ ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/** ++ * asn1_write_value: ++ * @node_root: pointer to a structure ++ * @name: the name of the element inside the structure that you want to set. ++ * @ivalue: vector used to specify the value to set. If len is >0, ++ * VALUE must be a two's complement form integer. if len=0 *VALUE ++ * must be a null terminated string with an integer value. ++ * @len: number of bytes of *value to use to set the value: ++ * value[0]..value[len-1] or 0 if value is a null terminated string ++ * ++ * Set the value of one element inside a structure. ++ * ++ * If an element is OPTIONAL and you want to delete it, you must use ++ * the value=NULL and len=0. Using "pkix.asn": ++ * ++ * result=asn1_write_value(cert, "tbsCertificate.issuerUniqueID", ++ * NULL, 0); ++ * ++ * Description for each type: ++ * ++ * INTEGER: VALUE must contain a two's complement form integer. ++ * ++ * value[0]=0xFF , len=1 -> integer=-1. ++ * value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1. ++ * value[0]=0x01 , len=1 -> integer= 1. ++ * value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1. ++ * value="123" , len=0 -> integer= 123. ++ * ++ * ENUMERATED: As INTEGER (but only with not negative numbers). ++ * ++ * BOOLEAN: VALUE must be the null terminated string "TRUE" or ++ * "FALSE" and LEN != 0. ++ * ++ * value="TRUE" , len=1 -> boolean=TRUE. ++ * value="FALSE" , len=1 -> boolean=FALSE. ++ * ++ * OBJECT IDENTIFIER: VALUE must be a null terminated string with ++ * each number separated by a dot (e.g. "1.2.3.543.1"). LEN != 0. ++ * ++ * value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha. ++ * ++ * UTCTime: VALUE must be a null terminated string in one of these ++ * formats: "YYMMDDhhmmssZ", "YYMMDDhhmmssZ", ++ * "YYMMDDhhmmss+hh'mm'", "YYMMDDhhmmss-hh'mm'", ++ * "YYMMDDhhmm+hh'mm'", or "YYMMDDhhmm-hh'mm'". LEN != 0. ++ * ++ * value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 ++ * at 12h 00m Greenwich Mean Time ++ * ++ * GeneralizedTime: VALUE must be in one of this format: ++ * "YYYYMMDDhhmmss.sZ", "YYYYMMDDhhmmss.sZ", ++ * "YYYYMMDDhhmmss.s+hh'mm'", "YYYYMMDDhhmmss.s-hh'mm'", ++ * "YYYYMMDDhhmm+hh'mm'", or "YYYYMMDDhhmm-hh'mm'" where ss.s ++ * indicates the seconds with any precision like "10.1" or "01.02". ++ * LEN != 0 ++ * ++ * value="2001010112001.12-0700" , len=1 -> time=Jannuary ++ * 1st, 2001 at 12h 00m 01.12s Pacific Daylight Time ++ * ++ * OCTET STRING: VALUE contains the octet string and LEN is the ++ * number of octets. ++ * ++ * value="$\backslash$x01$\backslash$x02$\backslash$x03" , ++ * len=3 -> three bytes octet string ++ * ++ * GeneralString: VALUE contains the generalstring and LEN is the ++ * number of octets. ++ * ++ * value="$\backslash$x01$\backslash$x02$\backslash$x03" , ++ * len=3 -> three bytes generalstring ++ * ++ * BIT STRING: VALUE contains the bit string organized by bytes and ++ * LEN is the number of bits. ++ * ++ * value="$\backslash$xCF" , len=6 -> bit string="110011" (six ++ * bits) ++ * ++ * CHOICE: if NAME indicates a choice type, VALUE must specify one of ++ * the alternatives with a null terminated string. LEN != 0. Using ++ * "pkix.asn"\: ++ * ++ * result=asn1_write_value(cert, ++ * "certificate1.tbsCertificate.subject", "rdnSequence", ++ * 1); ++ * ++ * ANY: VALUE indicates the der encoding of a structure. LEN != 0. ++ * ++ * SEQUENCE OF: VALUE must be the null terminated string "NEW" and ++ * LEN != 0. With this instruction another element is appended in ++ * the sequence. The name of this element will be "?1" if it's the ++ * first one, "?2" for the second and so on. ++ * ++ * Using "pkix.asn"\: ++ * ++ * result=asn1_write_value(cert, ++ * "certificate1.tbsCertificate.subject.rdnSequence", "NEW", 1); ++ * ++ * SET OF: the same as SEQUENCE OF. Using "pkix.asn": ++ * ++ * result=asn1_write_value(cert, ++ * "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1); ++ * ++ * Returns: %ASN1_SUCCESS if the value was set, ++ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and ++ * %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format. ++ **/ ++int ++asn1_write_value (asn1_node node_root, const char *name, ++ const void *ivalue, int len) ++{ ++ asn1_node node, p, p2; ++ unsigned char *temp, *value_temp = NULL, *default_temp = NULL; ++ int len2, k, k2, negative; ++ size_t i; ++ const unsigned char *value = ivalue; ++ unsigned int type; ++ ++ node = asn1_find_node (node_root, name); ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ if ((node->type & CONST_OPTION) && (value == NULL) && (len == 0)) ++ { ++ asn1_delete_structure (&node); ++ return ASN1_SUCCESS; ++ } ++ ++ type = type_field (node->type); ++ ++ if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0)) ++ { ++ p = node->down; ++ while ((type_field (p->type) == ASN1_ETYPE_TAG) ++ || (type_field (p->type) == ASN1_ETYPE_SIZE)) ++ p = p->right; ++ ++ while (p->right) ++ asn1_delete_structure (&p->right); ++ ++ return ASN1_SUCCESS; ++ } ++ ++ /* Don't allow element deletion for other types */ ++ if (value == NULL) ++ { ++ return ASN1_VALUE_NOT_VALID; ++ } ++ ++ switch (type) ++ { ++ case ASN1_ETYPE_BOOLEAN: ++ if (!_asn1_strcmp (value, "TRUE")) ++ { ++ if (node->type & CONST_DEFAULT) ++ { ++ p = node->down; ++ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) ++ p = p->right; ++ if (p->type & CONST_TRUE) ++ _asn1_set_value (node, NULL, 0); ++ else ++ _asn1_set_value (node, "T", 1); ++ } ++ else ++ _asn1_set_value (node, "T", 1); ++ } ++ else if (!_asn1_strcmp (value, "FALSE")) ++ { ++ if (node->type & CONST_DEFAULT) ++ { ++ p = node->down; ++ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) ++ p = p->right; ++ if (p->type & CONST_FALSE) ++ _asn1_set_value (node, NULL, 0); ++ else ++ _asn1_set_value (node, "F", 1); ++ } ++ else ++ _asn1_set_value (node, "F", 1); ++ } ++ else ++ return ASN1_VALUE_NOT_VALID; ++ break; ++ case ASN1_ETYPE_INTEGER: ++ case ASN1_ETYPE_ENUMERATED: ++ if (len == 0) ++ { ++ if ((c_isdigit (value[0])) || (value[0] == '-')) ++ { ++ value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); ++ if (value_temp == NULL) ++ return ASN1_MEM_ALLOC_ERROR; ++ ++ _asn1_convert_integer (value, value_temp, ++ SIZEOF_UNSIGNED_LONG_INT, &len); ++ } ++ else ++ { /* is an identifier like v1 */ ++ if (!(node->type & CONST_LIST)) ++ return ASN1_VALUE_NOT_VALID; ++ p = node->down; ++ while (p) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_CONSTANT) ++ { ++ if (!_asn1_strcmp (p->name, value)) ++ { ++ value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); ++ if (value_temp == NULL) ++ return ASN1_MEM_ALLOC_ERROR; ++ ++ _asn1_convert_integer (p->value, ++ value_temp, ++ SIZEOF_UNSIGNED_LONG_INT, ++ &len); ++ break; ++ } ++ } ++ p = p->right; ++ } ++ if (p == NULL) ++ return ASN1_VALUE_NOT_VALID; ++ } ++ } ++ else ++ { /* len != 0 */ ++ value_temp = malloc (len); ++ if (value_temp == NULL) ++ return ASN1_MEM_ALLOC_ERROR; ++ memcpy (value_temp, value, len); ++ } ++ ++ if (value_temp[0] & 0x80) ++ negative = 1; ++ else ++ negative = 0; ++ ++ if (negative && (type_field (node->type) == ASN1_ETYPE_ENUMERATED)) ++ { ++ free (value_temp); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ ++ for (k = 0; k < len - 1; k++) ++ if (negative && (value_temp[k] != 0xFF)) ++ break; ++ else if (!negative && value_temp[k]) ++ break; ++ ++ if ((negative && !(value_temp[k] & 0x80)) || ++ (!negative && (value_temp[k] & 0x80))) ++ k--; ++ ++ _asn1_set_value_lv (node, value_temp + k, len - k); ++ ++ if (node->type & CONST_DEFAULT) ++ { ++ p = node->down; ++ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) ++ p = p->right; ++ if ((c_isdigit (p->value[0])) || (p->value[0] == '-')) ++ { ++ default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); ++ if (default_temp == NULL) ++ { ++ free (value_temp); ++ return ASN1_MEM_ALLOC_ERROR; ++ } ++ ++ _asn1_convert_integer (p->value, default_temp, ++ SIZEOF_UNSIGNED_LONG_INT, &len2); ++ } ++ else ++ { /* is an identifier like v1 */ ++ if (!(node->type & CONST_LIST)) ++ { ++ free (value_temp); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ p2 = node->down; ++ while (p2) ++ { ++ if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) ++ { ++ if (!_asn1_strcmp (p2->name, p->value)) ++ { ++ default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); ++ if (default_temp == NULL) ++ { ++ free (value_temp); ++ return ASN1_MEM_ALLOC_ERROR; ++ } ++ ++ _asn1_convert_integer (p2->value, ++ default_temp, ++ SIZEOF_UNSIGNED_LONG_INT, ++ &len2); ++ break; ++ } ++ } ++ p2 = p2->right; ++ } ++ if (p2 == NULL) ++ { ++ free (value_temp); ++ return ASN1_VALUE_NOT_VALID; ++ } ++ } ++ ++ ++ if ((len - k) == len2) ++ { ++ for (k2 = 0; k2 < len2; k2++) ++ if (value_temp[k + k2] != default_temp[k2]) ++ { ++ break; ++ } ++ if (k2 == len2) ++ _asn1_set_value (node, NULL, 0); ++ } ++ free (default_temp); ++ } ++ free (value_temp); ++ break; ++ case ASN1_ETYPE_OBJECT_ID: ++ for (i = 0; i < _asn1_strlen (value); i++) ++ if ((!c_isdigit (value[i])) && (value[i] != '.') && (value[i] != '+')) ++ return ASN1_VALUE_NOT_VALID; ++ if (node->type & CONST_DEFAULT) ++ { ++ p = node->down; ++ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) ++ p = p->right; ++ if (!_asn1_strcmp (value, p->value)) ++ { ++ _asn1_set_value (node, NULL, 0); ++ break; ++ } ++ } ++ _asn1_set_value (node, value, _asn1_strlen (value) + 1); ++ break; ++ case ASN1_ETYPE_UTC_TIME: ++ { ++ len = _asn1_strlen (value); ++ if (len < 11) ++ return ASN1_VALUE_NOT_VALID; ++ for (k = 0; k < 10; k++) ++ if (!c_isdigit (value[k])) ++ return ASN1_VALUE_NOT_VALID; ++ switch (len) ++ { ++ case 11: ++ if (value[10] != 'Z') ++ return ASN1_VALUE_NOT_VALID; ++ break; ++ case 13: ++ if ((!c_isdigit (value[10])) || (!c_isdigit (value[11])) || ++ (value[12] != 'Z')) ++ return ASN1_VALUE_NOT_VALID; ++ break; ++ case 15: ++ if ((value[10] != '+') && (value[10] != '-')) ++ return ASN1_VALUE_NOT_VALID; ++ for (k = 11; k < 15; k++) ++ if (!c_isdigit (value[k])) ++ return ASN1_VALUE_NOT_VALID; ++ break; ++ case 17: ++ if ((!c_isdigit (value[10])) || (!c_isdigit (value[11]))) ++ return ASN1_VALUE_NOT_VALID; ++ if ((value[12] != '+') && (value[12] != '-')) ++ return ASN1_VALUE_NOT_VALID; ++ for (k = 13; k < 17; k++) ++ if (!c_isdigit (value[k])) ++ return ASN1_VALUE_NOT_VALID; ++ break; ++ default: ++ return ASN1_VALUE_NOT_FOUND; ++ } ++ _asn1_set_value (node, value, len); ++ } ++ break; ++ case ASN1_ETYPE_GENERALIZED_TIME: ++ len = _asn1_strlen (value); ++ _asn1_set_value (node, value, len); ++ break; ++ case ASN1_ETYPE_OCTET_STRING: ++ case ASN1_ETYPE_GENERALSTRING: ++ case ASN1_ETYPE_NUMERIC_STRING: ++ case ASN1_ETYPE_IA5_STRING: ++ case ASN1_ETYPE_TELETEX_STRING: ++ case ASN1_ETYPE_PRINTABLE_STRING: ++ case ASN1_ETYPE_UNIVERSAL_STRING: ++ case ASN1_ETYPE_BMP_STRING: ++ case ASN1_ETYPE_UTF8_STRING: ++ case ASN1_ETYPE_VISIBLE_STRING: ++ if (len == 0) ++ len = _asn1_strlen (value); ++ _asn1_set_value_lv (node, value, len); ++ break; ++ case ASN1_ETYPE_BIT_STRING: ++ if (len == 0) ++ len = _asn1_strlen (value); ++ asn1_length_der ((len >> 3) + 2, NULL, &len2); ++ temp = malloc ((len >> 3) + 2 + len2); ++ if (temp == NULL) ++ return ASN1_MEM_ALLOC_ERROR; ++ ++ asn1_bit_der (value, len, temp, &len2); ++ _asn1_set_value_m (node, temp, len2); ++ temp = NULL; ++ break; ++ case ASN1_ETYPE_CHOICE: ++ p = node->down; ++ while (p) ++ { ++ if (!_asn1_strcmp (p->name, value)) ++ { ++ p2 = node->down; ++ while (p2) ++ { ++ if (p2 != p) ++ { ++ asn1_delete_structure (&p2); ++ p2 = node->down; ++ } ++ else ++ p2 = p2->right; ++ } ++ break; ++ } ++ p = p->right; ++ } ++ if (!p) ++ return ASN1_ELEMENT_NOT_FOUND; ++ break; ++ case ASN1_ETYPE_ANY: ++ _asn1_set_value_lv (node, value, len); ++ break; ++ case ASN1_ETYPE_SEQUENCE_OF: ++ case ASN1_ETYPE_SET_OF: ++ if (_asn1_strcmp (value, "NEW")) ++ return ASN1_VALUE_NOT_VALID; ++ _asn1_append_sequence_set (node, NULL); ++ break; ++ default: ++ return ASN1_ELEMENT_NOT_FOUND; ++ break; ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++#define PUT_VALUE( ptr, ptr_size, data, data_size) \ ++ *len = data_size; \ ++ if (ptr_size < data_size) { \ ++ return ASN1_MEM_ERROR; \ ++ } else { \ ++ if (ptr && data_size > 0) \ ++ memcpy (ptr, data, data_size); \ ++ } ++ ++#define PUT_STR_VALUE( ptr, ptr_size, data) \ ++ *len = _asn1_strlen (data) + 1; \ ++ if (ptr_size < *len) { \ ++ return ASN1_MEM_ERROR; \ ++ } else { \ ++ /* this strcpy is checked */ \ ++ if (ptr) { \ ++ _asn1_strcpy (ptr, data); \ ++ } \ ++ } ++ ++#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \ ++ *len = data_size + 1; \ ++ if (ptr_size < *len) { \ ++ return ASN1_MEM_ERROR; \ ++ } else { \ ++ /* this strcpy is checked */ \ ++ if (ptr) { \ ++ if (data_size > 0) \ ++ memcpy (ptr, data, data_size); \ ++ ptr[data_size] = 0; \ ++ } \ ++ } ++ ++#define ADD_STR_VALUE( ptr, ptr_size, data) \ ++ *len += _asn1_strlen(data); \ ++ if (ptr_size < (int) *len) { \ ++ (*len)++; \ ++ return ASN1_MEM_ERROR; \ ++ } else { \ ++ /* this strcat is checked */ \ ++ if (ptr) _asn1_strcat (ptr, data); \ ++ } ++ ++/** ++ * asn1_read_value: ++ * @root: pointer to a structure. ++ * @name: the name of the element inside a structure that you want to read. ++ * @ivalue: vector that will contain the element's content, must be a ++ * pointer to memory cells already allocated (may be %NULL). ++ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy ++ * holds the sizeof value. ++ * ++ * Returns the value of one element inside a structure. ++ * If an element is OPTIONAL and this returns ++ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present ++ * in the der encoding that created the structure. The first element ++ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and ++ * so on. If the @root provided is a node to specific sequence element, ++ * then the keyword "?CURRENT" is also acceptable and indicates the ++ * current sequence element of this node. ++ * ++ * Note that there can be valid values with length zero. In these case ++ * this function will succeed and @len will be zero. ++ * ++ * INTEGER: VALUE will contain a two's complement form integer. ++ * ++ * integer=-1 -> value[0]=0xFF , len=1. ++ * integer=1 -> value[0]=0x01 , len=1. ++ * ++ * ENUMERATED: As INTEGER (but only with not negative numbers). ++ * ++ * BOOLEAN: VALUE will be the null terminated string "TRUE" or ++ * "FALSE" and LEN=5 or LEN=6. ++ * ++ * OBJECT IDENTIFIER: VALUE will be a null terminated string with ++ * each number separated by a dot (i.e. "1.2.3.543.1"). ++ * ++ * LEN = strlen(VALUE)+1 ++ * ++ * UTCTime: VALUE will be a null terminated string in one of these ++ * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'". ++ * LEN=strlen(VALUE)+1. ++ * ++ * GeneralizedTime: VALUE will be a null terminated string in the ++ * same format used to set the value. ++ * ++ * OCTET STRING: VALUE will contain the octet string and LEN will be ++ * the number of octets. ++ * ++ * GeneralString: VALUE will contain the generalstring and LEN will ++ * be the number of octets. ++ * ++ * BIT STRING: VALUE will contain the bit string organized by bytes ++ * and LEN will be the number of bits. ++ * ++ * CHOICE: If NAME indicates a choice type, VALUE will specify the ++ * alternative selected. ++ * ++ * ANY: If NAME indicates an any type, VALUE will indicate the DER ++ * encoding of the structure actually used. ++ * ++ * Returns: %ASN1_SUCCESS if value is returned, ++ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, ++ * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element ++ * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough ++ * to store the result, and in this case @len will contain the number of ++ * bytes needed. On the occasion that the stored data are of zero-length ++ * this function may return %ASN1_SUCCESS even if the provided @len is zero. ++ **/ ++int ++asn1_read_value (asn1_node_const root, const char *name, void *ivalue, int *len) ++{ ++ return asn1_read_value_type (root, name, ivalue, len, NULL); ++} ++ ++/** ++ * asn1_read_value_type: ++ * @root: pointer to a structure. ++ * @name: the name of the element inside a structure that you want to read. ++ * @ivalue: vector that will contain the element's content, must be a ++ * pointer to memory cells already allocated (may be %NULL). ++ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy ++ * holds the sizeof value. ++ * @etype: The type of the value read (ASN1_ETYPE) ++ * ++ * Returns the type and value of one element inside a structure. ++ * If an element is OPTIONAL and this returns ++ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present ++ * in the der encoding that created the structure. The first element ++ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and ++ * so on. If the @root provided is a node to specific sequence element, ++ * then the keyword "?CURRENT" is also acceptable and indicates the ++ * current sequence element of this node. ++ * ++ * Note that there can be valid values with length zero. In these case ++ * this function will succeed and @len will be zero. ++ * ++ * ++ * INTEGER: VALUE will contain a two's complement form integer. ++ * ++ * integer=-1 -> value[0]=0xFF , len=1. ++ * integer=1 -> value[0]=0x01 , len=1. ++ * ++ * ENUMERATED: As INTEGER (but only with not negative numbers). ++ * ++ * BOOLEAN: VALUE will be the null terminated string "TRUE" or ++ * "FALSE" and LEN=5 or LEN=6. ++ * ++ * OBJECT IDENTIFIER: VALUE will be a null terminated string with ++ * each number separated by a dot (i.e. "1.2.3.543.1"). ++ * ++ * LEN = strlen(VALUE)+1 ++ * ++ * UTCTime: VALUE will be a null terminated string in one of these ++ * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'". ++ * LEN=strlen(VALUE)+1. ++ * ++ * GeneralizedTime: VALUE will be a null terminated string in the ++ * same format used to set the value. ++ * ++ * OCTET STRING: VALUE will contain the octet string and LEN will be ++ * the number of octets. ++ * ++ * GeneralString: VALUE will contain the generalstring and LEN will ++ * be the number of octets. ++ * ++ * BIT STRING: VALUE will contain the bit string organized by bytes ++ * and LEN will be the number of bits. ++ * ++ * CHOICE: If NAME indicates a choice type, VALUE will specify the ++ * alternative selected. ++ * ++ * ANY: If NAME indicates an any type, VALUE will indicate the DER ++ * encoding of the structure actually used. ++ * ++ * Returns: %ASN1_SUCCESS if value is returned, ++ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, ++ * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element ++ * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough ++ * to store the result, and in this case @len will contain the number of ++ * bytes needed. On the occasion that the stored data are of zero-length ++ * this function may return %ASN1_SUCCESS even if the provided @len is zero. ++ **/ ++int ++asn1_read_value_type (asn1_node_const root, const char *name, void *ivalue, ++ int *len, unsigned int *etype) ++{ ++ asn1_node_const node, p, p2; ++ int len2, len3, result; ++ int value_size = *len; ++ unsigned char *value = ivalue; ++ unsigned type; ++ ++ node = asn1_find_node (root, name); ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ type = type_field (node->type); ++ ++ if ((type != ASN1_ETYPE_NULL) && ++ (type != ASN1_ETYPE_CHOICE) && ++ !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) && ++ (node->value == NULL)) ++ return ASN1_VALUE_NOT_FOUND; ++ ++ if (etype) ++ *etype = type; ++ switch (type) ++ { ++ case ASN1_ETYPE_NULL: ++ PUT_STR_VALUE (value, value_size, "NULL"); ++ break; ++ case ASN1_ETYPE_BOOLEAN: ++ if ((node->type & CONST_DEFAULT) && (node->value == NULL)) ++ { ++ p = node->down; ++ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) ++ p = p->right; ++ if (p->type & CONST_TRUE) ++ { ++ PUT_STR_VALUE (value, value_size, "TRUE"); ++ } ++ else ++ { ++ PUT_STR_VALUE (value, value_size, "FALSE"); ++ } ++ } ++ else if (node->value[0] == 'T') ++ { ++ PUT_STR_VALUE (value, value_size, "TRUE"); ++ } ++ else ++ { ++ PUT_STR_VALUE (value, value_size, "FALSE"); ++ } ++ break; ++ case ASN1_ETYPE_INTEGER: ++ case ASN1_ETYPE_ENUMERATED: ++ if ((node->type & CONST_DEFAULT) && (node->value == NULL)) ++ { ++ p = node->down; ++ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) ++ p = p->right; ++ if ((c_isdigit (p->value[0])) || (p->value[0] == '-') ++ || (p->value[0] == '+')) ++ { ++ result = _asn1_convert_integer ++ (p->value, value, value_size, len); ++ if (result != ASN1_SUCCESS) ++ return result; ++ } ++ else ++ { /* is an identifier like v1 */ ++ p2 = node->down; ++ while (p2) ++ { ++ if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) ++ { ++ if (!_asn1_strcmp (p2->name, p->value)) ++ { ++ result = _asn1_convert_integer ++ (p2->value, value, value_size, ++ len); ++ if (result != ASN1_SUCCESS) ++ return result; ++ break; ++ } ++ } ++ p2 = p2->right; ++ } ++ } ++ } ++ else ++ { ++ len2 = -1; ++ result = asn1_get_octet_der ++ (node->value, node->value_len, &len2, value, value_size, ++ len); ++ if (result != ASN1_SUCCESS) ++ return result; ++ } ++ break; ++ case ASN1_ETYPE_OBJECT_ID: ++ if (node->type & CONST_ASSIGN) ++ { ++ *len = 0; ++ if (value) ++ value[0] = 0; ++ p = node->down; ++ while (p) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_CONSTANT) ++ { ++ ADD_STR_VALUE (value, value_size, p->value); ++ if (p->right) ++ { ++ ADD_STR_VALUE (value, value_size, "."); ++ } ++ } ++ p = p->right; ++ } ++ (*len)++; ++ } ++ else if ((node->type & CONST_DEFAULT) && (node->value == NULL)) ++ { ++ p = node->down; ++ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) ++ p = p->right; ++ PUT_STR_VALUE (value, value_size, p->value); ++ } ++ else ++ { ++ PUT_STR_VALUE (value, value_size, node->value); ++ } ++ break; ++ case ASN1_ETYPE_GENERALIZED_TIME: ++ case ASN1_ETYPE_UTC_TIME: ++ PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len); ++ break; ++ case ASN1_ETYPE_OCTET_STRING: ++ case ASN1_ETYPE_GENERALSTRING: ++ case ASN1_ETYPE_NUMERIC_STRING: ++ case ASN1_ETYPE_IA5_STRING: ++ case ASN1_ETYPE_TELETEX_STRING: ++ case ASN1_ETYPE_PRINTABLE_STRING: ++ case ASN1_ETYPE_UNIVERSAL_STRING: ++ case ASN1_ETYPE_BMP_STRING: ++ case ASN1_ETYPE_UTF8_STRING: ++ case ASN1_ETYPE_VISIBLE_STRING: ++ len2 = -1; ++ result = asn1_get_octet_der ++ (node->value, node->value_len, &len2, value, value_size, ++ len); ++ if (result != ASN1_SUCCESS) ++ return result; ++ break; ++ case ASN1_ETYPE_BIT_STRING: ++ len2 = -1; ++ result = asn1_get_bit_der ++ (node->value, node->value_len, &len2, value, value_size, ++ len); ++ if (result != ASN1_SUCCESS) ++ return result; ++ break; ++ case ASN1_ETYPE_CHOICE: ++ PUT_STR_VALUE (value, value_size, node->down->name); ++ break; ++ case ASN1_ETYPE_ANY: ++ len3 = -1; ++ len2 = asn1_get_length_der (node->value, node->value_len, &len3); ++ if (len2 < 0) ++ return ASN1_DER_ERROR; ++ PUT_VALUE (value, value_size, node->value + len3, len2); ++ break; ++ default: ++ return ASN1_ELEMENT_NOT_FOUND; ++ break; ++ } ++ return ASN1_SUCCESS; ++} ++ ++ ++/** ++ * asn1_read_tag: ++ * @root: pointer to a structure ++ * @name: the name of the element inside a structure. ++ * @tagValue: variable that will contain the TAG value. ++ * @classValue: variable that will specify the TAG type. ++ * ++ * Returns the TAG and the CLASS of one element inside a structure. ++ * CLASS can have one of these constants: %ASN1_CLASS_APPLICATION, ++ * %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or ++ * %ASN1_CLASS_CONTEXT_SPECIFIC. ++ * ++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if ++ * @name is not a valid element. ++ **/ ++int ++asn1_read_tag (asn1_node_const root, const char *name, int *tagValue, ++ int *classValue) ++{ ++ asn1_node node, p, pTag; ++ ++ node = asn1_find_node (root, name); ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node->down; ++ ++ /* pTag will points to the IMPLICIT TAG */ ++ pTag = NULL; ++ if (node->type & CONST_TAG) ++ { ++ while (p) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_TAG) ++ { ++ if ((p->type & CONST_IMPLICIT) && (pTag == NULL)) ++ pTag = p; ++ else if (p->type & CONST_EXPLICIT) ++ pTag = NULL; ++ } ++ p = p->right; ++ } ++ } ++ ++ if (pTag) ++ { ++ *tagValue = _asn1_strtoul (pTag->value, NULL, 10); ++ ++ if (pTag->type & CONST_APPLICATION) ++ *classValue = ASN1_CLASS_APPLICATION; ++ else if (pTag->type & CONST_UNIVERSAL) ++ *classValue = ASN1_CLASS_UNIVERSAL; ++ else if (pTag->type & CONST_PRIVATE) ++ *classValue = ASN1_CLASS_PRIVATE; ++ else ++ *classValue = ASN1_CLASS_CONTEXT_SPECIFIC; ++ } ++ else ++ { ++ unsigned type = type_field (node->type); ++ *classValue = ASN1_CLASS_UNIVERSAL; ++ ++ switch (type) ++ { ++ CASE_HANDLED_ETYPES: ++ *tagValue = _asn1_tags[type].tag; ++ break; ++ case ASN1_ETYPE_TAG: ++ case ASN1_ETYPE_CHOICE: ++ case ASN1_ETYPE_ANY: ++ *tagValue = -1; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++/** ++ * asn1_read_node_value: ++ * @node: pointer to a node. ++ * @data: a point to a asn1_data_node_st ++ * ++ * Returns the value a data node inside a asn1_node structure. ++ * The data returned should be handled as constant values. ++ * ++ * Returns: %ASN1_SUCCESS if the node exists. ++ **/ ++int ++asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data) ++{ ++ data->name = node->name; ++ data->value = node->value; ++ data->value_len = node->value_len; ++ data->type = type_field (node->type); ++ ++ return ASN1_SUCCESS; ++} +diff --git a/grub-core/lib/libtasn1/lib/errors.c b/grub-core/lib/libtasn1/lib/errors.c +new file mode 100644 +index 0000000000..cee74daf79 +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/errors.c +@@ -0,0 +1,100 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++#include ++#ifdef STDC_HEADERS ++#include ++#endif ++ ++#define LIBTASN1_ERROR_ENTRY(name) { #name, name } ++ ++struct libtasn1_error_entry ++{ ++ const char *name; ++ int number; ++}; ++typedef struct libtasn1_error_entry libtasn1_error_entry; ++ ++static const libtasn1_error_entry error_algorithms[] = { ++ LIBTASN1_ERROR_ENTRY (ASN1_SUCCESS), ++ LIBTASN1_ERROR_ENTRY (ASN1_FILE_NOT_FOUND), ++ LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_FOUND), ++ LIBTASN1_ERROR_ENTRY (ASN1_IDENTIFIER_NOT_FOUND), ++ LIBTASN1_ERROR_ENTRY (ASN1_DER_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_FOUND), ++ LIBTASN1_ERROR_ENTRY (ASN1_GENERIC_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_VALID), ++ LIBTASN1_ERROR_ENTRY (ASN1_TAG_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_TAG_IMPLICIT), ++ LIBTASN1_ERROR_ENTRY (ASN1_ERROR_TYPE_ANY), ++ LIBTASN1_ERROR_ENTRY (ASN1_SYNTAX_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_MEM_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_MEM_ALLOC_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_DER_OVERFLOW), ++ LIBTASN1_ERROR_ENTRY (ASN1_NAME_TOO_LONG), ++ LIBTASN1_ERROR_ENTRY (ASN1_ARRAY_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_EMPTY), ++ LIBTASN1_ERROR_ENTRY (ASN1_TIME_ENCODING_ERROR), ++ LIBTASN1_ERROR_ENTRY (ASN1_RECURSION), ++ {0, 0} ++}; ++ ++/** ++ * asn1_perror: ++ * @error: is an error returned by a libtasn1 function. ++ * ++ * Prints a string to stderr with a description of an error. This ++ * function is like perror(). The only difference is that it accepts ++ * an error returned by a libtasn1 function. ++ * ++ * Since: 1.6 ++ **/ ++void ++asn1_perror (int error) ++{ ++ const char *str = asn1_strerror (error); ++ fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)"); ++} ++ ++/** ++ * asn1_strerror: ++ * @error: is an error returned by a libtasn1 function. ++ * ++ * Returns a string with a description of an error. This function is ++ * similar to strerror. The only difference is that it accepts an ++ * error (number) returned by a libtasn1 function. ++ * ++ * Returns: Pointer to static zero-terminated string describing error ++ * code. ++ * ++ * Since: 1.6 ++ **/ ++const char * ++asn1_strerror (int error) ++{ ++ const libtasn1_error_entry *p; ++ ++ for (p = error_algorithms; p->name != NULL; p++) ++ if (p->number == error) ++ return p->name + sizeof ("ASN1_") - 1; ++ ++ return NULL; ++} +diff --git a/grub-core/lib/libtasn1/lib/gstr.c b/grub-core/lib/libtasn1/lib/gstr.c +new file mode 100644 +index 0000000000..e91a3a151c +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/gstr.c +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++#include ++#include "gstr.h" ++ ++/* These function are like strcat, strcpy. They only ++ * do bounds checking (they shouldn't cause buffer overruns), ++ * and they always produce null terminated strings. ++ * ++ * They should be used only with null terminated strings. ++ */ ++void ++_asn1_str_cat (char *dest, size_t dest_tot_size, const char *src) ++{ ++ size_t str_size = strlen (src); ++ size_t dest_size = strlen (dest); ++ ++ if (dest_tot_size - dest_size > str_size) ++ { ++ strcat (dest, src); ++ } ++ else ++ { ++ if (dest_tot_size - dest_size > 0) ++ { ++ strncat (dest, src, (dest_tot_size - dest_size) - 1); ++ dest[dest_tot_size - 1] = 0; ++ } ++ } ++} ++ ++/* Returns the bytes copied (not including the null terminator) */ ++unsigned int ++_asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src) ++{ ++ size_t str_size = strlen (src); ++ ++ if (dest_tot_size > str_size) ++ { ++ strcpy (dest, src); ++ return str_size; ++ } ++ else ++ { ++ if (dest_tot_size > 0) ++ { ++ str_size = dest_tot_size - 1; ++ memcpy (dest, src, str_size); ++ dest[str_size] = 0; ++ return str_size; ++ } ++ else ++ return 0; ++ } ++} +diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c b/grub-core/lib/libtasn1/lib/parser_aux.c +new file mode 100644 +index 0000000000..d5dbbf8765 +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/parser_aux.c +@@ -0,0 +1,1173 @@ ++/* ++ * Copyright (C) 2000-2016 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++#include // WORD_BIT ++ ++#include "int.h" ++#include "parser_aux.h" ++#include "gstr.h" ++#include "structure.h" ++#include "element.h" ++#include "c-ctype.h" ++ ++char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not found */ ++ ++/* Return a hash of the N bytes of X using the method described by ++ Bruno Haible in https://www.haible.de/bruno/hashfunc.html. ++ Note that while many hash functions reduce their result via modulo ++ to a 0..table_size-1 range, this function does not do that. ++ ++ This implementation has been changed from size_t -> unsigned int. */ ++ ++#ifdef __clang__ ++__attribute__((no_sanitize("integer"))) ++#endif ++_GL_ATTRIBUTE_PURE ++static unsigned int ++_asn1_hash_name (const char *x) ++{ ++ const unsigned char *s = (unsigned char *) x; ++ unsigned h = 0; ++ ++ while (*s) ++ h = (*s++) + ((h << 9) | (h >> (WORD_BIT - 9))); ++ ++ return h; ++} ++ ++/******************************************************/ ++/* Function : _asn1_add_static_node */ ++/* Description: creates a new NODE_ASN element and */ ++/* puts it in the list pointed by e_list. */ ++/* Parameters: */ ++/* e_list: of type list_type; must be NULL initially */ ++/* type: type of the new element (see ASN1_ETYPE_ */ ++/* and CONST_ constants). */ ++/* Return: pointer to the new element. */ ++/******************************************************/ ++asn1_node ++_asn1_add_static_node (list_type **e_list, unsigned int type) ++{ ++ list_type *p; ++ asn1_node punt; ++ ++ punt = calloc (1, sizeof (struct asn1_node_st)); ++ if (punt == NULL) ++ return NULL; ++ ++ p = malloc (sizeof (list_type)); ++ if (p == NULL) ++ { ++ free (punt); ++ return NULL; ++ } ++ ++ p->node = punt; ++ p->next = *e_list; ++ *e_list = p; ++ ++ punt->type = type; ++ ++ return punt; ++} ++ ++static ++int _asn1_add_static_node2 (list_type **e_list, asn1_node node) ++{ ++ list_type *p; ++ ++ p = malloc (sizeof (list_type)); ++ if (p == NULL) ++ { ++ return -1; ++ } ++ ++ p->node = node; ++ p->next = *e_list; ++ *e_list = p; ++ ++ return 0; ++} ++ ++/** ++ * asn1_find_node: ++ * @pointer: NODE_ASN element pointer. ++ * @name: null terminated string with the element's name to find. ++ * ++ * Searches for an element called @name starting from @pointer. The ++ * name is composed by different identifiers separated by dots. When ++ * *@pointer has a name, the first identifier must be the name of ++ * *@pointer, otherwise it must be the name of one child of *@pointer. ++ * ++ * Returns: the search result, or %NULL if not found. ++ **/ ++asn1_node ++asn1_find_node (asn1_node_const pointer, const char *name) ++{ ++ asn1_node_const p; ++ char *n_end, n[ASN1_MAX_NAME_SIZE + 1]; ++ const char *n_start; ++ unsigned int nsize; ++ unsigned int nhash; ++ ++ if (pointer == NULL) ++ return NULL; ++ ++ if (name == NULL) ++ return NULL; ++ ++ p = pointer; ++ n_start = name; ++ ++ if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?') ++ { /* ?CURRENT */ ++ n_start = strchr(n_start, '.'); ++ if (n_start) ++ n_start++; ++ } ++ else if (p->name[0] != 0) ++ { /* has *pointer got a name ? */ ++ n_end = strchr (n_start, '.'); /* search the first dot */ ++ if (n_end) ++ { ++ nsize = n_end - n_start; ++ if (nsize >= sizeof(n)) ++ return NULL; ++ ++ memcpy (n, n_start, nsize); ++ n[nsize] = 0; ++ n_start = n_end; ++ n_start++; ++ ++ nhash = _asn1_hash_name (n); ++ } ++ else ++ { ++ _asn1_str_cpy (n, sizeof (n), n_start); ++ nhash = _asn1_hash_name (n); ++ ++ n_start = NULL; ++ } ++ ++ while (p) ++ { ++ if (nhash == p->name_hash && (!strcmp (p->name, n))) ++ break; ++ else ++ p = p->right; ++ } /* while */ ++ ++ if (p == NULL) ++ return NULL; ++ } ++ else ++ { /* *pointer doesn't have a name */ ++ if (n_start[0] == 0) ++ return (asn1_node) p; ++ } ++ ++ while (n_start) ++ { /* Has the end of NAME been reached? */ ++ n_end = strchr (n_start, '.'); /* search the next dot */ ++ if (n_end) ++ { ++ nsize = n_end - n_start; ++ if (nsize >= sizeof(n)) ++ return NULL; ++ ++ memcpy (n, n_start, nsize); ++ n[nsize] = 0; ++ n_start = n_end; ++ n_start++; ++ ++ nhash = _asn1_hash_name (n); ++ } ++ else ++ { ++ _asn1_str_cpy (n, sizeof (n), n_start); ++ nhash = _asn1_hash_name (n); ++ n_start = NULL; ++ } ++ ++ if (p->down == NULL) ++ return NULL; ++ ++ p = p->down; ++ if (p == NULL) ++ return NULL; ++ ++ /* The identifier "?LAST" indicates the last element ++ in the right chain. */ ++ if (n[0] == '?' && n[1] == 'L') /* ?LAST */ ++ { ++ while (p->right) ++ p = p->right; ++ } ++ else ++ { /* no "?LAST" */ ++ while (p) ++ { ++ if (p->name_hash == nhash && !strcmp (p->name, n)) ++ break; ++ else ++ p = p->right; ++ } ++ } ++ if (p == NULL) ++ return NULL; ++ } /* while */ ++ ++ return (asn1_node) p; ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_set_value */ ++/* Description: sets the field VALUE in a NODE_ASN element. The */ ++/* previous value (if exist) will be lost */ ++/* Parameters: */ ++/* node: element pointer. */ ++/* value: pointer to the value that you want to set. */ ++/* len: character number of value. */ ++/* Return: pointer to the NODE_ASN element. */ ++/******************************************************************/ ++asn1_node ++_asn1_set_value (asn1_node node, const void *value, unsigned int len) ++{ ++ if (node == NULL) ++ return node; ++ if (node->value) ++ { ++ if (node->value != node->small_value) ++ free (node->value); ++ node->value = NULL; ++ node->value_len = 0; ++ } ++ ++ if (!len) ++ return node; ++ ++ if (len < sizeof (node->small_value)) ++ { ++ node->value = node->small_value; ++ } ++ else ++ { ++ node->value = malloc (len); ++ if (node->value == NULL) ++ return NULL; ++ } ++ node->value_len = len; ++ ++ memcpy (node->value, value, len); ++ return node; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_set_value_lv */ ++/* Description: sets the field VALUE in a NODE_ASN element. The */ ++/* previous value (if exist) will be lost. The value */ ++/* given is stored as an length-value format (LV */ ++/* Parameters: */ ++/* node: element pointer. */ ++/* value: pointer to the value that you want to set. */ ++/* len: character number of value. */ ++/* Return: pointer to the NODE_ASN element. */ ++/******************************************************************/ ++asn1_node ++_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len) ++{ ++ int len2; ++ void *temp; ++ ++ if (node == NULL) ++ return node; ++ ++ asn1_length_der (len, NULL, &len2); ++ temp = malloc (len + len2); ++ if (temp == NULL) ++ return NULL; ++ ++ asn1_octet_der (value, len, temp, &len2); ++ return _asn1_set_value_m (node, temp, len2); ++} ++ ++/* the same as _asn1_set_value except that it sets an already malloc'ed ++ * value. ++ */ ++asn1_node ++_asn1_set_value_m (asn1_node node, void *value, unsigned int len) ++{ ++ if (node == NULL) ++ return node; ++ ++ if (node->value) ++ { ++ if (node->value != node->small_value) ++ free (node->value); ++ node->value = NULL; ++ node->value_len = 0; ++ } ++ ++ if (!len) ++ return node; ++ ++ node->value = value; ++ node->value_len = len; ++ ++ return node; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_append_value */ ++/* Description: appends to the field VALUE in a NODE_ASN element. */ ++/* */ ++/* Parameters: */ ++/* node: element pointer. */ ++/* value: pointer to the value that you want to be appended. */ ++/* len: character number of value. */ ++/* Return: pointer to the NODE_ASN element. */ ++/******************************************************************/ ++asn1_node ++_asn1_append_value (asn1_node node, const void *value, unsigned int len) ++{ ++ if (node == NULL) ++ return node; ++ ++ if (node->value == NULL) ++ return _asn1_set_value (node, value, len); ++ ++ if (len == 0) ++ return node; ++ ++ if (node->value == node->small_value) ++ { ++ /* value is in node */ ++ int prev_len = node->value_len; ++ node->value_len += len; ++ node->value = malloc (node->value_len); ++ if (node->value == NULL) ++ { ++ node->value_len = 0; ++ return NULL; ++ } ++ ++ if (prev_len > 0) ++ memcpy (node->value, node->small_value, prev_len); ++ ++ memcpy (&node->value[prev_len], value, len); ++ ++ return node; ++ } ++ else /* if (node->value != NULL && node->value != node->small_value) */ ++ { ++ /* value is allocated */ ++ int prev_len = node->value_len; ++ node->value_len += len; ++ ++ node->value = _asn1_realloc (node->value, node->value_len); ++ if (node->value == NULL) ++ { ++ node->value_len = 0; ++ return NULL; ++ } ++ ++ memcpy (&node->value[prev_len], value, len); ++ ++ return node; ++ } ++} ++ ++/******************************************************************/ ++/* Function : _asn1_set_name */ ++/* Description: sets the field NAME in a NODE_ASN element. The */ ++/* previous value (if exist) will be lost */ ++/* Parameters: */ ++/* node: element pointer. */ ++/* name: a null terminated string with the name that you want */ ++/* to set. */ ++/* Return: pointer to the NODE_ASN element. */ ++/******************************************************************/ ++asn1_node ++_asn1_set_name (asn1_node node, const char *name) ++{ ++ if (node == NULL) ++ return node; ++ ++ _asn1_str_cpy (node->name, sizeof (node->name), name ? name : ""); ++ node->name_hash = _asn1_hash_name (node->name); ++ ++ return node; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_cpy_name */ ++/* Description: copies the field NAME in a NODE_ASN element. */ ++/* Parameters: */ ++/* dst: a dest element pointer. */ ++/* src: a source element pointer. */ ++/* Return: pointer to the NODE_ASN element. */ ++/******************************************************************/ ++asn1_node ++_asn1_cpy_name (asn1_node dst, asn1_node_const src) ++{ ++ if (dst == NULL) ++ return dst; ++ ++ if (src == NULL) ++ { ++ dst->name[0] = 0; ++ dst->name_hash = _asn1_hash_name (dst->name); ++ return dst; ++ } ++ ++ _asn1_str_cpy (dst->name, sizeof (dst->name), src->name); ++ dst->name_hash = src->name_hash; ++ ++ return dst; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_set_right */ ++/* Description: sets the field RIGHT in a NODE_ASN element. */ ++/* Parameters: */ ++/* node: element pointer. */ ++/* right: pointer to a NODE_ASN element that you want be pointed*/ ++/* by NODE. */ ++/* Return: pointer to *NODE. */ ++/******************************************************************/ ++asn1_node ++_asn1_set_right (asn1_node node, asn1_node right) ++{ ++ if (node == NULL) ++ return node; ++ node->right = right; ++ if (right) ++ right->left = node; ++ return node; ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_get_last_right */ ++/* Description: return the last element along the right chain. */ ++/* Parameters: */ ++/* node: starting element pointer. */ ++/* Return: pointer to the last element along the right chain. */ ++/******************************************************************/ ++asn1_node ++_asn1_get_last_right (asn1_node_const node) ++{ ++ asn1_node_const p; ++ ++ if (node == NULL) ++ return NULL; ++ p = node; ++ while (p->right) ++ p = p->right; ++ return (asn1_node) p; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_remove_node */ ++/* Description: gets free the memory allocated for an NODE_ASN */ ++/* element (not the elements pointed by it). */ ++/* Parameters: */ ++/* node: NODE_ASN element pointer. */ ++/* flags: ASN1_DELETE_FLAG_* */ ++/******************************************************************/ ++void ++_asn1_remove_node (asn1_node node, unsigned int flags) ++{ ++ if (node == NULL) ++ return; ++ ++ if (node->value != NULL) ++ { ++ if (flags & ASN1_DELETE_FLAG_ZEROIZE) ++ { ++ safe_memset(node->value, 0, node->value_len); ++ } ++ ++ if (node->value != node->small_value) ++ free (node->value); ++ } ++ free (node); ++} ++ ++/******************************************************************/ ++/* Function : _asn1_find_up */ ++/* Description: return the father of the NODE_ASN element. */ ++/* Parameters: */ ++/* node: NODE_ASN element pointer. */ ++/* Return: Null if not found. */ ++/******************************************************************/ ++asn1_node ++_asn1_find_up (asn1_node_const node) ++{ ++ asn1_node_const p; ++ ++ if (node == NULL) ++ return NULL; ++ ++ p = node; ++ ++ while ((p->left != NULL) && (p->left->right == p)) ++ p = p->left; ++ ++ return p->left; ++} ++ ++static ++unsigned _asn1_is_up (asn1_node_const up_cand, asn1_node_const down) ++{ ++ asn1_node_const d, u; ++ ++ if (up_cand == NULL || down == NULL) ++ return 0; ++ ++ d = down; ++ ++ while ((u = _asn1_find_up(d)) != NULL && u != d) ++ { ++ if (u == up_cand) ++ return 1; ++ d = u; ++ } ++ ++ return 0; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_delete_node_from_list */ ++/* Description: deletes the list element given */ ++/******************************************************************/ ++void ++_asn1_delete_node_from_list (list_type *list, asn1_node node) ++{ ++ list_type *p = list; ++ ++ while (p) ++ { ++ if (p->node == node) ++ p->node = NULL; ++ p = p->next; ++ } ++} ++ ++/******************************************************************/ ++/* Function : _asn1_delete_list */ ++/* Description: deletes the list elements (not the elements */ ++/* pointed by them). */ ++/******************************************************************/ ++void ++_asn1_delete_list (list_type *e_list) ++{ ++ list_type *p; ++ ++ while (e_list) ++ { ++ p = e_list; ++ e_list = e_list->next; ++ free (p); ++ } ++} ++ ++/******************************************************************/ ++/* Function : _asn1_delete_list_and nodes */ ++/* Description: deletes the list elements and the elements */ ++/* pointed by them. */ ++/******************************************************************/ ++void ++_asn1_delete_list_and_nodes (list_type *e_list) ++{ ++ list_type *p; ++ ++ while (e_list) ++ { ++ p = e_list; ++ e_list = e_list->next; ++ _asn1_remove_node (p->node, 0); ++ free (p); ++ } ++} ++ ++ ++char * ++_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]) ++{ ++ uint64_t d, r; ++ char temp[LTOSTR_MAX_SIZE]; ++ int count, k, start; ++ uint64_t val; ++ ++ if (v < 0) ++ { ++ str[0] = '-'; ++ start = 1; ++ val = -((uint64_t)v); ++ } ++ else ++ { ++ val = v; ++ start = 0; ++ } ++ ++ count = 0; ++ do ++ { ++ d = val / 10; ++ r = val - d * 10; ++ temp[start + count] = '0' + (char) r; ++ count++; ++ val = d; ++ } ++ while (val && ((start+count) < LTOSTR_MAX_SIZE-1)); ++ ++ for (k = 0; k < count; k++) ++ str[k + start] = temp[start + count - k - 1]; ++ str[count + start] = 0; ++ return str; ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_change_integer_value */ ++/* Description: converts into DER coding the value assign to an */ ++/* INTEGER constant. */ ++/* Parameters: */ ++/* node: root of an ASN1element. */ ++/* Return: */ ++/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ ++/* otherwise ASN1_SUCCESS */ ++/******************************************************************/ ++int ++_asn1_change_integer_value (asn1_node node) ++{ ++ asn1_node p; ++ unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; ++ unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1]; ++ int len; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node; ++ while (p) ++ { ++ if ((type_field (p->type) == ASN1_ETYPE_INTEGER) ++ && (p->type & CONST_ASSIGN)) ++ { ++ if (p->value) ++ { ++ _asn1_convert_integer (p->value, val, sizeof (val), &len); ++ asn1_octet_der (val, len, val2, &len); ++ _asn1_set_value (p, val2, len); ++ } ++ } ++ ++ if (p->down) ++ { ++ p = p->down; ++ } ++ else ++ { ++ if (p == node) ++ p = NULL; ++ else if (p->right) ++ p = p->right; ++ else ++ { ++ while (1) ++ { ++ p = _asn1_find_up (p); ++ if (p == node) ++ { ++ p = NULL; ++ break; ++ } ++ if (p && p->right) ++ { ++ p = p->right; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++#define MAX_CONSTANTS 1024 ++/******************************************************************/ ++/* Function : _asn1_expand_object_id */ ++/* Description: expand the IDs of an OBJECT IDENTIFIER constant. */ ++/* Parameters: */ ++/* list: root of an object list */ ++/* node: root of an ASN1 element. */ ++/* Return: */ ++/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ ++/* otherwise ASN1_SUCCESS */ ++/******************************************************************/ ++int ++_asn1_expand_object_id (list_type **list, asn1_node node) ++{ ++ asn1_node p, p2, p3, p4, p5; ++ char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1]; ++ int move, tlen, tries; ++ unsigned max_constants; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ _asn1_str_cpy (name_root, sizeof (name_root), node->name); ++ ++ p = node; ++ move = DOWN; ++ tries = 0; ++ ++ while (!((p == node) && (move == UP))) ++ { ++ if (move != UP) ++ { ++ if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) ++ && (p->type & CONST_ASSIGN)) ++ { ++ p2 = p->down; ++ if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) ++ { ++ if (p2->value && !c_isdigit (p2->value[0])) ++ { ++ _asn1_str_cpy (name2, sizeof (name2), name_root); ++ _asn1_str_cat (name2, sizeof (name2), "."); ++ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); ++ p3 = asn1_find_node (node, name2); ++ if (!p3 || _asn1_is_up(p2, p3) || ++ (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || ++ !(p3->type & CONST_ASSIGN)) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ _asn1_set_down (p, p2->right); ++ if (p2->down) ++ _asn1_delete_structure (*list, &p2->down, 0); ++ _asn1_delete_node_from_list(*list, p2); ++ _asn1_remove_node (p2, 0); ++ p2 = p; ++ p4 = p3->down; ++ max_constants = 0; ++ while (p4) ++ { ++ if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) ++ { ++ max_constants++; ++ if (max_constants == MAX_CONSTANTS) ++ return ASN1_RECURSION; ++ ++ p5 = ++ _asn1_add_single_node (ASN1_ETYPE_CONSTANT); ++ _asn1_set_name (p5, p4->name); ++ if (p4->value) ++ { ++ tlen = _asn1_strlen (p4->value); ++ if (tlen > 0) ++ _asn1_set_value (p5, p4->value, tlen + 1); ++ } ++ _asn1_add_static_node2(list, p5); ++ ++ if (p2 == p) ++ { ++ _asn1_set_right (p5, p->down); ++ _asn1_set_down (p, p5); ++ } ++ else ++ { ++ _asn1_set_right (p5, p2->right); ++ _asn1_set_right (p2, p5); ++ } ++ p2 = p5; ++ } ++ p4 = p4->right; ++ } ++ move = DOWN; ++ ++ tries++; ++ if (tries >= EXPAND_OBJECT_ID_MAX_RECURSION) ++ return ASN1_RECURSION; ++ ++ continue; ++ } ++ } ++ } ++ move = DOWN; ++ } ++ else ++ move = RIGHT; ++ ++ tries = 0; ++ if (move == DOWN) ++ { ++ if (p->down) ++ p = p->down; ++ else ++ move = RIGHT; ++ } ++ ++ if (p == node) ++ { ++ move = UP; ++ continue; ++ } ++ ++ if (move == RIGHT) ++ { ++ if (p && p->right) ++ p = p->right; ++ else ++ move = UP; ++ } ++ if (move == UP) ++ p = _asn1_find_up (p); ++ } ++ ++ /*******************************/ ++ /* expand DEFAULT */ ++ /*******************************/ ++ p = node; ++ move = DOWN; ++ ++ while (!((p == node) && (move == UP))) ++ { ++ if (move != UP) ++ { ++ if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && ++ (p->type & CONST_DEFAULT)) ++ { ++ p2 = p->down; ++ if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) ++ { ++ _asn1_str_cpy (name2, sizeof (name2), name_root); ++ _asn1_str_cat (name2, sizeof (name2), "."); ++ if (p2->value) ++ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); ++ p3 = asn1_find_node (node, name2); ++ if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) ++ || !(p3->type & CONST_ASSIGN)) ++ return ASN1_ELEMENT_NOT_FOUND; ++ p4 = p3->down; ++ name2[0] = 0; ++ while (p4) ++ { ++ if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) ++ { ++ if (p4->value == NULL) ++ return ASN1_VALUE_NOT_FOUND; ++ ++ if (name2[0]) ++ _asn1_str_cat (name2, sizeof (name2), "."); ++ _asn1_str_cat (name2, sizeof (name2), ++ (char *) p4->value); ++ } ++ p4 = p4->right; ++ } ++ tlen = strlen (name2); ++ if (tlen > 0) ++ _asn1_set_value (p2, name2, tlen + 1); ++ } ++ } ++ move = DOWN; ++ } ++ else ++ move = RIGHT; ++ ++ if (move == DOWN) ++ { ++ if (p->down) ++ p = p->down; ++ else ++ move = RIGHT; ++ } ++ ++ if (p == node) ++ { ++ move = UP; ++ continue; ++ } ++ ++ if (move == RIGHT) ++ { ++ if (p && p->right) ++ p = p->right; ++ else ++ move = UP; ++ } ++ if (move == UP) ++ p = _asn1_find_up (p); ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_type_set_config */ ++/* Description: sets the CONST_SET and CONST_NOT_USED properties */ ++/* in the fields of the SET elements. */ ++/* Parameters: */ ++/* node: root of an ASN1 element. */ ++/* Return: */ ++/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ ++/* otherwise ASN1_SUCCESS */ ++/******************************************************************/ ++int ++_asn1_type_set_config (asn1_node node) ++{ ++ asn1_node p, p2; ++ int move; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node; ++ move = DOWN; ++ ++ while (!((p == node) && (move == UP))) ++ { ++ if (move != UP) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_SET) ++ { ++ p2 = p->down; ++ while (p2) ++ { ++ if (type_field (p2->type) != ASN1_ETYPE_TAG) ++ p2->type |= CONST_SET | CONST_NOT_USED; ++ p2 = p2->right; ++ } ++ } ++ move = DOWN; ++ } ++ else ++ move = RIGHT; ++ ++ if (move == DOWN) ++ { ++ if (p->down) ++ p = p->down; ++ else ++ move = RIGHT; ++ } ++ ++ if (p == node) ++ { ++ move = UP; ++ continue; ++ } ++ ++ if (move == RIGHT) ++ { ++ if (p && p->right) ++ p = p->right; ++ else ++ move = UP; ++ } ++ if (move == UP) ++ p = _asn1_find_up (p); ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_check_identifier */ ++/* Description: checks the definitions of all the identifiers */ ++/* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */ ++/* The _asn1_identifierMissing global variable is filled if */ ++/* necessary. */ ++/* Parameters: */ ++/* node: root of an ASN1 element. */ ++/* Return: */ ++/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ ++/* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */ ++/* otherwise ASN1_SUCCESS */ ++/******************************************************************/ ++int ++_asn1_check_identifier (asn1_node_const node) ++{ ++ asn1_node_const p, p2; ++ char name2[ASN1_MAX_NAME_SIZE * 2 + 2]; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node; ++ while (p) ++ { ++ if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER) ++ { ++ _asn1_str_cpy (name2, sizeof (name2), node->name); ++ _asn1_str_cat (name2, sizeof (name2), "."); ++ _asn1_str_cat (name2, sizeof (name2), (char *) p->value); ++ p2 = asn1_find_node (node, name2); ++ if (p2 == NULL) ++ { ++ if (p->value) ++ _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p->value); ++ else ++ _asn1_strcpy (_asn1_identifierMissing, "(null)"); ++ return ASN1_IDENTIFIER_NOT_FOUND; ++ } ++ } ++ else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && ++ (p->type & CONST_DEFAULT)) ++ { ++ p2 = p->down; ++ if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) ++ { ++ _asn1_str_cpy (name2, sizeof (name2), node->name); ++ if (p2->value) ++ { ++ _asn1_str_cat (name2, sizeof (name2), "."); ++ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); ++ _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); ++ } ++ else ++ _asn1_strcpy (_asn1_identifierMissing, "(null)"); ++ ++ p2 = asn1_find_node (node, name2); ++ if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) || ++ !(p2->type & CONST_ASSIGN)) ++ return ASN1_IDENTIFIER_NOT_FOUND; ++ else ++ _asn1_identifierMissing[0] = 0; ++ } ++ } ++ else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && ++ (p->type & CONST_ASSIGN)) ++ { ++ p2 = p->down; ++ if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) ++ { ++ if (p2->value && !c_isdigit (p2->value[0])) ++ { ++ _asn1_str_cpy (name2, sizeof (name2), node->name); ++ _asn1_str_cat (name2, sizeof (name2), "."); ++ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); ++ _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); ++ ++ p2 = asn1_find_node (node, name2); ++ if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ++ || !(p2->type & CONST_ASSIGN)) ++ return ASN1_IDENTIFIER_NOT_FOUND; ++ else ++ _asn1_identifierMissing[0] = 0; ++ } ++ } ++ } ++ ++ if (p->down) ++ { ++ p = p->down; ++ } ++ else if (p->right) ++ p = p->right; ++ else ++ { ++ while (p) ++ { ++ p = _asn1_find_up (p); ++ if (p == node) ++ { ++ p = NULL; ++ break; ++ } ++ if (p && p->right) ++ { ++ p = p->right; ++ break; ++ } ++ } ++ } ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_set_default_tag */ ++/* Description: sets the default IMPLICIT or EXPLICIT property in */ ++/* the tagged elements that don't have this declaration. */ ++/* Parameters: */ ++/* node: pointer to a DEFINITIONS element. */ ++/* Return: */ ++/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */ ++/* a DEFINITIONS element, */ ++/* otherwise ASN1_SUCCESS */ ++/******************************************************************/ ++int ++_asn1_set_default_tag (asn1_node node) ++{ ++ asn1_node p; ++ ++ if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS)) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node; ++ while (p) ++ { ++ if ((type_field (p->type) == ASN1_ETYPE_TAG) && ++ !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT)) ++ { ++ if (node->type & CONST_EXPLICIT) ++ p->type |= CONST_EXPLICIT; ++ else ++ p->type |= CONST_IMPLICIT; ++ } ++ ++ if (p->down) ++ { ++ p = p->down; ++ } ++ else if (p->right) ++ p = p->right; ++ else ++ { ++ while (1) ++ { ++ p = _asn1_find_up (p); ++ if (p == node) ++ { ++ p = NULL; ++ break; ++ } ++ if (p && p->right) ++ { ++ p = p->right; ++ break; ++ } ++ } ++ } ++ } ++ ++ return ASN1_SUCCESS; ++} +diff --git a/grub-core/lib/libtasn1/lib/structure.c b/grub-core/lib/libtasn1/lib/structure.c +new file mode 100644 +index 0000000000..8189c56a4c +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/structure.c +@@ -0,0 +1,1220 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++ ++/*****************************************************/ ++/* File: structure.c */ ++/* Description: Functions to create and delete an */ ++/* ASN1 tree. */ ++/*****************************************************/ ++ ++ ++#include ++#include ++#include "parser_aux.h" ++#include ++ ++ ++extern char _asn1_identifierMissing[]; ++ ++ ++/******************************************************/ ++/* Function : _asn1_add_single_node */ ++/* Description: creates a new NODE_ASN element. */ ++/* Parameters: */ ++/* type: type of the new element (see ASN1_ETYPE_ */ ++/* and CONST_ constants). */ ++/* Return: pointer to the new element. */ ++/******************************************************/ ++asn1_node ++_asn1_add_single_node (unsigned int type) ++{ ++ asn1_node punt; ++ ++ punt = calloc (1, sizeof (struct asn1_node_st)); ++ if (punt == NULL) ++ return NULL; ++ ++ punt->type = type; ++ ++ return punt; ++} ++ ++ ++/******************************************************************/ ++/* Function : _asn1_find_left */ ++/* Description: returns the NODE_ASN element with RIGHT field that*/ ++/* points the element NODE. */ ++/* Parameters: */ ++/* node: NODE_ASN element pointer. */ ++/* Return: NULL if not found. */ ++/******************************************************************/ ++asn1_node ++_asn1_find_left (asn1_node_const node) ++{ ++ if ((node == NULL) || (node->left == NULL) || (node->left->down == node)) ++ return NULL; ++ ++ return node->left; ++} ++ ++ ++int ++_asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, ++ char *vector_name) ++{ ++ FILE *file; ++ asn1_node_const p; ++ unsigned long t; ++ ++ file = fopen (output_file_name, "w"); ++ ++ if (file == NULL) ++ return ASN1_FILE_NOT_FOUND; ++ ++ fprintf (file, "#if HAVE_CONFIG_H\n"); ++ fprintf (file, "# include \"config.h\"\n"); ++ fprintf (file, "#endif\n\n"); ++ ++ fprintf (file, "#include \n\n"); ++ ++ fprintf (file, "const asn1_static_node %s[] = {\n", vector_name); ++ ++ p = pointer; ++ ++ while (p) ++ { ++ fprintf (file, " { "); ++ ++ if (p->name[0] != 0) ++ fprintf (file, "\"%s\", ", p->name); ++ else ++ fprintf (file, "NULL, "); ++ ++ t = p->type; ++ if (p->down) ++ t |= CONST_DOWN; ++ if (p->right) ++ t |= CONST_RIGHT; ++ ++ fprintf (file, "%lu, ", t); ++ ++ if (p->value) ++ fprintf (file, "\"%s\"},\n", p->value); ++ else ++ fprintf (file, "NULL },\n"); ++ ++ if (p->down) ++ { ++ p = p->down; ++ } ++ else if (p->right) ++ { ++ p = p->right; ++ } ++ else ++ { ++ while (1) ++ { ++ p = _asn1_find_up (p); ++ if (p == pointer) ++ { ++ p = NULL; ++ break; ++ } ++ if (p->right) ++ { ++ p = p->right; ++ break; ++ } ++ } ++ } ++ } ++ ++ fprintf (file, " { NULL, 0, NULL }\n};\n"); ++ ++ fclose (file); ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/** ++ * asn1_array2tree: ++ * @array: specify the array that contains ASN.1 declarations ++ * @definitions: return the pointer to the structure created by ++ * *ARRAY ASN.1 declarations ++ * @errorDescription: return the error description. ++ * ++ * Creates the structures needed to manage the ASN.1 definitions. ++ * @array is a vector created by asn1_parser2array(). ++ * ++ * Returns: %ASN1_SUCCESS if structure was created correctly, ++ * %ASN1_ELEMENT_NOT_EMPTY if *@definitions not NULL, ++ * %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier ++ * that is not defined (see @errorDescription for more information), ++ * %ASN1_ARRAY_ERROR if the array pointed by @array is wrong. ++ **/ ++int ++asn1_array2tree (const asn1_static_node * array, asn1_node * definitions, ++ char *errorDescription) ++{ ++ asn1_node p, p_last = NULL; ++ unsigned long k; ++ int move; ++ int result; ++ unsigned int type; ++ list_type *e_list = NULL; ++ ++ if (errorDescription) ++ errorDescription[0] = 0; ++ ++ if (*definitions != NULL) ++ return ASN1_ELEMENT_NOT_EMPTY; ++ ++ move = UP; ++ ++ for (k = 0; array[k].value || array[k].type || array[k].name; k++) ++ { ++ type = convert_old_type (array[k].type); ++ ++ p = _asn1_add_static_node (&e_list, type & (~CONST_DOWN)); ++ if (array[k].name) ++ _asn1_set_name (p, array[k].name); ++ if (array[k].value) ++ _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1); ++ ++ if (*definitions == NULL) ++ *definitions = p; ++ ++ if (move == DOWN) ++ { ++ if (p_last && p_last->down) ++ _asn1_delete_structure (e_list, &p_last->down, 0); ++ _asn1_set_down (p_last, p); ++ } ++ else if (move == RIGHT) ++ { ++ if (p_last && p_last->right) ++ _asn1_delete_structure (e_list, &p_last->right, 0); ++ _asn1_set_right (p_last, p); ++ } ++ ++ p_last = p; ++ ++ if (type & CONST_DOWN) ++ move = DOWN; ++ else if (type & CONST_RIGHT) ++ move = RIGHT; ++ else ++ { ++ while (p_last != *definitions) ++ { ++ p_last = _asn1_find_up (p_last); ++ ++ if (p_last == NULL) ++ break; ++ ++ if (p_last->type & CONST_RIGHT) ++ { ++ p_last->type &= ~CONST_RIGHT; ++ move = RIGHT; ++ break; ++ } ++ } /* while */ ++ } ++ } /* while */ ++ ++ if (p_last == *definitions) ++ { ++ result = _asn1_check_identifier (*definitions); ++ if (result == ASN1_SUCCESS) ++ { ++ _asn1_change_integer_value (*definitions); ++ result = _asn1_expand_object_id (&e_list, *definitions); ++ } ++ } ++ else ++ { ++ result = ASN1_ARRAY_ERROR; ++ } ++ ++ if (errorDescription != NULL) ++ { ++ if (result == ASN1_IDENTIFIER_NOT_FOUND) ++ { ++ Estrcpy (errorDescription, ":: identifier '"); ++ Estrcat (errorDescription, _asn1_identifierMissing); ++ Estrcat (errorDescription, "' not found"); ++ } ++ else ++ errorDescription[0] = 0; ++ } ++ ++ if (result != ASN1_SUCCESS) ++ { ++ _asn1_delete_list_and_nodes (e_list); ++ *definitions = NULL; ++ } ++ else ++ _asn1_delete_list (e_list); ++ ++ return result; ++} ++ ++/** ++ * asn1_delete_structure: ++ * @structure: pointer to the structure that you want to delete. ++ * ++ * Deletes the structure *@structure. At the end, *@structure is set ++ * to NULL. ++ * ++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if ++ * *@structure was NULL. ++ **/ ++int ++asn1_delete_structure (asn1_node * structure) ++{ ++ return _asn1_delete_structure (NULL, structure, 0); ++} ++ ++/** ++ * asn1_delete_structure2: ++ * @structure: pointer to the structure that you want to delete. ++ * @flags: additional flags (see %ASN1_DELETE_FLAG) ++ * ++ * Deletes the structure *@structure. At the end, *@structure is set ++ * to NULL. ++ * ++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if ++ * *@structure was NULL. ++ **/ ++int ++asn1_delete_structure2 (asn1_node * structure, unsigned int flags) ++{ ++ return _asn1_delete_structure (NULL, structure, flags); ++} ++ ++int ++_asn1_delete_structure (list_type *e_list, asn1_node * structure, unsigned int flags) ++{ ++ asn1_node p, p2, p3; ++ ++ if (*structure == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = *structure; ++ while (p) ++ { ++ if (p->down) ++ { ++ p = p->down; ++ } ++ else ++ { /* no down */ ++ p2 = p->right; ++ if (p != *structure) ++ { ++ p3 = _asn1_find_up (p); ++ _asn1_set_down (p3, p2); ++ if (e_list) ++ _asn1_delete_node_from_list (e_list, p); ++ _asn1_remove_node (p, flags); ++ p = p3; ++ } ++ else ++ { /* p==root */ ++ p3 = _asn1_find_left (p); ++ if (!p3) ++ { ++ p3 = _asn1_find_up (p); ++ if (p3) ++ _asn1_set_down (p3, p2); ++ else ++ { ++ if (p->right) ++ p->right->left = NULL; ++ } ++ } ++ else ++ _asn1_set_right (p3, p2); ++ if (e_list) ++ _asn1_delete_node_from_list (e_list, p); ++ _asn1_remove_node (p, flags); ++ p = NULL; ++ } ++ } ++ } ++ ++ *structure = NULL; ++ return ASN1_SUCCESS; ++} ++ ++ ++/** ++ * asn1_delete_element: ++ * @structure: pointer to the structure that contains the element you ++ * want to delete. ++ * @element_name: element's name you want to delete. ++ * ++ * Deletes the element named *@element_name inside *@structure. ++ * ++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if ++ * the @element_name was not found. ++ **/ ++int ++asn1_delete_element (asn1_node structure, const char *element_name) ++{ ++ asn1_node p2, p3, source_node; ++ ++ source_node = asn1_find_node (structure, element_name); ++ ++ if (source_node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p2 = source_node->right; ++ p3 = _asn1_find_left (source_node); ++ if (!p3) ++ { ++ p3 = _asn1_find_up (source_node); ++ if (p3) ++ _asn1_set_down (p3, p2); ++ else if (source_node->right) ++ source_node->right->left = NULL; ++ } ++ else ++ _asn1_set_right (p3, p2); ++ ++ return asn1_delete_structure (&source_node); ++} ++ ++#ifndef __clang_analyzer__ ++asn1_node ++_asn1_copy_structure3 (asn1_node_const source_node) ++{ ++ asn1_node_const p_s; ++ asn1_node dest_node, p_d, p_d_prev; ++ int move; ++ ++ if (source_node == NULL) ++ return NULL; ++ ++ dest_node = _asn1_add_single_node (source_node->type); ++ ++ p_s = source_node; ++ p_d = dest_node; ++ ++ move = DOWN; ++ ++ do ++ { ++ if (move != UP) ++ { ++ if (p_s->name[0] != 0) ++ _asn1_cpy_name (p_d, p_s); ++ if (p_s->value) ++ _asn1_set_value (p_d, p_s->value, p_s->value_len); ++ if (p_s->down) ++ { ++ p_s = p_s->down; ++ p_d_prev = p_d; ++ p_d = _asn1_add_single_node (p_s->type); ++ _asn1_set_down (p_d_prev, p_d); ++ continue; ++ } ++ p_d->start = p_s->start; ++ p_d->end = p_s->end; ++ } ++ ++ if (p_s == source_node) ++ break; ++ ++ if (p_s->right) ++ { ++ move = RIGHT; ++ p_s = p_s->right; ++ p_d_prev = p_d; ++ p_d = _asn1_add_single_node (p_s->type); ++ _asn1_set_right (p_d_prev, p_d); ++ } ++ else ++ { ++ move = UP; ++ p_s = _asn1_find_up (p_s); ++ p_d = _asn1_find_up (p_d); ++ } ++ } ++ while (p_s != source_node); ++ return dest_node; ++} ++#else ++ ++/* Non-production code */ ++asn1_node ++_asn1_copy_structure3 (asn1_node_const source_node) ++{ ++ return NULL; ++} ++#endif /* __clang_analyzer__ */ ++ ++ ++static asn1_node ++_asn1_copy_structure2 (asn1_node_const root, const char *source_name) ++{ ++ asn1_node source_node; ++ ++ source_node = asn1_find_node (root, source_name); ++ ++ return _asn1_copy_structure3 (source_node); ++ ++} ++ ++ ++static int ++_asn1_type_choice_config (asn1_node node) ++{ ++ asn1_node p, p2, p3, p4; ++ int move, tlen; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node; ++ move = DOWN; ++ ++ while (!((p == node) && (move == UP))) ++ { ++ if (move != UP) ++ { ++ if ((type_field (p->type) == ASN1_ETYPE_CHOICE) ++ && (p->type & CONST_TAG)) ++ { ++ p2 = p->down; ++ while (p2) ++ { ++ if (type_field (p2->type) != ASN1_ETYPE_TAG) ++ { ++ p2->type |= CONST_TAG; ++ p3 = _asn1_find_left (p2); ++ while (p3) ++ { ++ if (type_field (p3->type) == ASN1_ETYPE_TAG) ++ { ++ p4 = _asn1_add_single_node (p3->type); ++ tlen = _asn1_strlen (p3->value); ++ if (tlen > 0) ++ _asn1_set_value (p4, p3->value, tlen + 1); ++ _asn1_set_right (p4, p2->down); ++ _asn1_set_down (p2, p4); ++ } ++ p3 = _asn1_find_left (p3); ++ } ++ } ++ p2 = p2->right; ++ } ++ p->type &= ~(CONST_TAG); ++ p2 = p->down; ++ while (p2) ++ { ++ p3 = p2->right; ++ if (type_field (p2->type) == ASN1_ETYPE_TAG) ++ asn1_delete_structure (&p2); ++ p2 = p3; ++ } ++ } ++ move = DOWN; ++ } ++ else ++ move = RIGHT; ++ ++ if (move == DOWN) ++ { ++ if (p->down) ++ p = p->down; ++ else ++ move = RIGHT; ++ } ++ ++ if (p == node) ++ { ++ move = UP; ++ continue; ++ } ++ ++ if (move == RIGHT) ++ { ++ if (p->right) ++ p = p->right; ++ else ++ move = UP; ++ } ++ if (move == UP) ++ p = _asn1_find_up (p); ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++static int ++_asn1_expand_identifier (asn1_node * node, asn1_node_const root) ++{ ++ asn1_node p, p2, p3; ++ char name2[ASN1_MAX_NAME_SIZE + 2]; ++ int move; ++ ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = *node; ++ move = DOWN; ++ ++ while (!((p == *node) && (move == UP))) ++ { ++ if (move != UP) ++ { ++ if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER) ++ { ++ snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value); ++ p2 = _asn1_copy_structure2 (root, name2); ++ if (p2 == NULL) ++ { ++ return ASN1_IDENTIFIER_NOT_FOUND; ++ } ++ _asn1_cpy_name (p2, p); ++ p2->right = p->right; ++ p2->left = p->left; ++ if (p->right) ++ p->right->left = p2; ++ p3 = p->down; ++ if (p3) ++ { ++ while (p3->right) ++ p3 = p3->right; ++ _asn1_set_right (p3, p2->down); ++ _asn1_set_down (p2, p->down); ++ } ++ ++ p3 = _asn1_find_left (p); ++ if (p3) ++ _asn1_set_right (p3, p2); ++ else ++ { ++ p3 = _asn1_find_up (p); ++ if (p3) ++ _asn1_set_down (p3, p2); ++ else ++ { ++ p2->left = NULL; ++ } ++ } ++ ++ if (p->type & CONST_SIZE) ++ p2->type |= CONST_SIZE; ++ if (p->type & CONST_TAG) ++ p2->type |= CONST_TAG; ++ if (p->type & CONST_OPTION) ++ p2->type |= CONST_OPTION; ++ if (p->type & CONST_DEFAULT) ++ p2->type |= CONST_DEFAULT; ++ if (p->type & CONST_SET) ++ p2->type |= CONST_SET; ++ if (p->type & CONST_NOT_USED) ++ p2->type |= CONST_NOT_USED; ++ ++ if (p == *node) ++ *node = p2; ++ _asn1_remove_node (p, 0); ++ p = p2; ++ move = DOWN; ++ continue; ++ } ++ move = DOWN; ++ } ++ else ++ move = RIGHT; ++ ++ if (move == DOWN) ++ { ++ if (p->down) ++ p = p->down; ++ else ++ move = RIGHT; ++ } ++ ++ if (p == *node) ++ { ++ move = UP; ++ continue; ++ } ++ ++ if (move == RIGHT) ++ { ++ if (p->right) ++ p = p->right; ++ else ++ move = UP; ++ } ++ if (move == UP) ++ p = _asn1_find_up (p); ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/** ++ * asn1_create_element: ++ * @definitions: pointer to the structure returned by "parser_asn1" function ++ * @source_name: the name of the type of the new structure (must be ++ * inside p_structure). ++ * @element: pointer to the structure created. ++ * ++ * Creates a structure of type @source_name. Example using ++ * "pkix.asn": ++ * ++ * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr); ++ * ++ * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if ++ * @source_name is not known. ++ **/ ++int ++asn1_create_element (asn1_node_const definitions, const char *source_name, ++ asn1_node * element) ++{ ++ asn1_node dest_node; ++ int res; ++ ++ dest_node = _asn1_copy_structure2 (definitions, source_name); ++ ++ if (dest_node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ _asn1_set_name (dest_node, ""); ++ ++ res = _asn1_expand_identifier (&dest_node, definitions); ++ _asn1_type_choice_config (dest_node); ++ ++ *element = dest_node; ++ ++ return res; ++} ++ ++ ++/** ++ * asn1_print_structure: ++ * @out: pointer to the output file (e.g. stdout). ++ * @structure: pointer to the structure that you want to visit. ++ * @name: an element of the structure ++ * @mode: specify how much of the structure to print, can be ++ * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE, ++ * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL. ++ * ++ * Prints on the @out file descriptor the structure's tree starting ++ * from the @name element inside the structure @structure. ++ **/ ++void ++asn1_print_structure (FILE * out, asn1_node_const structure, const char *name, ++ int mode) ++{ ++ asn1_node_const p, root; ++ int k, indent = 0, len, len2, len3; ++ ++ if (out == NULL) ++ return; ++ ++ root = asn1_find_node (structure, name); ++ ++ if (root == NULL) ++ return; ++ ++ p = root; ++ while (p) ++ { ++ if (mode == ASN1_PRINT_ALL) ++ { ++ for (k = 0; k < indent; k++) ++ fprintf (out, " "); ++ fprintf (out, "name:"); ++ if (p->name[0] != 0) ++ fprintf (out, "%s ", p->name); ++ else ++ fprintf (out, "NULL "); ++ } ++ else ++ { ++ switch (type_field (p->type)) ++ { ++ case ASN1_ETYPE_CONSTANT: ++ case ASN1_ETYPE_TAG: ++ case ASN1_ETYPE_SIZE: ++ break; ++ default: ++ for (k = 0; k < indent; k++) ++ fprintf (out, " "); ++ fprintf (out, "name:"); ++ if (p->name[0] != 0) ++ fprintf (out, "%s ", p->name); ++ else ++ fprintf (out, "NULL "); ++ } ++ } ++ ++ if (mode != ASN1_PRINT_NAME) ++ { ++ unsigned type = type_field (p->type); ++ switch (type) ++ { ++ case ASN1_ETYPE_CONSTANT: ++ if (mode == ASN1_PRINT_ALL) ++ fprintf (out, "type:CONST"); ++ break; ++ case ASN1_ETYPE_TAG: ++ if (mode == ASN1_PRINT_ALL) ++ fprintf (out, "type:TAG"); ++ break; ++ case ASN1_ETYPE_SIZE: ++ if (mode == ASN1_PRINT_ALL) ++ fprintf (out, "type:SIZE"); ++ break; ++ case ASN1_ETYPE_DEFAULT: ++ fprintf (out, "type:DEFAULT"); ++ break; ++ case ASN1_ETYPE_IDENTIFIER: ++ fprintf (out, "type:IDENTIFIER"); ++ break; ++ case ASN1_ETYPE_ANY: ++ fprintf (out, "type:ANY"); ++ break; ++ case ASN1_ETYPE_CHOICE: ++ fprintf (out, "type:CHOICE"); ++ break; ++ case ASN1_ETYPE_DEFINITIONS: ++ fprintf (out, "type:DEFINITIONS"); ++ break; ++ CASE_HANDLED_ETYPES: ++ fprintf (out, "%s", _asn1_tags[type].desc); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL)) ++ { ++ switch (type_field (p->type)) ++ { ++ case ASN1_ETYPE_CONSTANT: ++ if (mode == ASN1_PRINT_ALL) ++ if (p->value) ++ fprintf (out, " value:%s", p->value); ++ break; ++ case ASN1_ETYPE_TAG: ++ if (mode == ASN1_PRINT_ALL) ++ if (p->value) ++ fprintf (out, " value:%s", p->value); ++ break; ++ case ASN1_ETYPE_SIZE: ++ if (mode == ASN1_PRINT_ALL) ++ if (p->value) ++ fprintf (out, " value:%s", p->value); ++ break; ++ case ASN1_ETYPE_DEFAULT: ++ if (p->value) ++ fprintf (out, " value:%s", p->value); ++ else if (p->type & CONST_TRUE) ++ fprintf (out, " value:TRUE"); ++ else if (p->type & CONST_FALSE) ++ fprintf (out, " value:FALSE"); ++ break; ++ case ASN1_ETYPE_IDENTIFIER: ++ if (p->value) ++ fprintf (out, " value:%s", p->value); ++ break; ++ case ASN1_ETYPE_INTEGER: ++ if (p->value) ++ { ++ len2 = -1; ++ len = asn1_get_length_der (p->value, p->value_len, &len2); ++ fprintf (out, " value:0x"); ++ if (len > 0) ++ for (k = 0; k < len; k++) ++ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); ++ } ++ break; ++ case ASN1_ETYPE_ENUMERATED: ++ if (p->value) ++ { ++ len2 = -1; ++ len = asn1_get_length_der (p->value, p->value_len, &len2); ++ fprintf (out, " value:0x"); ++ if (len > 0) ++ for (k = 0; k < len; k++) ++ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); ++ } ++ break; ++ case ASN1_ETYPE_BOOLEAN: ++ if (p->value) ++ { ++ if (p->value[0] == 'T') ++ fprintf (out, " value:TRUE"); ++ else if (p->value[0] == 'F') ++ fprintf (out, " value:FALSE"); ++ } ++ break; ++ case ASN1_ETYPE_BIT_STRING: ++ if (p->value) ++ { ++ len2 = -1; ++ len = asn1_get_length_der (p->value, p->value_len, &len2); ++ if (len > 0) ++ { ++ fprintf (out, " value(%i):", ++ (len - 1) * 8 - (p->value[len2])); ++ for (k = 1; k < len; k++) ++ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); ++ } ++ } ++ break; ++ case ASN1_ETYPE_GENERALIZED_TIME: ++ case ASN1_ETYPE_UTC_TIME: ++ if (p->value) ++ { ++ fprintf (out, " value:"); ++ for (k = 0; k < p->value_len; k++) ++ fprintf (out, "%c", (p->value)[k]); ++ } ++ break; ++ case ASN1_ETYPE_GENERALSTRING: ++ case ASN1_ETYPE_NUMERIC_STRING: ++ case ASN1_ETYPE_IA5_STRING: ++ case ASN1_ETYPE_TELETEX_STRING: ++ case ASN1_ETYPE_PRINTABLE_STRING: ++ case ASN1_ETYPE_UNIVERSAL_STRING: ++ case ASN1_ETYPE_UTF8_STRING: ++ case ASN1_ETYPE_VISIBLE_STRING: ++ if (p->value) ++ { ++ len2 = -1; ++ len = asn1_get_length_der (p->value, p->value_len, &len2); ++ fprintf (out, " value:"); ++ if (len > 0) ++ for (k = 0; k < len; k++) ++ fprintf (out, "%c", (p->value)[k + len2]); ++ } ++ break; ++ case ASN1_ETYPE_BMP_STRING: ++ case ASN1_ETYPE_OCTET_STRING: ++ if (p->value) ++ { ++ len2 = -1; ++ len = asn1_get_length_der (p->value, p->value_len, &len2); ++ fprintf (out, " value:"); ++ if (len > 0) ++ for (k = 0; k < len; k++) ++ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); ++ } ++ break; ++ case ASN1_ETYPE_OBJECT_ID: ++ if (p->value) ++ fprintf (out, " value:%s", p->value); ++ break; ++ case ASN1_ETYPE_ANY: ++ if (p->value) ++ { ++ len3 = -1; ++ len2 = asn1_get_length_der (p->value, p->value_len, &len3); ++ fprintf (out, " value:"); ++ if (len2 > 0) ++ for (k = 0; k < len2; k++) ++ fprintf (out, "%02x", (unsigned) (p->value)[k + len3]); ++ } ++ break; ++ case ASN1_ETYPE_SET: ++ case ASN1_ETYPE_SET_OF: ++ case ASN1_ETYPE_CHOICE: ++ case ASN1_ETYPE_DEFINITIONS: ++ case ASN1_ETYPE_SEQUENCE_OF: ++ case ASN1_ETYPE_SEQUENCE: ++ case ASN1_ETYPE_NULL: ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if (mode == ASN1_PRINT_ALL) ++ { ++ if (p->type & 0x1FFFFF00) ++ { ++ fprintf (out, " attr:"); ++ if (p->type & CONST_UNIVERSAL) ++ fprintf (out, "UNIVERSAL,"); ++ if (p->type & CONST_PRIVATE) ++ fprintf (out, "PRIVATE,"); ++ if (p->type & CONST_APPLICATION) ++ fprintf (out, "APPLICATION,"); ++ if (p->type & CONST_EXPLICIT) ++ fprintf (out, "EXPLICIT,"); ++ if (p->type & CONST_IMPLICIT) ++ fprintf (out, "IMPLICIT,"); ++ if (p->type & CONST_TAG) ++ fprintf (out, "TAG,"); ++ if (p->type & CONST_DEFAULT) ++ fprintf (out, "DEFAULT,"); ++ if (p->type & CONST_TRUE) ++ fprintf (out, "TRUE,"); ++ if (p->type & CONST_FALSE) ++ fprintf (out, "FALSE,"); ++ if (p->type & CONST_LIST) ++ fprintf (out, "LIST,"); ++ if (p->type & CONST_MIN_MAX) ++ fprintf (out, "MIN_MAX,"); ++ if (p->type & CONST_OPTION) ++ fprintf (out, "OPTION,"); ++ if (p->type & CONST_1_PARAM) ++ fprintf (out, "1_PARAM,"); ++ if (p->type & CONST_SIZE) ++ fprintf (out, "SIZE,"); ++ if (p->type & CONST_DEFINED_BY) ++ fprintf (out, "DEF_BY,"); ++ if (p->type & CONST_GENERALIZED) ++ fprintf (out, "GENERALIZED,"); ++ if (p->type & CONST_UTC) ++ fprintf (out, "UTC,"); ++ if (p->type & CONST_SET) ++ fprintf (out, "SET,"); ++ if (p->type & CONST_NOT_USED) ++ fprintf (out, "NOT_USED,"); ++ if (p->type & CONST_ASSIGN) ++ fprintf (out, "ASSIGNMENT,"); ++ } ++ } ++ ++ if (mode == ASN1_PRINT_ALL) ++ { ++ fprintf (out, "\n"); ++ } ++ else ++ { ++ switch (type_field (p->type)) ++ { ++ case ASN1_ETYPE_CONSTANT: ++ case ASN1_ETYPE_TAG: ++ case ASN1_ETYPE_SIZE: ++ break; ++ default: ++ fprintf (out, "\n"); ++ } ++ } ++ ++ if (p->down) ++ { ++ p = p->down; ++ indent += 2; ++ } ++ else if (p == root) ++ { ++ p = NULL; ++ break; ++ } ++ else if (p->right) ++ p = p->right; ++ else ++ { ++ while (1) ++ { ++ p = _asn1_find_up (p); ++ if (p == root) ++ { ++ p = NULL; ++ break; ++ } ++ indent -= 2; ++ if (p->right) ++ { ++ p = p->right; ++ break; ++ } ++ } ++ } ++ } ++} ++ ++ ++ ++/** ++ * asn1_number_of_elements: ++ * @element: pointer to the root of an ASN1 structure. ++ * @name: the name of a sub-structure of ROOT. ++ * @num: pointer to an integer where the result will be stored ++ * ++ * Counts the number of elements of a sub-structure called NAME with ++ * names equal to "?1","?2", ... ++ * ++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if ++ * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL. ++ **/ ++int ++asn1_number_of_elements (asn1_node_const element, const char *name, int *num) ++{ ++ asn1_node_const node, p; ++ ++ if (num == NULL) ++ return ASN1_GENERIC_ERROR; ++ ++ *num = 0; ++ ++ node = asn1_find_node (element, name); ++ if (node == NULL) ++ return ASN1_ELEMENT_NOT_FOUND; ++ ++ p = node->down; ++ ++ while (p) ++ { ++ if (p->name[0] == '?') ++ (*num)++; ++ p = p->right; ++ } ++ ++ return ASN1_SUCCESS; ++} ++ ++ ++/** ++ * asn1_find_structure_from_oid: ++ * @definitions: ASN1 definitions ++ * @oidValue: value of the OID to search (e.g. "1.2.3.4"). ++ * ++ * Search the structure that is defined just after an OID definition. ++ * ++ * Returns: %NULL when @oidValue not found, otherwise the pointer to a ++ * constant string that contains the element name defined just after ++ * the OID. ++ **/ ++const char * ++asn1_find_structure_from_oid (asn1_node_const definitions, const char *oidValue) ++{ ++ char name[2 * ASN1_MAX_NAME_SIZE + 2]; ++ char value[ASN1_MAX_NAME_SIZE]; ++ asn1_node p; ++ int len; ++ int result; ++ const char *definitionsName; ++ ++ if ((definitions == NULL) || (oidValue == NULL)) ++ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ ++ ++ definitionsName = definitions->name; ++ ++ /* search the OBJECT_ID into definitions */ ++ p = definitions->down; ++ while (p) ++ { ++ if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && ++ (p->type & CONST_ASSIGN)) ++ { ++ snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name); ++ ++ len = ASN1_MAX_NAME_SIZE; ++ result = asn1_read_value (definitions, name, value, &len); ++ ++ if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value))) ++ { ++ p = p->right; ++ if (p == NULL) /* reach the end of ASN1 definitions */ ++ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ ++ ++ return p->name; ++ } ++ } ++ p = p->right; ++ } ++ ++ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ ++} ++ ++/** ++ * asn1_copy_node: ++ * @dst: Destination asn1 node. ++ * @dst_name: Field name in destination node. ++ * @src: Source asn1 node. ++ * @src_name: Field name in source node. ++ * ++ * Create a deep copy of a asn1_node variable. That ++ * function requires @dst to be expanded using asn1_create_element(). ++ * ++ * Returns: Return %ASN1_SUCCESS on success. ++ **/ ++int ++asn1_copy_node (asn1_node dst, const char *dst_name, ++ asn1_node_const src, const char *src_name) ++{ ++ int result; ++ asn1_node dst_node; ++ void *data = NULL; ++ int size = 0; ++ ++ result = asn1_der_coding (src, src_name, NULL, &size, NULL); ++ if (result != ASN1_MEM_ERROR) ++ return result; ++ ++ data = malloc (size); ++ if (data == NULL) ++ return ASN1_MEM_ERROR; ++ ++ result = asn1_der_coding (src, src_name, data, &size, NULL); ++ if (result != ASN1_SUCCESS) ++ { ++ free (data); ++ return result; ++ } ++ ++ dst_node = asn1_find_node (dst, dst_name); ++ if (dst_node == NULL) ++ { ++ free (data); ++ return ASN1_ELEMENT_NOT_FOUND; ++ } ++ ++ result = asn1_der_decoding (&dst_node, data, size, NULL); ++ ++ free (data); ++ ++ return result; ++} ++ ++/** ++ * asn1_dup_node: ++ * @src: Source asn1 node. ++ * @src_name: Field name in source node. ++ * ++ * Create a deep copy of a asn1_node variable. This function ++ * will return an exact copy of the provided structure. ++ * ++ * Returns: Return %NULL on failure. ++ **/ ++asn1_node ++asn1_dup_node (asn1_node_const src, const char *src_name) ++{ ++ return _asn1_copy_structure2(src, src_name); ++} +diff --git a/grub-core/lib/libtasn1/lib/element.h b/grub-core/lib/libtasn1/lib/element.h +new file mode 100644 +index 0000000000..440a33f4bb +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/element.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2000-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++#ifndef _ELEMENT_H ++#define _ELEMENT_H ++ ++ ++struct node_tail_cache_st ++{ ++ asn1_node head; /* the first element of the sequence */ ++ asn1_node tail; ++}; ++ ++int _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcached); ++ ++int _asn1_convert_integer (const unsigned char *value, ++ unsigned char *value_out, ++ int value_out_size, int *len); ++ ++void _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size); ++ ++#endif +diff --git a/grub-core/lib/libtasn1/lib/gstr.h b/grub-core/lib/libtasn1/lib/gstr.h +new file mode 100644 +index 0000000000..48229844ff +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/gstr.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++#ifndef GSTR_H ++# define GSTR_H ++ ++unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size, ++ const char *src); ++void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src); ++ ++#define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) ++#define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) ++ ++inline static ++void safe_memset(void *data, int c, size_t size) ++{ ++ volatile unsigned volatile_zero = 0; ++ volatile char *vdata = (volatile char*)data; ++ ++ /* This is based on a nice trick for safe memset, ++ * sent by David Jacobson in the openssl-dev mailing list. ++ */ ++ ++ if (size > 0) do { ++ memset(data, c, size); ++ } while(vdata[volatile_zero] != c); ++} ++ ++#endif /* GSTR_H */ +diff --git a/grub-core/lib/libtasn1/lib/int.h b/grub-core/lib/libtasn1/lib/int.h +new file mode 100644 +index 0000000000..ea1625786c +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/int.h +@@ -0,0 +1,221 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++#ifndef INT_H ++#define INT_H ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_SYS_TYPES_H ++#include ++#endif ++ ++#include ++ ++#define ASN1_SMALL_VALUE_SIZE 16 ++ ++/* This structure is also in libtasn1.h, but then contains less ++ fields. You cannot make any modifications to these first fields ++ without breaking ABI. */ ++struct asn1_node_st ++{ ++ /* public fields: */ ++ char name[ASN1_MAX_NAME_SIZE + 1]; /* Node name */ ++ unsigned int name_hash; ++ unsigned int type; /* Node type */ ++ unsigned char *value; /* Node value */ ++ int value_len; ++ asn1_node down; /* Pointer to the son node */ ++ asn1_node right; /* Pointer to the brother node */ ++ asn1_node left; /* Pointer to the next list element */ ++ /* private fields: */ ++ unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */ ++ ++ /* values used during decoding/coding */ ++ int tmp_ival; ++ unsigned start; /* the start of the DER sequence - if decoded */ ++ unsigned end; /* the end of the DER sequence - if decoded */ ++}; ++ ++typedef struct tag_and_class_st ++{ ++ unsigned tag; ++ unsigned class; ++ const char *desc; ++} tag_and_class_st; ++ ++/* the types that are handled in _asn1_tags */ ++#define CASE_HANDLED_ETYPES \ ++ case ASN1_ETYPE_NULL: \ ++ case ASN1_ETYPE_BOOLEAN: \ ++ case ASN1_ETYPE_INTEGER: \ ++ case ASN1_ETYPE_ENUMERATED: \ ++ case ASN1_ETYPE_OBJECT_ID: \ ++ case ASN1_ETYPE_OCTET_STRING: \ ++ case ASN1_ETYPE_GENERALSTRING: \ ++ case ASN1_ETYPE_NUMERIC_STRING: \ ++ case ASN1_ETYPE_IA5_STRING: \ ++ case ASN1_ETYPE_TELETEX_STRING: \ ++ case ASN1_ETYPE_PRINTABLE_STRING: \ ++ case ASN1_ETYPE_UNIVERSAL_STRING: \ ++ case ASN1_ETYPE_BMP_STRING: \ ++ case ASN1_ETYPE_UTF8_STRING: \ ++ case ASN1_ETYPE_VISIBLE_STRING: \ ++ case ASN1_ETYPE_BIT_STRING: \ ++ case ASN1_ETYPE_SEQUENCE: \ ++ case ASN1_ETYPE_SEQUENCE_OF: \ ++ case ASN1_ETYPE_SET: \ ++ case ASN1_ETYPE_UTC_TIME: \ ++ case ASN1_ETYPE_GENERALIZED_TIME: \ ++ case ASN1_ETYPE_SET_OF ++ ++#define ETYPE_TAG(etype) (_asn1_tags[etype].tag) ++#define ETYPE_CLASS(etype) (_asn1_tags[etype].class) ++#define ETYPE_OK(etype) (((etype) != ASN1_ETYPE_INVALID && \ ++ (etype) <= _asn1_tags_size && \ ++ _asn1_tags[(etype)].desc != NULL)?1:0) ++ ++#define ETYPE_IS_STRING(etype) ((etype == ASN1_ETYPE_GENERALSTRING || \ ++ etype == ASN1_ETYPE_NUMERIC_STRING || etype == ASN1_ETYPE_IA5_STRING || \ ++ etype == ASN1_ETYPE_TELETEX_STRING || etype == ASN1_ETYPE_PRINTABLE_STRING || \ ++ etype == ASN1_ETYPE_UNIVERSAL_STRING || etype == ASN1_ETYPE_BMP_STRING || \ ++ etype == ASN1_ETYPE_UTF8_STRING || etype == ASN1_ETYPE_VISIBLE_STRING || \ ++ etype == ASN1_ETYPE_OCTET_STRING)?1:0) ++ ++extern unsigned int _asn1_tags_size; ++extern const tag_and_class_st _asn1_tags[]; ++ ++#define _asn1_strlen(s) strlen((const char *) s) ++#define _asn1_strtol(n,e,b) strtol((const char *) n, e, b) ++#define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b) ++#define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b) ++#define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b) ++#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b) ++ ++#if SIZEOF_UNSIGNED_LONG_INT == 8 ++# define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b) ++#else ++# define _asn1_strtou64(n,e,b) strtoull((const char *) n, e, b) ++#endif ++ ++#define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */ ++ ++/* Define used for visiting trees. */ ++#define UP 1 ++#define RIGHT 2 ++#define DOWN 3 ++ ++/***********************************************************************/ ++/* List of constants to better specify the type of typedef asn1_node_st. */ ++/***********************************************************************/ ++/* Used with TYPE_TAG */ ++#define CONST_UNIVERSAL (1U<<8) ++#define CONST_PRIVATE (1U<<9) ++#define CONST_APPLICATION (1U<<10) ++#define CONST_EXPLICIT (1U<<11) ++#define CONST_IMPLICIT (1U<<12) ++ ++#define CONST_TAG (1U<<13) /* Used in ASN.1 assignement */ ++#define CONST_OPTION (1U<<14) ++#define CONST_DEFAULT (1U<<15) ++#define CONST_TRUE (1U<<16) ++#define CONST_FALSE (1U<<17) ++ ++#define CONST_LIST (1U<<18) /* Used with TYPE_INTEGER and TYPE_BIT_STRING */ ++#define CONST_MIN_MAX (1U<<19) ++ ++#define CONST_1_PARAM (1U<<20) ++ ++#define CONST_SIZE (1U<<21) ++ ++#define CONST_DEFINED_BY (1U<<22) ++ ++/* Those two are deprecated and used for backwards compatibility */ ++#define CONST_GENERALIZED (1U<<23) ++#define CONST_UTC (1U<<24) ++ ++/* #define CONST_IMPORTS (1U<<25) */ ++ ++#define CONST_NOT_USED (1U<<26) ++#define CONST_SET (1U<<27) ++#define CONST_ASSIGN (1U<<28) ++ ++#define CONST_DOWN (1U<<29) ++#define CONST_RIGHT (1U<<30) ++ ++ ++#define ASN1_ETYPE_TIME 17 ++/****************************************/ ++/* Returns the first 8 bits. */ ++/* Used with the field type of asn1_node_st */ ++/****************************************/ ++inline static unsigned int ++type_field (unsigned int ntype) ++{ ++ return (ntype & 0xff); ++} ++ ++/* To convert old types from a static structure */ ++inline static unsigned int ++convert_old_type (unsigned int ntype) ++{ ++ unsigned int type = ntype & 0xff; ++ if (type == ASN1_ETYPE_TIME) ++ { ++ if (ntype & CONST_UTC) ++ type = ASN1_ETYPE_UTC_TIME; ++ else ++ type = ASN1_ETYPE_GENERALIZED_TIME; ++ ++ ntype &= ~(CONST_UTC | CONST_GENERALIZED); ++ ntype &= 0xffffff00; ++ ntype |= type; ++ ++ return ntype; ++ } ++ else ++ return ntype; ++} ++ ++static inline ++void *_asn1_realloc(void *ptr, size_t size) ++{ ++ void *ret; ++ ++ if (size == 0) ++ return ptr; ++ ++ ret = realloc(ptr, size); ++ if (ret == NULL) ++ { ++ free(ptr); ++ } ++ return ret; ++} ++ ++#endif /* INT_H */ +diff --git a/grub-core/lib/libtasn1/lib/parser_aux.h b/grub-core/lib/libtasn1/lib/parser_aux.h +new file mode 100644 +index 0000000000..598e684b35 +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/parser_aux.h +@@ -0,0 +1,172 @@ ++/* ++ * Copyright (C) 2000-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++#ifndef _PARSER_AUX_H ++#define _PARSER_AUX_H ++ ++/***********************************************/ ++/* Type: list_type */ ++/* Description: type used in the list during */ ++/* the structure creation. */ ++/***********************************************/ ++typedef struct list_struct ++{ ++ asn1_node node; ++ struct list_struct *next; ++} list_type; ++ ++/***************************************/ ++/* Functions used by ASN.1 parser */ ++/***************************************/ ++asn1_node _asn1_add_static_node (list_type **e_list, unsigned int type); ++ ++void _asn1_delete_list (list_type *e_list); ++ ++void _asn1_delete_list_and_nodes (list_type *e_list); ++ ++void _asn1_delete_node_from_list (list_type *list, asn1_node node); ++ ++asn1_node ++_asn1_set_value (asn1_node node, const void *value, unsigned int len); ++ ++asn1_node _asn1_set_value_m (asn1_node node, void *value, unsigned int len); ++ ++asn1_node ++_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len); ++ ++asn1_node ++_asn1_append_value (asn1_node node, const void *value, unsigned int len); ++ ++asn1_node _asn1_set_name (asn1_node node, const char *name); ++ ++asn1_node _asn1_cpy_name (asn1_node dst, asn1_node_const src); ++ ++asn1_node _asn1_set_right (asn1_node node, asn1_node right); ++ ++asn1_node _asn1_get_last_right (asn1_node_const node); ++ ++void _asn1_remove_node (asn1_node node, unsigned int flags); ++ ++/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */ ++#define LTOSTR_MAX_SIZE 22 ++char *_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]); ++ ++asn1_node _asn1_find_up (asn1_node_const node); ++ ++int _asn1_change_integer_value (asn1_node node); ++ ++#define EXPAND_OBJECT_ID_MAX_RECURSION 16 ++int _asn1_expand_object_id (list_type **list, asn1_node node); ++ ++int _asn1_type_set_config (asn1_node node); ++ ++int _asn1_check_identifier (asn1_node_const node); ++ ++int _asn1_set_default_tag (asn1_node node); ++ ++/******************************************************************/ ++/* Function : _asn1_get_right */ ++/* Description: returns the element pointed by the RIGHT field of */ ++/* a NODE_ASN element. */ ++/* Parameters: */ ++/* node: NODE_ASN element pointer. */ ++/* Return: field RIGHT of NODE. */ ++/******************************************************************/ ++inline static asn1_node ++_asn1_get_right (asn1_node_const node) ++{ ++ if (node == NULL) ++ return NULL; ++ return node->right; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_set_down */ ++/* Description: sets the field DOWN in a NODE_ASN element. */ ++/* Parameters: */ ++/* node: element pointer. */ ++/* down: pointer to a NODE_ASN element that you want be pointed */ ++/* by NODE. */ ++/* Return: pointer to *NODE. */ ++/******************************************************************/ ++inline static asn1_node ++_asn1_set_down (asn1_node node, asn1_node down) ++{ ++ if (node == NULL) ++ return node; ++ node->down = down; ++ if (down) ++ down->left = node; ++ return node; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_get_down */ ++/* Description: returns the element pointed by the DOWN field of */ ++/* a NODE_ASN element. */ ++/* Parameters: */ ++/* node: NODE_ASN element pointer. */ ++/* Return: field DOWN of NODE. */ ++/******************************************************************/ ++inline static asn1_node ++_asn1_get_down (asn1_node_const node) ++{ ++ if (node == NULL) ++ return NULL; ++ return node->down; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_get_name */ ++/* Description: returns the name of a NODE_ASN element. */ ++/* Parameters: */ ++/* node: NODE_ASN element pointer. */ ++/* Return: a null terminated string. */ ++/******************************************************************/ ++inline static char * ++_asn1_get_name (asn1_node_const node) ++{ ++ if (node == NULL) ++ return NULL; ++ return (char *) node->name; ++} ++ ++/******************************************************************/ ++/* Function : _asn1_mod_type */ ++/* Description: change the field TYPE of an NODE_ASN element. */ ++/* The new value is the old one | (bitwise or) the */ ++/* paramener VALUE. */ ++/* Parameters: */ ++/* node: NODE_ASN element pointer. */ ++/* value: the integer value that must be or-ed with the current */ ++/* value of field TYPE. */ ++/* Return: NODE pointer. */ ++/******************************************************************/ ++inline static asn1_node ++_asn1_mod_type (asn1_node node, unsigned int value) ++{ ++ if (node == NULL) ++ return node; ++ node->type |= value; ++ return node; ++} ++ ++#endif +diff --git a/grub-core/lib/libtasn1/lib/structure.h b/grub-core/lib/libtasn1/lib/structure.h +new file mode 100644 +index 0000000000..99e685da07 +--- /dev/null ++++ b/grub-core/lib/libtasn1/lib/structure.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * The LIBTASN1 library is free software; you can redistribute it ++ * and/or modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ */ ++ ++/*************************************************/ ++/* File: structure.h */ ++/* Description: list of exported object by */ ++/* "structure.c" */ ++/*************************************************/ ++ ++#ifndef _STRUCTURE_H ++#define _STRUCTURE_H ++ ++#include "parser_aux.h" // list_type ++ ++int _asn1_create_static_structure (asn1_node_const pointer, ++ char *output_file_name, char *vector_name); ++ ++asn1_node _asn1_copy_structure3 (asn1_node_const source_node); ++ ++asn1_node _asn1_add_single_node (unsigned int type); ++ ++asn1_node _asn1_find_left (asn1_node_const node); ++ ++int ++_asn1_delete_structure (list_type *e_list, asn1_node *structure, unsigned int flags); ++ ++#endif +diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h +new file mode 100644 +index 0000000000..6fd7a30dc3 +--- /dev/null ++++ b/include/grub/libtasn1.h +@@ -0,0 +1,588 @@ ++/* ++ * Copyright (C) 2002-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * LIBTASN1 is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as ++ * published by the Free Software Foundation; either version 2.1 of ++ * the License, or (at your option) any later version. ++ * ++ * LIBTASN1 is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with LIBTASN1; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * ++ */ ++ ++/** ++ * libtasn1:Short_Description: ++ * ++ * GNU ASN.1 library ++ */ ++/** ++ * libtasn1:Long_Description: ++ * ++ * The Libtasn1 library provides Abstract Syntax Notation One (ASN.1, as ++ * specified by the X.680 ITU-T recommendation) parsing and structures ++ * management, and Distinguished Encoding Rules (DER, as per X.690) ++ * encoding and decoding functions. ++ */ ++ ++ ++#ifndef LIBTASN1_H ++#define LIBTASN1_H ++ ++#ifndef ASN1_API ++#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY ++#define ASN1_API __attribute__((__visibility__("default"))) ++#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC ++#define ASN1_API __declspec(dllexport) ++#elif defined _MSC_VER && ! defined ASN1_STATIC ++#define ASN1_API __declspec(dllimport) ++#else ++#define ASN1_API ++#endif ++#endif ++ ++#ifdef __GNUC__ ++# define __LIBTASN1_CONST__ __attribute__((const)) ++# define __LIBTASN1_PURE__ __attribute__((pure)) ++#else ++# define __LIBTASN1_CONST__ ++# define __LIBTASN1_PURE__ ++#endif ++ ++#include ++#include ++#include /* for FILE* */ ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++/** ++ * ASN1_VERSION: ++ * ++ * Version of the library as a string. ++ */ ++#define ASN1_VERSION "4.16.0" ++ ++/** ++ * ASN1_VERSION_MAJOR: ++ * ++ * Major version number of the library. ++ */ ++#define ASN1_VERSION_MAJOR 4 ++ ++/** ++ * ASN1_VERSION_MINOR: ++ * ++ * Minor version number of the library. ++ */ ++#define ASN1_VERSION_MINOR 16 ++ ++/** ++ * ASN1_VERSION_PATCH: ++ * ++ * Patch version number of the library. ++ */ ++#define ASN1_VERSION_PATCH 0 ++ ++/** ++ * ASN1_VERSION_NUMBER: ++ * ++ * Version number of the library as a number. ++ */ ++#define ASN1_VERSION_NUMBER 0x041000 ++ ++ ++#if defined __GNUC__ && !defined ASN1_INTERNAL_BUILD ++# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) ++# if _ASN1_GCC_VERSION >= 30100 ++# define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__)) ++# endif ++#endif ++ ++#ifndef _ASN1_GCC_ATTR_DEPRECATED ++#define _ASN1_GCC_ATTR_DEPRECATED ++#endif ++ ++/*****************************************/ ++/* Errors returned by libtasn1 functions */ ++/*****************************************/ ++#define ASN1_SUCCESS 0 ++#define ASN1_FILE_NOT_FOUND 1 ++#define ASN1_ELEMENT_NOT_FOUND 2 ++#define ASN1_IDENTIFIER_NOT_FOUND 3 ++#define ASN1_DER_ERROR 4 ++#define ASN1_VALUE_NOT_FOUND 5 ++#define ASN1_GENERIC_ERROR 6 ++#define ASN1_VALUE_NOT_VALID 7 ++#define ASN1_TAG_ERROR 8 ++#define ASN1_TAG_IMPLICIT 9 ++#define ASN1_ERROR_TYPE_ANY 10 ++#define ASN1_SYNTAX_ERROR 11 ++#define ASN1_MEM_ERROR 12 ++#define ASN1_MEM_ALLOC_ERROR 13 ++#define ASN1_DER_OVERFLOW 14 ++#define ASN1_NAME_TOO_LONG 15 ++#define ASN1_ARRAY_ERROR 16 ++#define ASN1_ELEMENT_NOT_EMPTY 17 ++#define ASN1_TIME_ENCODING_ERROR 18 ++#define ASN1_RECURSION 19 ++ ++/*************************************/ ++/* Constants used in asn1_visit_tree */ ++/*************************************/ ++#define ASN1_PRINT_NAME 1 ++#define ASN1_PRINT_NAME_TYPE 2 ++#define ASN1_PRINT_NAME_TYPE_VALUE 3 ++#define ASN1_PRINT_ALL 4 ++ ++/*****************************************/ ++/* Constants returned by asn1_read_tag */ ++/*****************************************/ ++#define ASN1_CLASS_UNIVERSAL 0x00 /* old: 1 */ ++#define ASN1_CLASS_APPLICATION 0x40 /* old: 2 */ ++#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /* old: 3 */ ++#define ASN1_CLASS_PRIVATE 0xC0 /* old: 4 */ ++#define ASN1_CLASS_STRUCTURED 0x20 ++ ++/*****************************************/ ++/* Constants returned by asn1_read_tag */ ++/*****************************************/ ++#define ASN1_TAG_BOOLEAN 0x01 ++#define ASN1_TAG_INTEGER 0x02 ++#define ASN1_TAG_SEQUENCE 0x10 ++#define ASN1_TAG_SET 0x11 ++#define ASN1_TAG_OCTET_STRING 0x04 ++#define ASN1_TAG_BIT_STRING 0x03 ++#define ASN1_TAG_UTCTime 0x17 ++#define ASN1_TAG_GENERALIZEDTime 0x18 ++#define ASN1_TAG_OBJECT_ID 0x06 ++#define ASN1_TAG_ENUMERATED 0x0A ++#define ASN1_TAG_NULL 0x05 ++#define ASN1_TAG_GENERALSTRING 0x1B ++#define ASN1_TAG_NUMERIC_STRING 0x12 ++#define ASN1_TAG_IA5_STRING 0x16 ++#define ASN1_TAG_TELETEX_STRING 0x14 ++#define ASN1_TAG_PRINTABLE_STRING 0x13 ++#define ASN1_TAG_UNIVERSAL_STRING 0x1C ++#define ASN1_TAG_BMP_STRING 0x1E ++#define ASN1_TAG_UTF8_STRING 0x0C ++#define ASN1_TAG_VISIBLE_STRING 0x1A ++ ++/** ++ * asn1_node: ++ * ++ * Structure definition used for the node of the tree ++ * that represents an ASN.1 DEFINITION. ++ */ ++typedef struct asn1_node_st asn1_node_st; ++ ++typedef asn1_node_st *asn1_node; ++typedef const asn1_node_st *asn1_node_const; ++ ++/** ++ * ASN1_MAX_NAME_SIZE: ++ * ++ * Maximum number of characters of a name ++ * inside a file with ASN1 definitions. ++ */ ++#define ASN1_MAX_NAME_SIZE 64 ++ ++ ++/** ++ * asn1_static_node: ++ * @name: Node name ++ * @type: Node typ ++ * @value: Node value ++ * ++ * For the on-disk format of ASN.1 trees, created by asn1_parser2array(). ++ */ ++struct asn1_static_node_st ++{ ++ const char *name; /* Node name */ ++ unsigned int type; /* Node type */ ++ const void *value; /* Node value */ ++}; ++typedef struct asn1_static_node_st asn1_static_node; ++ ++/* List of constants for field type of node_asn */ ++#define ASN1_ETYPE_INVALID 0 ++#define ASN1_ETYPE_CONSTANT 1 ++#define ASN1_ETYPE_IDENTIFIER 2 ++#define ASN1_ETYPE_INTEGER 3 ++#define ASN1_ETYPE_BOOLEAN 4 ++#define ASN1_ETYPE_SEQUENCE 5 ++#define ASN1_ETYPE_BIT_STRING 6 ++#define ASN1_ETYPE_OCTET_STRING 7 ++#define ASN1_ETYPE_TAG 8 ++#define ASN1_ETYPE_DEFAULT 9 ++#define ASN1_ETYPE_SIZE 10 ++#define ASN1_ETYPE_SEQUENCE_OF 11 ++#define ASN1_ETYPE_OBJECT_ID 12 ++#define ASN1_ETYPE_ANY 13 ++#define ASN1_ETYPE_SET 14 ++#define ASN1_ETYPE_SET_OF 15 ++#define ASN1_ETYPE_DEFINITIONS 16 ++#define ASN1_ETYPE_CHOICE 18 ++#define ASN1_ETYPE_IMPORTS 19 ++#define ASN1_ETYPE_NULL 20 ++#define ASN1_ETYPE_ENUMERATED 21 ++#define ASN1_ETYPE_GENERALSTRING 27 ++#define ASN1_ETYPE_NUMERIC_STRING 28 ++#define ASN1_ETYPE_IA5_STRING 29 ++#define ASN1_ETYPE_TELETEX_STRING 30 ++#define ASN1_ETYPE_PRINTABLE_STRING 31 ++#define ASN1_ETYPE_UNIVERSAL_STRING 32 ++#define ASN1_ETYPE_BMP_STRING 33 ++#define ASN1_ETYPE_UTF8_STRING 34 ++#define ASN1_ETYPE_VISIBLE_STRING 35 ++#define ASN1_ETYPE_UTC_TIME 36 ++#define ASN1_ETYPE_GENERALIZED_TIME 37 ++ ++/** ++ * ASN1_DELETE_FLAG_ZEROIZE: ++ * ++ * Used by: asn1_delete_structure2() ++ * ++ * Zeroize values prior to deinitialization. ++ */ ++#define ASN1_DELETE_FLAG_ZEROIZE 1 ++ ++/** ++ * ASN1_DECODE_FLAG_ALLOW_PADDING: ++ * ++ * Used by: asn1_der_decoding2() ++ * ++ * This flag would allow arbitrary data past the DER data. ++ */ ++#define ASN1_DECODE_FLAG_ALLOW_PADDING 1 ++/** ++ * ASN1_DECODE_FLAG_STRICT_DER: ++ * ++ * Used by: asn1_der_decoding2() ++ * ++ * This flag would ensure that no BER decoding takes place. ++ */ ++#define ASN1_DECODE_FLAG_STRICT_DER (1<<1) ++/** ++ * ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME: ++ * ++ * Used by: asn1_der_decoding2() ++ * ++ * This flag will tolerate Time encoding errors when in strict DER. ++ */ ++#define ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME (1<<2) ++ ++ ++/** ++ * asn1_data_node_st: ++ * @name: Node name ++ * @value: Node value ++ * @value_len: Node value size ++ * @type: Node value type (ASN1_ETYPE_*) ++ * ++ * Data node inside a #asn1_node structure. ++ */ ++struct asn1_data_node_st ++{ ++ const char *name; /* Node name */ ++ const void *value; /* Node value */ ++ unsigned int value_len; /* Node value size */ ++ unsigned int type; /* Node value type (ASN1_ETYPE_*) */ ++}; ++typedef struct asn1_data_node_st asn1_data_node_st; ++ ++/***********************************/ ++/* Fixed constants */ ++/***********************************/ ++ ++/** ++ * ASN1_MAX_ERROR_DESCRIPTION_SIZE: ++ * ++ * Maximum number of characters ++ * of a description message ++ * (null character included). ++ */ ++#define ASN1_MAX_ERROR_DESCRIPTION_SIZE 128 ++ ++/***********************************/ ++/* Functions definitions */ ++/***********************************/ ++ ++extern ASN1_API int ++ asn1_parser2tree (const char *file, ++ asn1_node * definitions, char *error_desc); ++ ++extern ASN1_API int ++ asn1_parser2array (const char *inputFileName, ++ const char *outputFileName, ++ const char *vectorName, char *error_desc); ++ ++extern ASN1_API int ++ asn1_array2tree (const asn1_static_node * array, ++ asn1_node * definitions, char *errorDescription); ++ ++extern ASN1_API void ++ asn1_print_structure (FILE * out, asn1_node_const structure, ++ const char *name, int mode); ++ ++extern ASN1_API int ++ asn1_create_element (asn1_node_const definitions, ++ const char *source_name, asn1_node * element); ++ ++extern ASN1_API int asn1_delete_structure (asn1_node * structure); ++ ++extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int flags); ++ ++extern ASN1_API int ++ asn1_delete_element (asn1_node structure, const char *element_name); ++ ++extern ASN1_API int ++ asn1_write_value (asn1_node node_root, const char *name, ++ const void *ivalue, int len); ++ ++extern ASN1_API int ++ asn1_read_value (asn1_node_const root, const char *name, ++ void *ivalue, int *len); ++ ++extern ASN1_API int ++ asn1_read_value_type (asn1_node_const root, const char *name, ++ void *ivalue, int *len, unsigned int *etype); ++ ++extern ASN1_API int ++ asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data); ++ ++extern ASN1_API int ++ asn1_number_of_elements (asn1_node_const element, const char *name, int *num); ++ ++extern ASN1_API int ++ asn1_der_coding (asn1_node_const element, const char *name, ++ void *ider, int *len, char *ErrorDescription); ++ ++extern ASN1_API int ++ asn1_der_decoding2 (asn1_node *element, const void *ider, ++ int *max_ider_len, unsigned int flags, ++ char *errorDescription); ++ ++extern ASN1_API int ++ asn1_der_decoding (asn1_node * element, const void *ider, ++ int ider_len, char *errorDescription); ++ ++/* Do not use. Use asn1_der_decoding() instead. */ ++extern ASN1_API int ++ asn1_der_decoding_element (asn1_node * structure, ++ const char *elementName, ++ const void *ider, int len, ++ char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED; ++ ++extern ASN1_API int ++ asn1_der_decoding_startEnd (asn1_node element, ++ const void *ider, int ider_len, ++ const char *name_element, ++ int *start, int *end); ++ ++extern ASN1_API int ++ asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element); ++ ++extern ASN1_API int ++ asn1_expand_octet_string (asn1_node_const definitions, ++ asn1_node * element, ++ const char *octetName, const char *objectName); ++ ++extern ASN1_API int ++ asn1_read_tag (asn1_node_const root, const char *name, ++ int *tagValue, int *classValue); ++ ++extern ASN1_API const char *asn1_find_structure_from_oid (asn1_node_const ++ definitions, ++ const char ++ *oidValue); ++ ++__LIBTASN1_PURE__ ++extern ASN1_API const char *asn1_check_version (const char *req_version); ++ ++__LIBTASN1_PURE__ ++extern ASN1_API const char *asn1_strerror (int error); ++ ++extern ASN1_API void asn1_perror (int error); ++ ++#define ASN1_MAX_TAG_SIZE 4 ++#define ASN1_MAX_LENGTH_SIZE 9 ++#define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE) ++extern ASN1_API long ++ asn1_get_length_der (const unsigned char *der, int der_len, int *len); ++ ++extern ASN1_API long ++ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len); ++ ++extern ASN1_API void ++ asn1_length_der (unsigned long int len, unsigned char *der, int *der_len); ++ ++/* Other utility functions. */ ++ ++extern ASN1_API ++ int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, ++ const unsigned char **str, ++ unsigned int *str_len); ++ ++extern ASN1_API ++ int asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, ++ unsigned int _der_len, ++ unsigned char **str, ++ unsigned int *str_len, ++ unsigned int *ber_len); ++ ++extern ASN1_API int ++ asn1_encode_simple_der (unsigned int etype, const unsigned char *str, ++ unsigned int str_len, unsigned char *tl, ++ unsigned int *tl_len); ++ ++extern ASN1_API asn1_node ++ asn1_find_node (asn1_node_const pointer, const char *name); ++ ++extern ASN1_API int ++ asn1_copy_node (asn1_node dst, const char *dst_name, ++ asn1_node_const src, const char *src_name); ++extern ASN1_API asn1_node ++ asn1_dup_node (asn1_node_const src, const char *src_name); ++ ++/* Internal and low-level DER utility functions. */ ++ ++extern ASN1_API int ++ asn1_get_tag_der (const unsigned char *der, int der_len, ++ unsigned char *cls, int *len, unsigned long *tag); ++ ++extern ASN1_API void ++ asn1_octet_der (const unsigned char *str, int str_len, ++ unsigned char *der, int *der_len); ++ ++extern ASN1_API int ++ asn1_get_octet_der (const unsigned char *der, int der_len, ++ int *ret_len, unsigned char *str, ++ int str_size, int *str_len); ++ ++extern ASN1_API void asn1_bit_der (const unsigned char *str, int bit_len, ++ unsigned char *der, int *der_len); ++ ++extern ASN1_API int ++ asn1_get_bit_der (const unsigned char *der, int der_len, ++ int *ret_len, unsigned char *str, ++ int str_size, int *bit_len); ++ ++extern ASN1_API int ++ asn1_get_object_id_der (const unsigned char *der, ++ int der_len, int *ret_len, ++ char *str, int str_size); ++ ++extern ASN1_API int ++ asn1_object_id_der (const char *str, unsigned char *der, int *der_len, ++ unsigned flags); ++ ++/* Compatibility types */ ++ ++/** ++ * asn1_retCode: ++ * ++ * Type formerly returned by libtasn1 functions. ++ * ++ * Deprecated: 3.0: Use int instead. ++ */ ++typedef int asn1_retCode; ++ ++/** ++ * node_asn_struct: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_node instead. ++ */ ++#define node_asn_struct asn1_node_st ++ ++/** ++ * node_asn: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_node instead. ++ */ ++#define node_asn asn1_node_st ++ ++/** ++ * ASN1_TYPE: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_node instead. ++ */ ++#define ASN1_TYPE asn1_node ++ ++/** ++ * ASN1_TYPE_EMPTY: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use NULL instead. ++ */ ++#define ASN1_TYPE_EMPTY NULL ++ ++/** ++ * static_struct_asn: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_static_node instead. ++ */ ++#define static_struct_asn asn1_static_node_st ++ ++/** ++ * ASN1_ARRAY_TYPE: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_static_node instead. ++ */ ++#define ASN1_ARRAY_TYPE asn1_static_node ++ ++/** ++ * asn1_static_node_t: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_static_node instead. ++ */ ++#define asn1_static_node_t asn1_static_node ++ ++/** ++ * node_data_struct: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_data_node_st instead. ++ */ ++#define node_data_struct asn1_data_node_st ++ ++/** ++ * ASN1_DATA_NODE: ++ * ++ * Compat #define. ++ * ++ * Deprecated: 3.0: Use #asn1_data_node_st instead. ++ */ ++#define ASN1_DATA_NODE asn1_data_node_st ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LIBTASN1_H */ +diff --git a/grub-core/lib/libtasn1/LICENSE b/grub-core/lib/libtasn1/LICENSE +new file mode 100644 +index 0000000000..e8b3628db9 +--- /dev/null ++++ b/grub-core/lib/libtasn1/LICENSE +@@ -0,0 +1,16 @@ ++LICENSING ++========= ++ ++The libtasn1 library is released under the GNU Lesser General Public ++License (LGPL) version 2.1 or later; see [COPYING.LESSER](doc/COPYING.LESSER) ++for the license terms. ++ ++The GNU LGPL applies to the main libtasn1 library, while the ++included applications library are under the GNU GPL version 3. ++The libtasn1 library is located in the lib directory, while the applications ++in src/. ++ ++The documentation in doc/ is under the GNU FDL license 1.3. ++ ++For any copyright year range specified as YYYY-ZZZZ in this package ++note that the range specifies every single year in that closed interval. +diff --git a/grub-core/lib/libtasn1/README.md b/grub-core/lib/libtasn1/README.md +new file mode 100644 +index 0000000000..50a8642296 +--- /dev/null ++++ b/grub-core/lib/libtasn1/README.md +@@ -0,0 +1,91 @@ ++|Branch|CI system|Status| ++|:----:|:-------:|-----:| ++|Master|Gitlab|[![build status](https://gitlab.com/gnutls/libtasn1/badges/master/pipeline.svg)](https://gitlab.com/gnutls/libtasn1/commits/master)[![coverage report](https://gitlab.com/gnutls/libtasn1/badges/master/coverage.svg)](https://gnutls.gitlab.io/libtasn1/coverage)| ++ ++# libtasn1 ++ ++This is GNU Libtasn1, a small ASN.1 library. ++ ++The C library (libtasn1.*) is licensed under the GNU Lesser General ++Public License version 2.1 or later. See the file COPYING.LIB. ++ ++The command line tool, self tests, examples, and other auxilliary ++files, are licensed under the GNU General Public License version 3.0 ++or later. See the file COPYING. ++ ++## Building the library ++ ++We require several tools to build the software, including: ++ ++* [Make](https://www.gnu.org/software/make/) ++* [Automake](https://www.gnu.org/software/automake/) (use 1.11.3 or later) ++* [Autoconf](https://www.gnu.org/software/autoconf/) ++* [Libtool](https://www.gnu.org/software/libtool/) ++* [Texinfo](https://www.gnu.org/software/texinfo/) ++* [help2man](http://www.gnu.org/software/help2man/) ++* [Tar](https://www.gnu.org/software/tar/) ++* [Gzip](https://www.gnu.org/software/gzip/) ++* [bison](https://www.gnu.org/software/bison/) ++* [Texlive & epsf](https://www.tug.org/texlive/) (for PDF manual) ++* [GTK-DOC](https://www.gtk.org/gtk-doc/) (for API manual) ++* [Git](https://git-scm.com/) ++* [libabigail](https://pagure.io/libabigail/) (for abi comparison in make dist) ++* [Valgrind](https://valgrind.org/) (optional) ++ ++The required software is typically distributed with your operating ++system, and the instructions for installing them differ. Here are ++some hints: ++ ++gNewSense/Debian/Ubuntu: ++``` ++sudo apt-get install make git-core autoconf automake libtool ++sudo apt-get install texinfo texlive texlive-generic-recommended texlive-extra-utils ++sudo apt-get install help2man gtk-doc-tools valgrind abigail-tools ++``` ++ ++The next step is to run autoreconf, ./configure, etc: ++ ++``` ++$ ./bootstrap ++``` ++ ++Then build the project normally: ++ ++``` ++$ make ++$ make check ++``` ++ ++Happy hacking! ++ ++ ++## Manual ++ ++The manual is in the `doc/` directory of the release. You can also browse ++the manual online at: ++ ++ - https://gnutls.gitlab.io/libtasn1/ ++ ++ ++## Code coverage report ++ ++The coverage report is at: ++ ++ - https://gnutls.gitlab.io/libtasn1/coverage ++ ++ ++## Issue trackers ++ ++ - [Main issue tracker](https://gitlab.com/gnutls/libtasn1/issues) ++ - [oss-fuzz found issues](https://bugs.chromium.org/p/oss-fuzz/issues/list?q=libtasn1&can=2) ++ ++ ++## Homepage ++ ++The project homepage at the gnu site is at: ++ ++http://www.gnu.org/software/libtasn1/ ++ ++ ++For any copyright year range specified as YYYY-ZZZZ in this package ++note that the range specifies every single year in that closed interval. diff --git a/SOURCES/0163-Fix-const-char-pointers-in-grub-core-net-efi-ip6_con.patch b/SOURCES/0163-Fix-const-char-pointers-in-grub-core-net-efi-ip6_con.patch deleted file mode 100644 index 7c29683..0000000 --- a/SOURCES/0163-Fix-const-char-pointers-in-grub-core-net-efi-ip6_con.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 20 Jul 2020 12:24:02 -0400 -Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/ip6_config.c - -This will need to get folded back in the right place on the next rebase, -but it's before "Make grub_strtol() "end" pointers have safer const -qualifiers" currently, so for now I'm leaving it here instead of merging -it back with the original patch. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/ip6_config.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c -index a46f6f9b685..1c5415d7185 100644 ---- a/grub-core/net/efi/ip6_config.c -+++ b/grub-core/net/efi/ip6_config.c -@@ -85,7 +85,7 @@ grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *addres - ptr++; - continue; - } -- t = grub_strtoul (ptr, (char **) &ptr, 16); -+ t = grub_strtoul (ptr, &ptr, 16); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; diff --git a/SOURCES/0163-libtasn1-disable-code-not-needed-in-grub.patch b/SOURCES/0163-libtasn1-disable-code-not-needed-in-grub.patch new file mode 100644 index 0000000..84dcbf0 --- /dev/null +++ b/SOURCES/0163-libtasn1-disable-code-not-needed-in-grub.patch @@ -0,0 +1,307 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 1 May 2020 17:12:23 +1000 +Subject: [PATCH] libtasn1: disable code not needed in grub + +We don't expect to be able to write ASN.1, only read it, +so we can disable some code. + +Do that with #if 0/#endif, rather than deletion. This means +that the difference between upstream and grub is smaller, +which should make updating libtasn1 easier in the future. + +With these exclusions we also avoid the need for minmax.h, +which is convenient because it means we don't have to +import it from gnulib. + +Signed-off-by: Daniel Axtens +--- + grub-core/lib/libtasn1/lib/coding.c | 12 ++++++++++-- + grub-core/lib/libtasn1/lib/decoding.c | 2 ++ + grub-core/lib/libtasn1/lib/element.c | 4 ++-- + grub-core/lib/libtasn1/lib/errors.c | 3 +++ + grub-core/lib/libtasn1/lib/structure.c | 10 ++++++---- + include/grub/libtasn1.h | 15 +++++++++++++++ + 6 files changed, 38 insertions(+), 8 deletions(-) + +diff --git a/grub-core/lib/libtasn1/lib/coding.c b/grub-core/lib/libtasn1/lib/coding.c +index 245ea64cf0..52def59836 100644 +--- a/grub-core/lib/libtasn1/lib/coding.c ++++ b/grub-core/lib/libtasn1/lib/coding.c +@@ -30,11 +30,11 @@ + #include "parser_aux.h" + #include + #include "element.h" +-#include "minmax.h" + #include + + #define MAX_TAG_LEN 16 + ++#if 0 + /******************************************************/ + /* Function : _asn1_error_description_value_not_found */ + /* Description: creates the ErrorDescription string */ +@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node, + Estrcat (ErrorDescription, "' not found"); + + } ++#endif + + /** + * asn1_length_der: +@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const unsigned char *str, + return ASN1_SUCCESS; + } + ++#if 0 + /******************************************************/ + /* Function : _asn1_time_der */ + /* Description: creates the DER coding for a TIME */ +@@ -281,7 +283,7 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned char *der, + + return ASN1_SUCCESS; + } +- ++#endif + + /* + void +@@ -520,6 +522,7 @@ asn1_bit_der (const unsigned char *str, int bit_len, + } + + ++#if 0 + /******************************************************/ + /* Function : _asn1_complete_explicit_tag */ + /* Description: add the length coding to the EXPLICIT */ +@@ -596,6 +599,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der, + + return ASN1_SUCCESS; + } ++#endif + + const tag_and_class_st _asn1_tags[] = { + [ASN1_ETYPE_GENERALSTRING] = +@@ -648,6 +652,8 @@ const tag_and_class_st _asn1_tags[] = { + + unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]); + ++ ++#if 0 + /******************************************************/ + /* Function : _asn1_insert_tag_der */ + /* Description: creates the DER coding of tags of one */ +@@ -1413,3 +1419,5 @@ error: + asn1_delete_structure (&node); + return err; + } ++ ++#endif +\ No newline at end of file +diff --git a/grub-core/lib/libtasn1/lib/decoding.c b/grub-core/lib/libtasn1/lib/decoding.c +index ff04eb778c..42f9a92b5d 100644 +--- a/grub-core/lib/libtasn1/lib/decoding.c ++++ b/grub-core/lib/libtasn1/lib/decoding.c +@@ -1613,6 +1613,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len, + return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription); + } + ++#if 0 + /** + * asn1_der_decoding_element: + * @structure: pointer to an ASN1 structure +@@ -1643,6 +1644,7 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName, + { + return asn1_der_decoding(structure, ider, len, errorDescription); + } ++#endif + + /** + * asn1_der_decoding_startEnd: +diff --git a/grub-core/lib/libtasn1/lib/element.c b/grub-core/lib/libtasn1/lib/element.c +index 997eb2725d..539008d8e9 100644 +--- a/grub-core/lib/libtasn1/lib/element.c ++++ b/grub-core/lib/libtasn1/lib/element.c +@@ -191,7 +191,7 @@ _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) + return ASN1_SUCCESS; + } + +- ++#if 0 + /** + * asn1_write_value: + * @node_root: pointer to a structure +@@ -645,7 +645,7 @@ asn1_write_value (asn1_node node_root, const char *name, + + return ASN1_SUCCESS; + } +- ++#endif + + #define PUT_VALUE( ptr, ptr_size, data, data_size) \ + *len = data_size; \ +diff --git a/grub-core/lib/libtasn1/lib/errors.c b/grub-core/lib/libtasn1/lib/errors.c +index cee74daf79..42785e8622 100644 +--- a/grub-core/lib/libtasn1/lib/errors.c ++++ b/grub-core/lib/libtasn1/lib/errors.c +@@ -57,6 +57,8 @@ static const libtasn1_error_entry error_algorithms[] = { + {0, 0} + }; + ++ ++#if 0 + /** + * asn1_perror: + * @error: is an error returned by a libtasn1 function. +@@ -73,6 +75,7 @@ asn1_perror (int error) + const char *str = asn1_strerror (error); + fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)"); + } ++#endif + + /** + * asn1_strerror: +diff --git a/grub-core/lib/libtasn1/lib/structure.c b/grub-core/lib/libtasn1/lib/structure.c +index 8189c56a4c..fcfde01a39 100644 +--- a/grub-core/lib/libtasn1/lib/structure.c ++++ b/grub-core/lib/libtasn1/lib/structure.c +@@ -76,7 +76,7 @@ _asn1_find_left (asn1_node_const node) + return node->left; + } + +- ++#if 0 + int + _asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, + char *vector_name) +@@ -155,7 +155,7 @@ _asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, + + return ASN1_SUCCESS; + } +- ++#endif + + /** + * asn1_array2tree: +@@ -718,7 +718,7 @@ asn1_create_element (asn1_node_const definitions, const char *source_name, + return res; + } + +- ++#if 0 + /** + * asn1_print_structure: + * @out: pointer to the output file (e.g. stdout). +@@ -1058,7 +1058,7 @@ asn1_print_structure (FILE * out, asn1_node_const structure, const char *name, + } + } + } +- ++#endif + + + /** +@@ -1153,6 +1153,7 @@ asn1_find_structure_from_oid (asn1_node_const definitions, const char *oidValue) + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ + } + ++#if 0 + /** + * asn1_copy_node: + * @dst: Destination asn1 node. +@@ -1202,6 +1203,7 @@ asn1_copy_node (asn1_node dst, const char *dst_name, + + return result; + } ++#endif + + /** + * asn1_dup_node: +diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h +index 6fd7a30dc3..785eda2ae3 100644 +--- a/include/grub/libtasn1.h ++++ b/include/grub/libtasn1.h +@@ -319,6 +319,8 @@ typedef struct asn1_data_node_st asn1_data_node_st; + /* Functions definitions */ + /***********************************/ + ++/* These functions are not used in grub and should not be referenced. */ ++#if 0 + extern ASN1_API int + asn1_parser2tree (const char *file, + asn1_node * definitions, char *error_desc); +@@ -327,14 +329,17 @@ extern ASN1_API int + asn1_parser2array (const char *inputFileName, + const char *outputFileName, + const char *vectorName, char *error_desc); ++#endif + + extern ASN1_API int + asn1_array2tree (const asn1_static_node * array, + asn1_node * definitions, char *errorDescription); + ++#if 0 + extern ASN1_API void + asn1_print_structure (FILE * out, asn1_node_const structure, + const char *name, int mode); ++#endif + + extern ASN1_API int + asn1_create_element (asn1_node_const definitions, +@@ -347,9 +352,11 @@ extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int + extern ASN1_API int + asn1_delete_element (asn1_node structure, const char *element_name); + ++#if 0 + extern ASN1_API int + asn1_write_value (asn1_node node_root, const char *name, + const void *ivalue, int len); ++#endif + + extern ASN1_API int + asn1_read_value (asn1_node_const root, const char *name, +@@ -365,9 +372,11 @@ extern ASN1_API int + extern ASN1_API int + asn1_number_of_elements (asn1_node_const element, const char *name, int *num); + ++#if 0 + extern ASN1_API int + asn1_der_coding (asn1_node_const element, const char *name, + void *ider, int *len, char *ErrorDescription); ++#endif + + extern ASN1_API int + asn1_der_decoding2 (asn1_node *element, const void *ider, +@@ -378,12 +387,14 @@ extern ASN1_API int + asn1_der_decoding (asn1_node * element, const void *ider, + int ider_len, char *errorDescription); + ++#if 0 + /* Do not use. Use asn1_der_decoding() instead. */ + extern ASN1_API int + asn1_der_decoding_element (asn1_node * structure, + const char *elementName, + const void *ider, int len, + char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED; ++#endif + + extern ASN1_API int + asn1_der_decoding_startEnd (asn1_node element, +@@ -408,13 +419,17 @@ extern ASN1_API const char *asn1_find_structure_from_oid (asn1_node_const + const char + *oidValue); + ++#if 0 + __LIBTASN1_PURE__ + extern ASN1_API const char *asn1_check_version (const char *req_version); ++#endif + + __LIBTASN1_PURE__ + extern ASN1_API const char *asn1_strerror (int error); + ++#if 0 + extern ASN1_API void asn1_perror (int error); ++#endif + + #define ASN1_MAX_TAG_SIZE 4 + #define ASN1_MAX_LENGTH_SIZE 9 diff --git a/SOURCES/0164-Fix-const-char-pointers-in-grub-core-net-efi-net.c.patch b/SOURCES/0164-Fix-const-char-pointers-in-grub-core-net-efi-net.c.patch deleted file mode 100644 index 0fe90c8..0000000 --- a/SOURCES/0164-Fix-const-char-pointers-in-grub-core-net-efi-net.c.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 20 Jul 2020 12:24:02 -0400 -Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/net.c - -This will need to get folded back in the right place on the next rebase, -but it's before "Make grub_strtol() "end" pointers have safer const -qualifiers" currently, so for now I'm leaving it here instead of merging -it back with the original patch. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/net.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c -index a3f0535d43c..78e5442fc52 100644 ---- a/grub-core/net/efi/net.c -+++ b/grub-core/net/efi/net.c -@@ -729,7 +729,7 @@ grub_efi_net_parse_address (const char *address, - { - grub_uint32_t subnet_mask_size; - -- subnet_mask_size = grub_strtoul (rest + 1, (char **) &rest, 0); -+ subnet_mask_size = grub_strtoul (rest + 1, &rest, 0); - - if (!grub_errno && subnet_mask_size <= 32 && *rest == 0) - { -@@ -758,7 +758,7 @@ grub_efi_net_parse_address (const char *address, - { - grub_efi_uint8_t prefix_length; - -- prefix_length = grub_strtoul (rest + 1, (char **) &rest, 0); -+ prefix_length = grub_strtoul (rest + 1, &rest, 0); - if (!grub_errno && prefix_length <= 128 && *rest == 0) - { - ip6->prefix_length = prefix_length; diff --git a/SOURCES/0164-libtasn1-changes-for-grub-compatibility.patch b/SOURCES/0164-libtasn1-changes-for-grub-compatibility.patch new file mode 100644 index 0000000..7c756bd --- /dev/null +++ b/SOURCES/0164-libtasn1-changes-for-grub-compatibility.patch @@ -0,0 +1,202 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 1 May 2020 20:44:29 +1000 +Subject: [PATCH] libtasn1: changes for grub compatibility + +Do a few things to make libtasn1 compile as part of grub: + + - replace strcat. grub removed strcat so replace it with the appropriate + calls to memcpy and strlen. + + - replace c_isdigit with grub_isdigit (and don't import c-ctype from + gnulib) grub_isdigit provides the same functionality as c_isdigit: it + determines if the input is an ASCII digit without regard for locale. + + - replace GL_ATTRIBUTE_PURE with __attribute__((pure)) which been + supported since gcc-2.96. This avoids messing around with gnulib. + + - adjust libtasn1.h: drop the ASN1_API logic, it's not needed for our + modules. Unconditionally support const and pure attributes and adjust + header paths. + + - adjust header paths to "grub/libtasn1.h". + + - replace a 64 bit division with a call to grub_divmod64, preventing + creation of __udivdi3 calls on 32 bit platforms. + +Signed-off-by: Daniel Axtens +--- + grub-core/lib/libtasn1/lib/decoding.c | 11 ++++++----- + grub-core/lib/libtasn1/lib/element.c | 3 ++- + grub-core/lib/libtasn1/lib/gstr.c | 4 ++-- + grub-core/lib/libtasn1/lib/parser_aux.c | 7 ++++--- + grub-core/lib/libtasn1/lib/int.h | 4 ++-- + include/grub/libtasn1.h | 26 ++++++-------------------- + 6 files changed, 22 insertions(+), 33 deletions(-) + +diff --git a/grub-core/lib/libtasn1/lib/decoding.c b/grub-core/lib/libtasn1/lib/decoding.c +index 42f9a92b5d..7856858b27 100644 +--- a/grub-core/lib/libtasn1/lib/decoding.c ++++ b/grub-core/lib/libtasn1/lib/decoding.c +@@ -32,7 +32,8 @@ + #include + #include + #include +-#include ++ ++#define c_isdigit grub_isdigit + + #ifdef DEBUG + # define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) +@@ -2008,8 +2009,8 @@ asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, + (p2->type & CONST_ASSIGN)) + { + strcpy (name, definitions->name); +- strcat (name, "."); +- strcat (name, p2->name); ++ memcpy (name + strlen(name), ".", sizeof(" . ")); ++ memcpy (name + strlen(name), p2->name, strlen(p2->name) + 1); + + len = sizeof (value); + result = asn1_read_value (definitions, name, value, &len); +@@ -2026,8 +2027,8 @@ asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, + if (p2) + { + strcpy (name, definitions->name); +- strcat (name, "."); +- strcat (name, p2->name); ++ memcpy (name + strlen(name), ".", sizeof(" . ")); ++ memcpy (name + strlen(name), p2->name, strlen(p2->name) + 1); + + result = asn1_create_element (definitions, name, &aux); + if (result == ASN1_SUCCESS) +diff --git a/grub-core/lib/libtasn1/lib/element.c b/grub-core/lib/libtasn1/lib/element.c +index 539008d8e9..ed761ff56b 100644 +--- a/grub-core/lib/libtasn1/lib/element.c ++++ b/grub-core/lib/libtasn1/lib/element.c +@@ -30,9 +30,10 @@ + #include "parser_aux.h" + #include + #include "structure.h" +-#include "c-ctype.h" + #include "element.h" + ++#define c_isdigit grub_isdigit ++ + void + _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size) + { +diff --git a/grub-core/lib/libtasn1/lib/gstr.c b/grub-core/lib/libtasn1/lib/gstr.c +index e91a3a151c..e33875c2c7 100644 +--- a/grub-core/lib/libtasn1/lib/gstr.c ++++ b/grub-core/lib/libtasn1/lib/gstr.c +@@ -36,13 +36,13 @@ _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src) + + if (dest_tot_size - dest_size > str_size) + { +- strcat (dest, src); ++ memcpy (dest + dest_size, src, str_size + 1); + } + else + { + if (dest_tot_size - dest_size > 0) + { +- strncat (dest, src, (dest_tot_size - dest_size) - 1); ++ memcpy (dest + dest_size, src, (dest_tot_size - dest_size) - 1); + dest[dest_tot_size - 1] = 0; + } + } +diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c b/grub-core/lib/libtasn1/lib/parser_aux.c +index d5dbbf8765..89c9be69dc 100644 +--- a/grub-core/lib/libtasn1/lib/parser_aux.c ++++ b/grub-core/lib/libtasn1/lib/parser_aux.c +@@ -26,7 +26,8 @@ + #include "gstr.h" + #include "structure.h" + #include "element.h" +-#include "c-ctype.h" ++ ++#define c_isdigit grub_isdigit + + char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not found */ + +@@ -40,7 +41,7 @@ char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not fou + #ifdef __clang__ + __attribute__((no_sanitize("integer"))) + #endif +-_GL_ATTRIBUTE_PURE ++__attribute__((__pure__)) + static unsigned int + _asn1_hash_name (const char *x) + { +@@ -634,7 +635,7 @@ _asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]) + count = 0; + do + { +- d = val / 10; ++ d = grub_divmod64(val, 10, NULL); + r = val - d * 10; + temp[start + count] = '0' + (char) r; + count++; +diff --git a/grub-core/lib/libtasn1/lib/int.h b/grub-core/lib/libtasn1/lib/int.h +index ea1625786c..4a568efee9 100644 +--- a/grub-core/lib/libtasn1/lib/int.h ++++ b/grub-core/lib/libtasn1/lib/int.h +@@ -35,7 +35,7 @@ + #include + #endif + +-#include ++#include "grub/libtasn1.h" + + #define ASN1_SMALL_VALUE_SIZE 16 + +@@ -115,7 +115,7 @@ extern const tag_and_class_st _asn1_tags[]; + #define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b) + #define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b) + #define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b) +-#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b) ++#define _asn1_strcat(a,b) memcpy((char *)a + strlen((const char *)a), (const char *)b, strlen((const char *)b) + 1) + + #if SIZEOF_UNSIGNED_LONG_INT == 8 + # define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b) +diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h +index 785eda2ae3..28dbf16c4e 100644 +--- a/include/grub/libtasn1.h ++++ b/include/grub/libtasn1.h +@@ -38,29 +38,15 @@ + #ifndef LIBTASN1_H + #define LIBTASN1_H + +-#ifndef ASN1_API +-#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY +-#define ASN1_API __attribute__((__visibility__("default"))) +-#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC +-#define ASN1_API __declspec(dllexport) +-#elif defined _MSC_VER && ! defined ASN1_STATIC +-#define ASN1_API __declspec(dllimport) +-#else ++/* grub: ASN1_API is not used */ + #define ASN1_API +-#endif +-#endif + +-#ifdef __GNUC__ +-# define __LIBTASN1_CONST__ __attribute__((const)) +-# define __LIBTASN1_PURE__ __attribute__((pure)) +-#else +-# define __LIBTASN1_CONST__ +-# define __LIBTASN1_PURE__ +-#endif ++/* grub: all our supported compilers support these attributes */ ++#define __LIBTASN1_CONST__ __attribute__((const)) ++#define __LIBTASN1_PURE__ __attribute__((pure)) + +-#include +-#include +-#include /* for FILE* */ ++#include ++#include + + #ifdef __cplusplus + extern "C" diff --git a/SOURCES/0165-Fix-const-char-pointers-in-grub-core-net-efi-pxe.c.patch b/SOURCES/0165-Fix-const-char-pointers-in-grub-core-net-efi-pxe.c.patch deleted file mode 100644 index 59f29e4..0000000 --- a/SOURCES/0165-Fix-const-char-pointers-in-grub-core-net-efi-pxe.c.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 20 Jul 2020 12:24:02 -0400 -Subject: [PATCH] Fix const char ** pointers in grub-core/net/efi/pxe.c - -This will need to get folded back in the right place on the next rebase, -but it's before "Make grub_strtol() "end" pointers have safer const -qualifiers" currently, so for now I'm leaving it here instead of merging -it back with the original patch. - -Signed-off-by: Peter Jones ---- - grub-core/net/efi/pxe.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/grub-core/net/efi/pxe.c b/grub-core/net/efi/pxe.c -index 531949cba5c..73e2bb01c1b 100644 ---- a/grub-core/net/efi/pxe.c -+++ b/grub-core/net/efi/pxe.c -@@ -187,7 +187,7 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) - ptr++; - continue; - } -- t = grub_strtoul (ptr, (char **) &ptr, 16); -+ t = grub_strtoul (ptr, &ptr, 16); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; -@@ -225,7 +225,7 @@ pxe_open (struct grub_efi_net_device *dev, - int type __attribute__((unused))) - { - int i; -- char *p; -+ const char *p; - grub_efi_status_t status; - grub_efi_pxe_ip_address_t server_ip; - grub_efi_uint64_t file_size = 0; -@@ -313,7 +313,7 @@ pxe_read (struct grub_efi_net_device *dev, - grub_size_t len) - { - int i; -- char *p; -+ const char *p; - grub_efi_status_t status; - grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; - grub_efi_uint64_t bufsz = len; diff --git a/SOURCES/0165-libtasn1-compile-into-asn1-module.patch b/SOURCES/0165-libtasn1-compile-into-asn1-module.patch new file mode 100644 index 0000000..0fb433f --- /dev/null +++ b/SOURCES/0165-libtasn1-compile-into-asn1-module.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 5 Jun 2020 17:47:25 +1000 +Subject: [PATCH] libtasn1: compile into asn1 module + +Create a wrapper file that specifies the module license. +Set up the makefile so it is built. + +Signed-off-by: Daniel Axtens +--- + grub-core/Makefile.core.def | 15 +++++++++++++++ + grub-core/lib/libtasn1_wrap/wrap.c | 26 ++++++++++++++++++++++++++ + 2 files changed, 41 insertions(+) + create mode 100644 grub-core/lib/libtasn1_wrap/wrap.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 64cc758835..ea92468fa2 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2577,3 +2577,18 @@ module = { + common = commands/i386/wrmsr.c; + enable = x86; + }; ++ ++module = { ++ name = asn1; ++ common = lib/libtasn1/lib/decoding.c; ++ common = lib/libtasn1/lib/coding.c; ++ common = lib/libtasn1/lib/element.c; ++ common = lib/libtasn1/lib/structure.c; ++ common = lib/libtasn1/lib/parser_aux.c; ++ common = lib/libtasn1/lib/gstr.c; ++ common = lib/libtasn1/lib/errors.c; ++ common = lib/libtasn1_wrap/wrap.c; ++ cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; ++ // -Wno-type-limits comes from libtasn1's configure.ac ++ cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/libtasn1/lib -Wno-type-limits'; ++}; +diff --git a/grub-core/lib/libtasn1_wrap/wrap.c b/grub-core/lib/libtasn1_wrap/wrap.c +new file mode 100644 +index 0000000000..622ba942e3 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/wrap.c +@@ -0,0 +1,26 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++ ++/* ++ * libtasn1 is provided under LGPL2.1+, which is compatible ++ * with GPL3+. As Grub as a whole is under GPL3+, this module ++ * is therefore under GPL3+ also. ++ */ ++GRUB_MOD_LICENSE ("GPLv3+"); diff --git a/SOURCES/0166-Add-systemd-integration-scripts-to-make-systemctl-re.patch b/SOURCES/0166-Add-systemd-integration-scripts-to-make-systemctl-re.patch deleted file mode 100644 index 130dc77..0000000 --- a/SOURCES/0166-Add-systemd-integration-scripts-to-make-systemctl-re.patch +++ /dev/null @@ -1,190 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Wed, 22 Jul 2020 14:03:42 +0200 -Subject: [PATCH] Add systemd integration scripts to make "systemctl reboot - --boot-loader-menu=xxx" work with grub - -This commit adds a number of scripts / config files to make -"systemctl reboot --boot-loader-menu=xxx" work with grub: - -1. /lib/systemd/system/systemd-logind.service.d/10-grub.conf -This sets SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU in the env. for logind, -indicating that the boot-loader which is used supports this feature, see: -https://github.com/systemd/systemd/blob/master/docs/ENVIRONMENT.md - -2. /lib/systemd/system/grub-systemd-integration.service - /lib/systemd/system/reboot.target.wants/grub-systemd-integration.service -> - ../grub-systemd-integration.service - /usr/libexec/grub/grub-systemd-integration.sh - -The symlink in the .wants dir causes the added service file to be started -by systemd just before rebooting the system. -If /run/systemd/reboot-to-boot-loader-menu exist then the service will run -the grub-systemd-integration.sh script. -This script sets the new menu_show_once_timeout grubenv variable to the -requested timeout in seconds. - -3. /etc/grub.d/14_menu_show_once - -This new grub-mkconfig snippet adds the necessary code to the generated -grub.conf to honor the new menu_show_once_timeout variable, and to -automatically clear it after consuming it. - -Note the service and libexec script use grub-systemd-integration as name -because in the future they may be used to add further integration with -systemctl reboot --foo options, e.g. support for --boot-loader-entry=NAME. - -A few notes about upstreaming this patch from the rhboot grub2 fork: -1. I have deliberately put the grub.conf bits for this in a new / separate - grub-mkconfig snippet generator for easy upstreaming -2. Even though the commit message mentions the .wants symlink for the .service - I have been unable to come up with a clean way to do this at "make install" - time, this should be fixed before upstreaming. - -Downstream notes: -1. Since make install does not add the .wants symlink, this needs to be done - in grub2.spec %install -2. This is keeping support for the "old" Fedora specific menu_show_once env - variable, which has a hardcoded timeout of 60 sec in 12_menu_auto_hide in - place for now. This can be dropped (eventually) in a follow-up patch once - GNOME has been converted to use the systemd dbus API equivalent of - "systemctl reboot --boot-loader-menu=xxx". - -Signed-off-by: Hans de Goede ---- - Makefile.util.def | 27 ++++++++++++++++++++++++ - conf/Makefile.common | 6 ++++++ - util/grub.d/14_menu_show_once.in | 13 ++++++++++++ - util/systemd/10-grub-logind-service.conf.in | 2 ++ - util/systemd/grub-systemd-integration.service.in | 8 +++++++ - util/systemd/systemd-integration.sh.in | 6 ++++++ - 6 files changed, 62 insertions(+) - create mode 100755 util/grub.d/14_menu_show_once.in - create mode 100644 util/systemd/10-grub-logind-service.conf.in - create mode 100644 util/systemd/grub-systemd-integration.service.in - create mode 100644 util/systemd/systemd-integration.sh.in - -diff --git a/Makefile.util.def b/Makefile.util.def -index 11ab2d6fad1..e1242f54022 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -470,6 +470,12 @@ script = { - installdir = grubconf; - }; - -+script = { -+ name = '14_menu_show_once'; -+ common = util/grub.d/14_menu_show_once.in; -+ installdir = grubconf; -+}; -+ - script = { - name = '01_users'; - common = util/grub.d/01_users.in; -@@ -569,6 +575,27 @@ script = { - installdir = grubconf; - }; - -+script = { -+ name = 'grub-systemd-integration.service'; -+ common = util/systemd/grub-systemd-integration.service.in; -+ installdir = systemdunit; -+ condition = COND_HOST_LINUX; -+}; -+ -+script = { -+ name = 'systemd-integration.sh'; -+ common = util/systemd/systemd-integration.sh.in; -+ installdir = grublibexec; -+ condition = COND_HOST_LINUX; -+}; -+ -+script = { -+ name = '10-grub-logind-service.conf'; -+ common = util/systemd/10-grub-logind-service.conf.in; -+ installdir = systemd_logind_service_d; -+ condition = COND_HOST_LINUX; -+}; -+ - program = { - mansection = 1; - name = grub-mkrescue; -diff --git a/conf/Makefile.common b/conf/Makefile.common -index 0647c53b916..9fe5863b2d9 100644 ---- a/conf/Makefile.common -+++ b/conf/Makefile.common -@@ -63,8 +63,11 @@ CCASFLAGS_LIBRARY = $(UTILS_CCASFLAGS) - # Other variables - - grubconfdir = $(sysconfdir)/grub.d -+grublibexecdir = $(libexecdir)/$(grubdirname) - platformdir = $(pkglibdir)/$(target_cpu)-$(platform) - starfielddir = $(pkgdatadir)/themes/starfield -+systemdunitdir = ${prefix}/lib/systemd/system -+systemd_logind_service_ddir = $(systemdunitdir)/systemd-logind.service.d - - CFLAGS_GNULIB = -Wno-undef -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Werror=trampolines -fno-trampolines - CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib -@@ -121,6 +124,9 @@ noinst_LIBRARIES = - dist_noinst_DATA = - platform_SCRIPTS = - platform_PROGRAMS = -+grublibexec_SCRIPTS = -+systemdunit_SCRIPTS = -+systemd_logind_service_d_SCRIPTS = - - TESTS = - EXTRA_DIST = -diff --git a/util/grub.d/14_menu_show_once.in b/util/grub.d/14_menu_show_once.in -new file mode 100755 -index 00000000000..1cd7f36142b ---- /dev/null -+++ b/util/grub.d/14_menu_show_once.in -@@ -0,0 +1,13 @@ -+#! /bin/sh -+# Force the menu to be shown once, with a timeout of ${menu_show_once_timeout} -+# if requested by ${menu_show_once_timeout} being set in the env. -+cat << EOF -+if [ x\$feature_timeout_style = xy ]; then -+ if [ "\${menu_show_once_timeout}" ]; then -+ set timeout_style=menu -+ set timeout="\${menu_show_once_timeout}" -+ unset menu_show_once_timeout -+ save_env menu_show_once_timeout -+ fi -+fi -+EOF -diff --git a/util/systemd/10-grub-logind-service.conf.in b/util/systemd/10-grub-logind-service.conf.in -new file mode 100644 -index 00000000000..f2d4ac00732 ---- /dev/null -+++ b/util/systemd/10-grub-logind-service.conf.in -@@ -0,0 +1,2 @@ -+[Service] -+Environment=SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU=true -diff --git a/util/systemd/grub-systemd-integration.service.in b/util/systemd/grub-systemd-integration.service.in -new file mode 100644 -index 00000000000..c81fb594ce1 ---- /dev/null -+++ b/util/systemd/grub-systemd-integration.service.in -@@ -0,0 +1,8 @@ -+[Unit] -+Description=Grub2 systemctl reboot --boot-loader-menu=... support -+Before=umount.target systemd-reboot.service -+DefaultDependencies=no -+ConditionPathExists=/run/systemd/reboot-to-boot-loader-menu -+ -+[Service] -+ExecStart=@libexecdir@/@grubdirname@/systemd-integration.sh -diff --git a/util/systemd/systemd-integration.sh.in b/util/systemd/systemd-integration.sh.in -new file mode 100644 -index 00000000000..dc1218597bc ---- /dev/null -+++ b/util/systemd/systemd-integration.sh.in -@@ -0,0 +1,6 @@ -+#!/bin/sh -+ -+TIMEOUT_USEC=$(cat /run/systemd/reboot-to-boot-loader-menu) -+TIMEOUT=$(((TIMEOUT_USEC + 500000) / 1000000)) -+ -+@grub_editenv@ - set menu_show_once_timeout=$TIMEOUT diff --git a/SOURCES/0166-test_asn1-test-module-for-libtasn1.patch b/SOURCES/0166-test_asn1-test-module-for-libtasn1.patch new file mode 100644 index 0000000..6cc13bd --- /dev/null +++ b/SOURCES/0166-test_asn1-test-module-for-libtasn1.patch @@ -0,0 +1,1457 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Wed, 10 Jun 2020 17:48:42 +1000 +Subject: [PATCH] test_asn1: test module for libtasn1 + +Import tests from libtasn1 that don't use functionality we don't +import. I have put them here rather than in the libtasn1 directory +because: + + - They need much more significant changes to run in the grub + context. + + - I don't expect they will need to be changed when updating + libtasn1: I expect the old tests will usually continue to pass on + new versions. + +This doesn't test the full decoder but that will be exercised in +test suites for coming patch sets. + +Signed-off-by: Daniel Axtens +--- + Makefile.util.def | 6 + + grub-core/Makefile.core.def | 13 ++ + .../lib/libtasn1_wrap/tests/CVE-2018-1000654.c | 61 ++++++ + grub-core/lib/libtasn1_wrap/tests/Test_overflow.c | 138 ++++++++++++++ + grub-core/lib/libtasn1_wrap/tests/Test_simple.c | 207 ++++++++++++++++++++ + grub-core/lib/libtasn1_wrap/tests/Test_strings.c | 150 +++++++++++++++ + .../lib/libtasn1_wrap/tests/object-id-decoding.c | 116 +++++++++++ + .../lib/libtasn1_wrap/tests/object-id-encoding.c | 120 ++++++++++++ + grub-core/lib/libtasn1_wrap/tests/octet-string.c | 211 +++++++++++++++++++++ + grub-core/lib/libtasn1_wrap/tests/reproducers.c | 81 ++++++++ + grub-core/lib/libtasn1_wrap/wrap_tests.c | 75 ++++++++ + .../tests/CVE-2018-1000654-1_asn1_tab.h | 32 ++++ + .../tests/CVE-2018-1000654-2_asn1_tab.h | 36 ++++ + grub-core/lib/libtasn1_wrap/wrap_tests.h | 38 ++++ + .gitignore | 1 + + tests/test_asn1.in | 12 ++ + 16 files changed, 1297 insertions(+) + create mode 100644 grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/Test_overflow.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/Test_simple.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/Test_strings.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/octet-string.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/reproducers.c + create mode 100644 grub-core/lib/libtasn1_wrap/wrap_tests.c + create mode 100644 grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h + create mode 100644 grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h + create mode 100644 grub-core/lib/libtasn1_wrap/wrap_tests.h + create mode 100644 tests/test_asn1.in + +diff --git a/Makefile.util.def b/Makefile.util.def +index 6366442129..d04b3fe68a 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -1289,6 +1289,12 @@ script = { + common = tests/syslinux_test.in; + }; + ++script = { ++ testcase; ++ name = test_asn1; ++ common = tests/test_asn1.in; ++}; ++ + program = { + testcase; + name = example_unit_test; +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index ea92468fa2..a32e6ada59 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2592,3 +2592,16 @@ module = { + // -Wno-type-limits comes from libtasn1's configure.ac + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/libtasn1/lib -Wno-type-limits'; + }; ++ ++module = { ++ name = test_asn1; ++ common = lib/libtasn1_wrap/tests/CVE-2018-1000654.c; ++ common = lib/libtasn1_wrap/tests/object-id-decoding.c; ++ common = lib/libtasn1_wrap/tests/object-id-encoding.c; ++ common = lib/libtasn1_wrap/tests/octet-string.c; ++ common = lib/libtasn1_wrap/tests/reproducers.c; ++ common = lib/libtasn1_wrap/tests/Test_overflow.c; ++ common = lib/libtasn1_wrap/tests/Test_simple.c; ++ common = lib/libtasn1_wrap/tests/Test_strings.c; ++ common = lib/libtasn1_wrap/wrap_tests.c; ++}; +diff --git a/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c +new file mode 100644 +index 0000000000..534e304521 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2002-2018 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++ ++/****************************************************************/ ++/* Description: reproducer for CVE-2018-1000654 */ ++/****************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++#include "CVE-2018-1000654-1_asn1_tab.h" ++#include "CVE-2018-1000654-2_asn1_tab.h" ++ ++void ++test_CVE_2018_1000654 (void) ++{ ++ int result; ++ asn1_node definitions = NULL; ++ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; ++ ++ result = asn1_array2tree (CVE_2018_1000654_1_asn1_tab, &definitions, errorDescription); ++ if (result != ASN1_RECURSION) ++ { ++ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", ++ asn1_strerror (result), errorDescription); ++ return; ++ } ++ ++ asn1_delete_structure (&definitions); ++ ++ result = asn1_array2tree (CVE_2018_1000654_2_asn1_tab, &definitions, errorDescription); ++ if (result != ASN1_RECURSION) ++ { ++ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", ++ asn1_strerror (result), errorDescription); ++ return; ++ } ++ ++ asn1_delete_structure (&definitions); ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/Test_overflow.c b/grub-core/lib/libtasn1_wrap/tests/Test_overflow.c +new file mode 100644 +index 0000000000..f48aea0ef8 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/Test_overflow.c +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2012-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++ ++/* Written by Simon Josefsson */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++void ++test_overflow(void) ++{ ++ /* Test that values larger than long are rejected. This has worked ++ fine with all versions of libtasn1. */ ++ ++ { ++ unsigned char der[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; ++ long l; ++ int len; ++ ++ l = asn1_get_length_der (der, sizeof der, &len); ++ ++ if (l != -2L) ++ { ++ grub_fatal ("ERROR: asn1_get_length_der bignum (l %ld len %d)\n", l, len); ++ return; ++ } ++ } ++ ++ /* Test that values larger than int but smaller than long are ++ rejected. This limitation was introduced with libtasn1 2.12. */ ++#if (GRUB_LONG_MAX > GRUB_INT_MAX) ++ { ++ unsigned long num = ((long) GRUB_UINT_MAX) << 2; ++ unsigned char der[20]; ++ int der_len; ++ long l; ++ int len; ++ ++ asn1_length_der (num, der, &der_len); ++ ++ l = asn1_get_length_der (der, der_len, &len); ++ ++ if (l != -2L) ++ { ++ grub_fatal ("ERROR: asn1_get_length_der intnum (l %ld len %d)\n", l, ++ len); ++ return; ++ } ++ } ++#endif ++ ++ /* Test that values larger than would fit in the input string are ++ rejected. This problem was fixed in libtasn1 2.12. */ ++ { ++ unsigned long num = 64; ++ unsigned char der[20]; ++ int der_len; ++ long l; ++ int len; ++ ++ asn1_length_der (num, der, &der_len); ++ ++ der_len = sizeof (der); ++ l = asn1_get_length_der (der, der_len, &len); ++ ++ if (l != -4L) ++ { ++ grub_fatal ("ERROR: asn1_get_length_der overflow-small (l %ld len %d)\n", ++ l, len); ++ return; ++ } ++ } ++ ++ /* Test that values larger than would fit in the input string are ++ rejected. This problem was fixed in libtasn1 2.12. */ ++ { ++ unsigned long num = 1073741824; ++ unsigned char der[20]; ++ int der_len; ++ long l; ++ int len; ++ ++ asn1_length_der (num, der, &der_len); ++ ++ der_len = sizeof (der); ++ l = asn1_get_length_der (der, der_len, &len); ++ ++ if (l != -4L) ++ { ++ grub_fatal ("ERROR: asn1_get_length_der overflow-large1 (l %ld len %d)\n", ++ l, len); ++ return; ++ } ++ } ++ ++ /* Test that values larger than would fit in the input string are ++ rejected. This problem was fixed in libtasn1 2.12. */ ++ { ++ unsigned long num = 2147483649; ++ unsigned char der[20]; ++ int der_len; ++ long l; ++ int len; ++ ++ asn1_length_der (num, der, &der_len); ++ ++ der_len = sizeof (der); ++ l = asn1_get_length_der (der, der_len, &len); ++ ++ if (l != -2L) ++ { ++ grub_fatal ("ERROR: asn1_get_length_der overflow-large2 (l %ld len %d)\n", ++ l, len); ++ return; ++ } ++ } ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/Test_simple.c b/grub-core/lib/libtasn1_wrap/tests/Test_simple.c +new file mode 100644 +index 0000000000..9f01006ddf +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/Test_simple.c +@@ -0,0 +1,207 @@ ++/* ++ * Copyright (C) 2011-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Written by Simon Josefsson ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++struct tv ++{ ++ int bitlen; ++ const char *bitstr; ++ int derlen; ++ const char *der; ++}; ++ ++static const struct tv tv[] = { ++ {0, "", 2, "\x01\x00"}, ++ {1, "\x00", 3, "\x02\x07\x00"}, ++ {2, "\x00", 3, "\x02\x06\x00"}, ++ {3, "\x00", 3, "\x02\x05\x00"}, ++ {4, "\x00", 3, "\x02\x04\x00"}, ++ {5, "\x00", 3, "\x02\x03\x00"}, ++ {6, "\x00", 3, "\x02\x02\x00"}, ++ {7, "\x00", 3, "\x02\x01\x00"}, ++ {8, "\x00\x00", 3, "\x02\x00\x00"}, ++ {9, "\x00\x00", 4, "\x03\x07\x00\x00"}, ++ {10, "\x00\x00", 4, "\x03\x06\x00\x00"}, ++ {11, "\x00\x00", 4, "\x03\x05\x00\x00"}, ++ {12, "\x00\x00", 4, "\x03\x04\x00\x00"}, ++ {13, "\x00\x00", 4, "\x03\x03\x00\x00"}, ++ {14, "\x00\x00", 4, "\x03\x02\x00\x00"}, ++ {15, "\x00\x00", 4, "\x03\x01\x00\x00"}, ++ {16, "\x00\x00", 4, "\x03\x00\x00\x00"}, ++ {17, "\x00\x00\x00", 5, "\x04\x07\x00\x00\x00"}, ++ {18, "\x00\x00\x00", 5, "\x04\x06\x00\x00\x00"}, ++ {19, "\x00\x00\x00", 5, "\x04\x05\x00\x00\x00"}, ++ {1, "\xFF", 3, "\x02\x07\x80"}, ++ {2, "\xFF", 3, "\x02\x06\xc0"}, ++ {3, "\xFF", 3, "\x02\x05\xe0"}, ++ {4, "\xFF", 3, "\x02\x04\xf0"}, ++ {5, "\xFF", 3, "\x02\x03\xf8"}, ++ {6, "\xFF", 3, "\x02\x02\xfc"}, ++ {7, "\xFF", 3, "\x02\x01\xfe"}, ++ {8, "\xFF\xFF", 3, "\x02\x00\xff"}, ++ {9, "\xFF\xFF", 4, "\x03\x07\xff\x80"}, ++ {10, "\xFF\xFF", 4, "\x03\x06\xff\xc0"}, ++ {11, "\xFF\xFF", 4, "\x03\x05\xff\xe0"}, ++ {12, "\xFF\xFF", 4, "\x03\x04\xff\xf0"}, ++ {13, "\xFF\xFF", 4, "\x03\x03\xff\xf8"}, ++ {14, "\xFF\xFF", 4, "\x03\x02\xff\xfc"}, ++ {15, "\xFF\xFF", 4, "\x03\x01\xff\xfe"}, ++ {16, "\xFF\xFF", 4, "\x03\x00\xff\xff"}, ++ {17, "\xFF\xFF\xFF", 5, "\x04\x07\xff\xff\x80"}, ++ {18, "\xFF\xFF\xFF", 5, "\x04\x06\xff\xff\xc0"}, ++ {19, "\xFF\xFF\xFF", 5, "\x04\x05\xff\xff\xe0"}, ++}; ++ ++void ++test_simple (void) ++{ ++ int result; ++ unsigned char der[100]; ++ unsigned char str[100]; ++ int der_len = sizeof (der); ++ int str_size = sizeof (str); ++ int ret_len, bit_len; ++ grub_size_t i; ++ ++ /* Dummy test */ ++ ++ asn1_bit_der (NULL, 0, der, &der_len); ++ result = asn1_get_bit_der (der, 0, &ret_len, str, str_size, &bit_len); ++ if (result != ASN1_GENERIC_ERROR) ++ { ++ grub_fatal ("asn1_get_bit_der zero\n"); ++ return; ++ } ++ ++ /* Encode short strings with increasing bit lengths */ ++ ++ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) ++ { ++ /* Encode */ ++ ++ asn1_bit_der ((const unsigned char *) tv[i].bitstr, tv[i].bitlen, ++ der, &der_len); ++ ++#if 0 ++ { ++ size_t j; ++ for (j = 0; j < der_len; j++) ++ printf ("\\x%02x", der[j]); ++ printf ("\n"); ++ } ++#endif ++ ++ if (der_len != tv[i].derlen || grub_memcmp (der, tv[i].der, der_len) != 0) ++ { ++ grub_fatal ("asn1_bit_der iter %lu\n", (unsigned long) i); ++ return; ++ } ++ ++ /* Decode it */ ++ ++ result = asn1_get_bit_der (der, der_len, &ret_len, str, ++ str_size, &bit_len); ++ if (result != ASN1_SUCCESS || ret_len != tv[i].derlen ++ || bit_len != tv[i].bitlen) ++ { ++ grub_fatal ("asn1_get_bit_der iter %lu, err: %d\n", (unsigned long) i, result); ++ return; ++ } ++ } ++ ++ ++ /* Decode sample from "A Layman's Guide to a Subset of ASN.1, BER, ++ and DER" section 5.4 "BIT STRING": "The BER encoding of the BIT ++ STRING value "011011100101110111" can be any of the following, ++ among others, depending on the choice of padding bits, the form ++ of length octets [...]". ++ */ ++ ++ /* 03 04 06 6e 5d c0 DER encoding */ ++ ++ grub_memcpy (der, "\x04\x06\x6e\x5d\xc0", 5); ++ der_len = 5; ++ ++ result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len); ++ if (result != ASN1_SUCCESS || ret_len != 5 ++ || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xc0", 3) != 0) ++ { ++ grub_fatal ("asn1_get_bit_der example\n"); ++ return; ++ } ++ ++ der_len = sizeof (der); ++ asn1_bit_der (str, bit_len, der, &der_len); ++ if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0) ++ { ++ grub_fatal ("asn1_bit_der example roundtrip\n"); ++ return; ++ } ++ ++ /* 03 04 06 6e 5d e0 padded with "100000" */ ++ ++ grub_memcpy (der, "\x04\x06\x6e\x5d\xe0", 5); ++ der_len = 5; ++ ++ result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len); ++ if (result != ASN1_SUCCESS || ret_len != 5 ++ || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xe0", 3) != 0) ++ { ++ grub_fatal ("asn1_get_bit_der example padded\n"); ++ return; ++ } ++ ++ der_len = sizeof (der); ++ asn1_bit_der (str, bit_len, der, &der_len); ++ if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0) ++ { ++ grub_fatal ("asn1_bit_der example roundtrip\n"); ++ return; ++ } ++ ++ /* 03 81 04 06 6e 5d c0 long form of length octets */ ++ ++ grub_memcpy (der, "\x81\x04\x06\x6e\x5d\xc0", 6); ++ der_len = 6; ++ ++ result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len); ++ ++ if (result != ASN1_SUCCESS || ret_len != 6 ++ || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xc0", 3) != 0) ++ { ++ grub_fatal ("asn1_get_bit_der example long form\n"); ++ return; ++ } ++ ++ der_len = sizeof (der); ++ asn1_bit_der (str, bit_len, der, &der_len); ++ if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0) ++ { ++ grub_fatal ("asn1_bit_der example roundtrip\n"); ++ return; ++ } ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/Test_strings.c b/grub-core/lib/libtasn1_wrap/tests/Test_strings.c +new file mode 100644 +index 0000000000..dbe1474b20 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/Test_strings.c +@@ -0,0 +1,150 @@ ++/* ++ * Copyright (C) 2012-2014 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Written by Simon Josefsson ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++struct tv ++{ ++ unsigned int etype; ++ unsigned int str_len; ++ const void *str; ++ unsigned int der_len; ++ const void *der; ++}; ++ ++static const struct tv tv[] = { ++ {ASN1_ETYPE_IA5_STRING, 20, ++ "\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72", ++ 22, ++ "\x16\x14\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72"}, ++ {ASN1_ETYPE_PRINTABLE_STRING, 5, "\x4e\x69\x6b\x6f\x73", ++ 7, "\x13\x05\x4e\x69\x6b\x6f\x73"}, ++ {ASN1_ETYPE_UTF8_STRING, 12, "Αττική", ++ 14, "\x0c\x0c\xce\x91\xcf\x84\xcf\x84\xce\xb9\xce\xba\xce\xae"}, ++ {ASN1_ETYPE_TELETEX_STRING, 15, ++ "\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e", ++ 17, ++ "\x14\x0f\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e"}, ++ {ASN1_ETYPE_OCTET_STRING, 36, ++ "\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A", ++ 38, ++ "\x04\x24\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A"} ++}; ++ ++#define SSTR(x) sizeof(x)-1,x ++static const struct tv ber[] = { ++ {ASN1_ETYPE_OCTET_STRING, ++ SSTR("\xa0\xa0"), ++ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x00\x00")}, ++ {ASN1_ETYPE_OCTET_STRING, ++ SSTR("\xa0\xa0\xb0\xb0\xb0"), ++ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x00\x00")}, ++ {ASN1_ETYPE_OCTET_STRING, ++ SSTR("\xa0\xa0\xb0\xb0\xb0\xa1\xa1"), ++ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x24\x80\x04\x82\x00\x02\xa1\xa1\x00\x00\x00\x00")}, ++ {ASN1_ETYPE_OCTET_STRING, ++ SSTR("\xa0\xa0\xb0\xb0\xb0\xa1\xa1\xc1"), ++ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x24\x80\x04\x82\x00\x02\xa1\xa1\x04\x82\x00\x01\xc1\x00\x00\x00\x00")}, ++}; ++ ++void ++test_strings () ++{ ++ int ret; ++ unsigned char tl[ASN1_MAX_TL_SIZE]; ++ unsigned int tl_len, der_len, str_len; ++ const unsigned char *str; ++ unsigned char *b; ++ unsigned int i; ++ ++ /* Dummy test */ ++ ++ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) ++ { ++ /* Encode */ ++ tl_len = sizeof (tl); ++ ret = asn1_encode_simple_der (tv[i].etype, tv[i].str, tv[i].str_len, ++ tl, &tl_len); ++ if (ret != ASN1_SUCCESS) ++ { ++ grub_fatal ("Encoding error in %u: %s\n", i, ++ asn1_strerror (ret)); ++ return; ++ } ++ der_len = tl_len + tv[i].str_len; ++ ++ if (der_len != tv[i].der_len || grub_memcmp (tl, tv[i].der, tl_len) != 0) ++ { ++ grub_fatal ( ++ "DER encoding differs in %u! (size: %u, expected: %u)\n", ++ i, der_len, tv[i].der_len); ++ return; ++ } ++ ++ /* decoding */ ++ ret = ++ asn1_decode_simple_der (tv[i].etype, tv[i].der, tv[i].der_len, &str, ++ &str_len); ++ if (ret != ASN1_SUCCESS) ++ { ++ grub_fatal ("Decoding error in %u: %s\n", i, ++ asn1_strerror (ret)); ++ return; ++ } ++ ++ if (str_len != tv[i].str_len || grub_memcmp (str, tv[i].str, str_len) != 0) ++ { ++ grub_fatal ( ++ "DER decoded data differ in %u! (size: %u, expected: %u)\n", ++ i, der_len, tv[i].str_len); ++ return; ++ } ++ } ++ ++ /* BER decoding */ ++ for (i = 0; i < sizeof (ber) / sizeof (ber[0]); i++) ++ { ++ /* decoding */ ++ ret = ++ asn1_decode_simple_ber (ber[i].etype, ber[i].der, ber[i].der_len, &b, ++ &str_len, NULL); ++ if (ret != ASN1_SUCCESS) ++ { ++ grub_fatal ("BER decoding error in %u: %s\n", i, ++ asn1_strerror (ret)); ++ return; ++ } ++ ++ if (str_len != ber[i].str_len || grub_memcmp (b, ber[i].str, str_len) != 0) ++ { ++ grub_fatal ( ++ "BER decoded data differ in %u! (size: %u, expected: %u)\n", ++ i, str_len, ber[i].str_len); ++ return; ++ } ++ grub_free(b); ++ } ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c b/grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c +new file mode 100644 +index 0000000000..d367bbfb5a +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c +@@ -0,0 +1,116 @@ ++/* ++ * Copyright (C) 2016 Red Hat, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++struct tv ++{ ++ int der_len; ++ const unsigned char *der; ++ const char *oid; ++ int expected_error; ++}; ++ ++static const struct tv tv[] = { ++ {.der_len = 5, ++ .der = (void *) "\x06\x03\x80\x37\x03", ++ .oid = "2.999.3", ++ .expected_error = ASN1_DER_ERROR /* leading 0x80 */ ++ }, ++ {.der_len = 12, ++ .der = (void *) "\x06\x0a\x2b\x06\x01\x80\x01\x92\x08\x09\x05\x01", ++ .oid = "1.3.6.1.4.1.2312.9.5.1", ++ .expected_error = ASN1_DER_ERROR /* leading 0x80 */ ++ }, ++ {.der_len = 6, ++ .der = (void *) "\x06\x04\x01\x02\x03\x04", ++ .oid = "0.1.2.3.4", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 5, ++ .der = (void *) "\x06\x03\x51\x02\x03", ++ .oid = "2.1.2.3", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 5, ++ .der = (void *) "\x06\x03\x88\x37\x03", ++ .oid = "2.999.3", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 12, ++ .der = (void *) "\x06\x0a\x2b\x06\x01\x04\x01\x92\x08\x09\x05\x01", ++ .oid = "1.3.6.1.4.1.2312.9.5.1", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 19, ++ .der = (void *) "\x06\x11\xfa\x80\x00\x00\x00\x0e\x01\x0e\xfa\x80\x00\x00\x00\x0e\x63\x6f\x6d", ++ .oid = "2.1998768.0.0.14.1.14.1998848.0.0.14.99.111.109", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 19, ++ .der = ++ (void *) ++ "\x06\x11\x2b\x06\x01\x04\x01\x92\x08\x09\x02\xaa\xda\xbe\xbe\xfa\x72\x01\x07", ++ .oid = "1.3.6.1.4.1.2312.9.2.1467399257458.1.7", ++ .expected_error = ASN1_SUCCESS}, ++}; ++ ++void ++test_object_id_decoding (void) ++{ ++ char str[128]; ++ int ret, ret_len; ++ grub_size_t i; ++ ++ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) ++ { ++ /* decode */ ++ ret = ++ asn1_get_object_id_der (tv[i].der+1, ++ tv[i].der_len-1, &ret_len, str, ++ sizeof (str)); ++ if (ret != tv[i].expected_error) ++ { ++ grub_fatal ( ++ "%d: asn1_get_object_id_der iter %lu: got '%s' expected %d\n", ++ __LINE__, (unsigned long) i, asn1_strerror(ret), tv[i].expected_error); ++ return; ++ } ++ ++ if (tv[i].expected_error != ASN1_SUCCESS) ++ continue; ++ ++ if (ret_len != tv[i].der_len-1) ++ { ++ grub_fatal ( ++ "%d: iter %lu: error in DER, length returned is %d, had %d\n", ++ __LINE__, (unsigned long)i, ret_len, tv[i].der_len-1); ++ return; ++ } ++ ++ if (grub_strcmp (tv[i].oid, str) != 0) ++ { ++ grub_fatal ( ++ "%d: strcmp iter %lu: got invalid OID: %s, expected: %s\n", ++ __LINE__, (unsigned long) i, str, tv[i].oid); ++ return; ++ } ++ ++ } ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c b/grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c +new file mode 100644 +index 0000000000..3a83b58c59 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (C) 2019 Nikos Mavrogiannopoulos ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++struct tv ++{ ++ int der_len; ++ const unsigned char *der; ++ const char *oid; ++ int expected_error; ++}; ++ ++static const struct tv tv[] = { ++ {.der_len = 0, ++ .der = (void *) "", ++ .oid = "5.999.3", ++ .expected_error = ASN1_VALUE_NOT_VALID /* cannot start with 5 */ ++ }, ++ {.der_len = 0, ++ .der = (void *) "", ++ .oid = "0.48.9", ++ .expected_error = ASN1_VALUE_NOT_VALID /* second field cannot be 48 */ ++ }, ++ {.der_len = 0, ++ .der = (void *) "", ++ .oid = "1.40.9", ++ .expected_error = ASN1_VALUE_NOT_VALID /* second field cannot be 40 */ ++ }, ++ {.der_len = 4, ++ .der = (void *) "\x06\x02\x4f\x63", ++ .oid = "1.39.99", ++ .expected_error = ASN1_SUCCESS, ++ }, ++ {.der_len = 6, ++ .der = (void *) "\x06\x04\x01\x02\x03\x04", ++ .oid = "0.1.2.3.4", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 5, ++ .der = (void *) "\x06\x03\x51\x02\x03", ++ .oid = "2.1.2.3", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 5, ++ .der = (void *) "\x06\x03\x88\x37\x03", ++ .oid = "2.999.3", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 12, ++ .der = (void *) "\x06\x0a\x2b\x06\x01\x04\x01\x92\x08\x09\x05\x01", ++ .oid = "1.3.6.1.4.1.2312.9.5.1", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 19, ++ .der = (void *) "\x06\x11\xfa\x80\x00\x00\x00\x0e\x01\x0e\xfa\x80\x00\x00\x00\x0e\x63\x6f\x6d", ++ .oid = "2.1998768.0.0.14.1.14.1998848.0.0.14.99.111.109", ++ .expected_error = ASN1_SUCCESS}, ++ {.der_len = 19, ++ .der = ++ (void *) ++ "\x06\x11\x2b\x06\x01\x04\x01\x92\x08\x09\x02\xaa\xda\xbe\xbe\xfa\x72\x01\x07", ++ .oid = "1.3.6.1.4.1.2312.9.2.1467399257458.1.7", ++ .expected_error = ASN1_SUCCESS}, ++}; ++ ++void ++test_object_id_encoding(void) ++{ ++ unsigned char der[128]; ++ int ret, der_len, i; ++ ++ for (i = 0; i < (int)(sizeof (tv) / sizeof (tv[0])); i++) ++ { ++ der_len = sizeof(der); ++ ret = asn1_object_id_der(tv[i].oid, der, &der_len, 0); ++ if (ret != ASN1_SUCCESS) ++ { ++ if (ret == tv[i].expected_error) ++ continue; ++ grub_fatal ( ++ "%d: iter %lu, encoding of OID failed: %s\n", ++ __LINE__, (unsigned long) i, asn1_strerror(ret)); ++ return; ++ } ++ else if (ret != tv[i].expected_error) ++ { ++ grub_fatal ( ++ "%d: iter %lu, encoding of OID %s succeeded when expecting failure\n", ++ __LINE__, (unsigned long) i, tv[i].oid); ++ return; ++ } ++ ++ if (der_len != tv[i].der_len || grub_memcmp(der, tv[i].der, der_len) != 0) ++ { ++ grub_fatal ( ++ "%d: iter %lu, re-encoding of OID %s resulted to different string (%d vs %d bytes)\n", ++ __LINE__, (unsigned long) i, tv[i].oid, der_len, tv[i].der_len); ++ ++ return; ++ } ++ } ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/octet-string.c b/grub-core/lib/libtasn1_wrap/tests/octet-string.c +new file mode 100644 +index 0000000000..d8a049e8df +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/octet-string.c +@@ -0,0 +1,211 @@ ++/* ++ * Copyright (C) 2011-2020 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Written by Simon Josefsson and Nikos Mavrogiannopoulos ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++ ++struct tv ++{ ++ const char *name; ++ int der_len; ++ const unsigned char *der_str; ++ int len; ++ const unsigned char *string; ++ int expected_error; ++ int ber; ++}; ++ ++static const struct tv tv[] = { ++ {.name = "primitive octet strings", ++ .der_len = 10, ++ .der_str = ++ (void*)"\x04\x08\x01\x23\x45\x67\x89\xab\xcd\xef", ++ .len = 8, ++ .string = ++ (void*)"\x01\x23\x45\x67\x89\xab\xcd\xef", ++ .ber = 0}, ++ {.der_len = 22, ++ .der_str = ++ (void*)"\x04\x14\x13\x00\xd9\xa8\x47\xf7\xf2\x1c\xf4\xb0\xec\x5f\xc1\x73\xe5\x1b\x25\xc2\x62\x27", ++ .len = 20, ++ .string = ++ (void*)"\x13\x00\xD9\xA8\x47\xF7\xF2\x1C\xF4\xB0\xEC\x5F\xC1\x73\xE5\x1B\x25\xC2\x62\x27"}, ++ ++ {.name = "long type of length", ++ .der_len = 23, ++ .der_str = ++ (void*)"\x04\x81\x14\x13\x00\xd9\xa8\x47\xf7\xf2\x1c\xf4\xb0\xec\x5f\xc1\x73\xe5\x1b\x25\xc2\x62\x27", ++ .len = 20, ++ .string = ++ (void*)"\x13\x00\xD9\xA8\x47\xF7\xF2\x1C\xF4\xB0\xEC\x5F\xC1\x73\xE5\x1B\x25\xC2\x62\x27", ++ .ber = 1}, ++ {.der_len = 11, ++ .der_str = ++ (void*)"\x04\x81\x08\x01\x23\x45\x67\x89\xab\xcd\xef", ++ .len = 8, ++ .string = ++ (void*)"\x01\x23\x45\x67\x89\xab\xcd\xef", ++ .ber = 1}, ++ ++ {.name = "constructed - indefinite", ++ .der_len = 11, ++ .der_str = (void*)"\x24\x80\x04\x05\x01\x02\x03\x04\x05\x00\x00", ++ .len = 5, ++ .string = (void*)"\x01\x02\x03\x04\x05", ++ .ber = 1, ++ }, ++ ++ {.name = "constructed - definite - concat", ++ .der_len = 12, ++ .der_str = (void*)"\x24\x0a\x04\x04\x0a\x0b\x0c\x0d\x04\x02\x0e\x0f", ++ .len = 6, ++ .string = (void*)"\x0a\x0b\x0c\x0d\x0e\x0f", ++ .ber = 1, ++ }, ++ {.name = "constructed - definite - recursive", ++ .der_len = 15, ++ .der_str = (void*)"\x24\x0d\x04\x04\x0a\x0b\x0c\x0d\x24\x05\x04\x00\x04\x01\x0f", ++ .len = 5, ++ .string = (void*)"\x0a\x0b\x0c\x0d\x0f", ++ .ber = 1, ++ }, ++ {.name = "constructed - definite - single", ++ .der_len = 7, ++ .der_str = (void*)"\x24\x05\x04\x03\x01\x02\x03", ++ .len = 3, ++ .string = (void*)"\x01\x02\x03", ++ .ber = 1, ++ }, ++ ++ /* a large amount of recursive indefinite encoding */ ++ {.name = "a large amount of recursive indefinite encoding", ++ .der_len = 29325, ++ .der_str = (void*)"\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80", ++ .len = 0, ++ .ber = 1, ++ .expected_error = ASN1_DER_ERROR ++ } ++}; ++ ++void ++test_octet_string (void) ++{ ++ unsigned char str[100]; ++ unsigned char der[100]; ++ int der_len = sizeof (der); ++ int str_size = sizeof (str); ++ unsigned char *tmp = NULL; ++ int ret, ret_len; ++ grub_size_t i; ++ ++ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) ++ { ++ /* Decode */ ++ ++ if (tv[i].ber == 0) ++ { ++ str_size = sizeof (str); ++ ret = ++ asn1_get_octet_der (tv[i].der_str + 1, ++ tv[i].der_len - 1, &ret_len, str, ++ sizeof (str), &str_size); ++ if (ret != tv[i].expected_error) ++ { ++ grub_fatal ( ++ "%d: asn1_get_octet_der: %s: got %d expected %d\n", ++ __LINE__, tv[i].name, ret, ++ tv[i].expected_error); ++ return; ++ } ++ if (tv[i].expected_error) ++ continue; ++ ++ if (ret_len != tv[i].der_len - 1) ++ { ++ grub_fatal ( ++ "%d: error in DER, length returned is %d, had %d\n", ++ __LINE__, ret_len, tv[i].der_len - 1); ++ return; ++ } ++ ++ if (str_size != tv[i].len ++ || grub_memcmp (tv[i].string, str, tv[i].len) != 0) ++ { ++ grub_fatal ( ++ "%d: memcmp: %s: got invalid decoding\n", ++ __LINE__, tv[i].name); ++ ++ return; ++ } ++ ++ /* Encode */ ++ der_len = sizeof (der); ++ asn1_octet_der (str, str_size, der, &der_len); ++ ++ if (der_len != tv[i].der_len - 1 ++ || grub_memcmp (tv[i].der_str + 1, der, tv[i].der_len - 1) != 0) ++ { ++ grub_fatal ( ++ "encoding: %s: got invalid encoding\n", ++ tv[i].name); ++ return; ++ } ++ } ++ ++ ret = ++ asn1_decode_simple_ber (ASN1_ETYPE_OCTET_STRING, ++ tv[i].der_str, tv[i].der_len, ++ &tmp, (unsigned int*)&str_size, (unsigned int*)&der_len); ++ if (ret != tv[i].expected_error) ++ { ++ grub_fatal ( ++ "%d: asn1_decode_simple_ber: %s: got %s expected %s\n", ++ __LINE__, tv[i].name, asn1_strerror(ret), asn1_strerror(tv[i].expected_error)); ++ return; ++ } ++ if (tv[i].expected_error) ++ continue; ++ ++ if (der_len != tv[i].der_len) ++ { ++ grub_fatal ( ++ "%d: error: %s: DER, length returned is %d, had %d\n", ++ __LINE__, tv[i].name, der_len, tv[i].der_len); ++ return; ++ } ++ ++ if (str_size != tv[i].len || grub_memcmp (tv[i].string, tmp, tv[i].len) != 0) ++ { ++ grub_fatal ( ++ "%d: memcmp: %s: got invalid decoding\n", ++ __LINE__, tv[i].name); ++ return; ++ } ++ grub_free (tmp); ++ tmp = NULL; ++ ++ } ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/reproducers.c b/grub-core/lib/libtasn1_wrap/tests/reproducers.c +new file mode 100644 +index 0000000000..dc7268d4c6 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/reproducers.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2019 Free Software Foundation, Inc. ++ * ++ * This file is part of LIBTASN1. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++ ++/****************************************************************/ ++/* Description: run reproducers for several fixed issues */ ++/****************************************************************/ ++ ++#include ++#include ++#include ++#include "../wrap_tests.h" ++ ++#define CONST_DOWN (1U<<29) ++ ++/* produces endless loop (fixed by d4b624b2): ++ * The following translates into a single node with all pointers ++ * (right,left,down) set to NULL. */ ++const asn1_static_node endless_asn1_tab[] = { ++ { "TEST_TREE", 536875024, NULL }, ++ { NULL, 0, NULL } ++}; ++ ++/* produces memory leak (fixed by f16d1ff9): ++ * 152 bytes in 1 blocks are definitely lost in loss record 1 of 1 ++ * at 0x4837B65: calloc (vg_replace_malloc.c:762) ++ * by 0x4851C0D: _asn1_add_static_node (parser_aux.c:71) ++ * by 0x4853AAC: asn1_array2tree (structure.c:200) ++ * by 0x10923B: main (single_node.c:67) ++ */ ++const asn1_static_node tab[] = { ++{ "a", CONST_DOWN, "" }, ++{ "b", 0, "" }, ++{ "c", 0, "" }, ++{ NULL, 0, NULL } ++}; ++ ++void ++test_reproducers (void) ++{ ++ int result; ++ asn1_node definitions = NULL; ++ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; ++ ++ result = asn1_array2tree (endless_asn1_tab, &definitions, errorDescription); ++ if (result != ASN1_SUCCESS) ++ { ++ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", ++ asn1_strerror (result), errorDescription); ++ return; ++ } ++ ++ asn1_delete_structure (&definitions); ++ ++ definitions = NULL; ++ result = asn1_array2tree (tab, &definitions, errorDescription); ++ if (result != ASN1_SUCCESS) ++ { ++ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", ++ asn1_strerror (result), errorDescription); ++ return; ++ } ++ ++ asn1_delete_structure (&definitions); ++} +diff --git a/grub-core/lib/libtasn1_wrap/wrap_tests.c b/grub-core/lib/libtasn1_wrap/wrap_tests.c +new file mode 100644 +index 0000000000..75fcd21f0d +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/wrap_tests.c +@@ -0,0 +1,75 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include "wrap_tests.h" ++ ++/* ++ * libtasn1 tests - from which this is derived - are provided under GPL3+. ++ */ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_command_t cmd; ++ ++static grub_err_t ++grub_cmd_asn1test (grub_command_t cmdd __attribute__((unused)), ++ int argc __attribute__((unused)), ++ char **args __attribute__((unused))) ++{ ++ grub_printf ("test_CVE_2018_1000654\n"); ++ test_CVE_2018_1000654 (); ++ ++ grub_printf ("test_object_id_decoding\n"); ++ test_object_id_decoding (); ++ ++ grub_printf ("test_object_id_encoding\n"); ++ test_object_id_encoding (); ++ ++ grub_printf ("test_octet_string\n"); ++ test_octet_string (); ++ ++ grub_printf ("test_overflow\n"); ++ test_overflow (); ++ ++ grub_printf ("test_reproducers\n"); ++ test_overflow (); ++ ++ grub_printf ("test_simple\n"); ++ test_simple (); ++ ++ grub_printf ("test_strings\n"); ++ test_strings (); ++ ++ grub_printf ("ASN.1 self-tests passed\n"); ++ ++ return GRUB_ERR_NONE; ++} ++ ++ ++GRUB_MOD_INIT(test_asn1) ++{ ++ cmd = grub_register_command ("test_asn1", grub_cmd_asn1test, NULL, ++ "Run self-tests for the ASN.1 parser."); ++} ++ ++GRUB_MOD_FINI(test_asn1) ++{ ++ grub_unregister_command (cmd); ++} +diff --git a/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h +new file mode 100644 +index 0000000000..1e7d3d64f5 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h +@@ -0,0 +1,32 @@ ++#if HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#include ++ ++const asn1_static_node CVE_2018_1000654_1_asn1_tab[] = { ++ { "TEST_TREE", 536875024, NULL }, ++ { NULL, 1610612748, NULL }, ++ { "iso", 1073741825, "1"}, ++ { "identified-organization", 1073741825, "3"}, ++ { "dod", 1073741825, "6"}, ++ { "internet", 1073741825, "1"}, ++ { "security", 1073741825, "5"}, ++ { "mechanisms", 1073741825, "5"}, ++ { "pkix", 1073741825, "7"}, ++ { "id-mod", 1073741825, "0"}, ++ { "id-pkix1-implicit-88", 1, "2"}, ++ { "id-xnyTest", 1879048204, NULL }, ++ { NULL, 1073741825, "id-ix"}, ++ { NULL, 1073741825, "29"}, ++ { NULL, 1, "1"}, ++ { "id-ix", 1880096780, "OBJECR"}, ++ { NULL, 1073741825, "id-ix"}, ++ { NULL, 1073741825, "29"}, ++ { NULL, 1, "2"}, ++ { "id-xnyTest", 805306380, NULL }, ++ { NULL, 1073741825, "id-ix"}, ++ { NULL, 1073741825, "29"}, ++ { NULL, 1, "1"}, ++ { NULL, 0, NULL } ++}; +diff --git a/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h +new file mode 100644 +index 0000000000..e2561e5ec6 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h +@@ -0,0 +1,36 @@ ++#if HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#include ++ ++const asn1_static_node CVE_2018_1000654_2_asn1_tab[] = { ++ { "TEST_TREE", 536875024, NULL }, ++ { NULL, 1610612748, NULL }, ++ { "iso", 1073741825, "1"}, ++ { "identified-organization", 1073741825, "3"}, ++ { "dod", 1073741825, "6"}, ++ { "internet", 1073741825, "1"}, ++ { "security", 1073741825, "5"}, ++ { "mechanisms", 1073741825, "5"}, ++ { "pkix", 1073741825, "7"}, ++ { "id-mod", 1073741825, "0"}, ++ { "id-pkix1-implicit-88", 1, "2"}, ++ { "id-oneTest", 1879048204, NULL }, ++ { NULL, 1073741825, "id-two"}, ++ { NULL, 1073741825, "9"}, ++ { NULL, 1, "1"}, ++ { "id-two", 1879048204, NULL }, ++ { NULL, 1073741825, "id-three"}, ++ { NULL, 1073741825, "2"}, ++ { NULL, 1, "2"}, ++ { "id-three", 1879048204, NULL }, ++ { NULL, 1073741825, "id-four"}, ++ { NULL, 1073741825, "3"}, ++ { NULL, 1, "3"}, ++ { "id-four", 805306380, NULL }, ++ { NULL, 1073741825, "id-two"}, ++ { NULL, 1073741825, "3"}, ++ { NULL, 1, "3"}, ++ { NULL, 0, NULL } ++}; +diff --git a/grub-core/lib/libtasn1_wrap/wrap_tests.h b/grub-core/lib/libtasn1_wrap/wrap_tests.h +new file mode 100644 +index 0000000000..555e56dd20 +--- /dev/null ++++ b/grub-core/lib/libtasn1_wrap/wrap_tests.h +@@ -0,0 +1,38 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef LIBTASN1_WRAP_TESTS_H ++#define LIBTASN1_WRAP_TESTS_H ++ ++void test_CVE_2018_1000654 (void); ++ ++void test_object_id_encoding (void); ++ ++void test_object_id_decoding (void); ++ ++void test_octet_string (void); ++ ++void test_overflow (void); ++ ++void test_reproducers (void); ++ ++void test_simple (void); ++ ++void test_strings (void); ++ ++#endif +diff --git a/.gitignore b/.gitignore +index 208d1d2325..1d005887e7 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -264,6 +264,7 @@ widthspec.bin + /stamp-h1 + /syslinux_test + /tar_test ++/test_asn1 + /test_sha512sum + /test_unset + /tests/syslinux/ubuntu10.04_grub.cfg +diff --git a/tests/test_asn1.in b/tests/test_asn1.in +new file mode 100644 +index 0000000000..8173c5c270 +--- /dev/null ++++ b/tests/test_asn1.in +@@ -0,0 +1,12 @@ ++#! @BUILD_SHEBANG@ ++set -e ++ ++. "@builddir@/grub-core/modinfo.sh" ++ ++out=`echo test_asn1 | @builddir@/grub-shell` ++ ++if [ "$(echo "$out" | tail -n 1)" != "ASN.1 self-tests passed" ]; then ++ echo "ASN.1 test failure: $out" ++ exit 1 ++fi ++ diff --git a/SOURCES/0167-grub-install-support-embedding-x509-certificates.patch b/SOURCES/0167-grub-install-support-embedding-x509-certificates.patch new file mode 100644 index 0000000..c4c35f4 --- /dev/null +++ b/SOURCES/0167-grub-install-support-embedding-x509-certificates.patch @@ -0,0 +1,253 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alastair D'Silva +Date: Mon, 6 Jul 2020 13:33:04 +1000 +Subject: [PATCH] grub-install: support embedding x509 certificates + +To support verification of appended signatures, we need a way to +embed the necessary public keys. Existing appended signature schemes +in the Linux kernel use X.509 certificates, so allow certificates to +be embedded in the grub core image in the same way as PGP keys. + +Signed-off-by: Alastair D'Silva +Signed-off-by: Daniel Axtens +--- + grub-core/commands/pgp.c | 2 +- + util/grub-install-common.c | 23 ++++++++++++++++++++++- + util/grub-mkimage.c | 15 +++++++++++++-- + util/mkimage.c | 38 ++++++++++++++++++++++++++++++++++++-- + include/grub/kernel.h | 4 +++- + include/grub/util/install.h | 7 +++++-- + 6 files changed, 80 insertions(+), 9 deletions(-) + +diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c +index 355a43844a..b81ac0ae46 100644 +--- a/grub-core/commands/pgp.c ++++ b/grub-core/commands/pgp.c +@@ -944,7 +944,7 @@ GRUB_MOD_INIT(pgp) + grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); + + /* Not an ELF module, skip. */ +- if (header->type != OBJ_TYPE_PUBKEY) ++ if (header->type != OBJ_TYPE_GPG_PUBKEY) + continue; + + pseudo_file.fs = &pseudo_fs; +diff --git a/util/grub-install-common.c b/util/grub-install-common.c +index a74fee16e2..c603f5b308 100644 +--- a/util/grub-install-common.c ++++ b/util/grub-install-common.c +@@ -460,6 +460,8 @@ static char **pubkeys; + static size_t npubkeys; + static char *sbat; + static int disable_shim_lock; ++static char **x509keys; ++static size_t nx509keys; + static grub_compression_t compression; + static size_t appsig_size; + +@@ -501,6 +503,12 @@ grub_install_parse (int key, char *arg) + case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK: + disable_shim_lock = 1; + return 1; ++ case 'x': ++ x509keys = xrealloc (x509keys, ++ sizeof (x509keys[0]) ++ * (nx509keys + 1)); ++ x509keys[nx509keys++] = xstrdup (arg); ++ return 1; + + case GRUB_INSTALL_OPTIONS_VERBOSITY: + verbosity++; +@@ -627,6 +635,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, + for (pk = pubkeys; pk < pubkeys + npubkeys; pk++) + slen += 20 + grub_strlen (*pk); + ++ for (pk = x509keys; pk < x509keys + nx509keys; pk++) ++ slen += 10 + grub_strlen (*pk); ++ + for (md = modules.entries; *md; md++) + { + slen += 10 + grub_strlen (*md); +@@ -655,6 +666,14 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, + *p++ = ' '; + } + ++ for (pk = x509keys; pk < x509keys + nx509keys; pk++) ++ { ++ p = grub_stpcpy (p, "--x509 '"); ++ p = grub_stpcpy (p, *pk); ++ *p++ = '\''; ++ *p++ = ' '; ++ } ++ + for (md = modules.entries; *md; md++) + { + *p++ = '\''; +@@ -684,7 +703,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, + + grub_install_generate_image (dir, prefix, fp, outname, + modules.entries, memdisk_path, +- pubkeys, npubkeys, config_path, tgt, ++ pubkeys, npubkeys, ++ x509keys, nx509keys, ++ config_path, tgt, + note, appsig_size, compression, dtb, sbat, + disable_shim_lock); + while (dc--) +diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c +index 8a53310548..e1f1112784 100644 +--- a/util/grub-mkimage.c ++++ b/util/grub-mkimage.c +@@ -75,7 +75,8 @@ static struct argp_option options[] = { + /* TRANSLATORS: "embed" is a verb (command description). "*/ + {"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0}, + /* TRANSLATORS: "embed" is a verb (command description). "*/ +- {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for signature checking"), 0}, ++ {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for PGP signature checking"), 0}, ++ {"x509", 'x', N_("FILE"), 0, N_("embed FILE as an x509 certificate for appended signature checking"), 0}, + /* TRANSLATORS: NOTE is a name of segment. */ + {"note", 'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0}, + {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, +@@ -124,6 +125,8 @@ struct arguments + char *dtb; + char **pubkeys; + size_t npubkeys; ++ char **x509keys; ++ size_t nx509keys; + char *font; + char *config; + char *sbat; +@@ -206,6 +209,13 @@ argp_parser (int key, char *arg, struct argp_state *state) + arguments->pubkeys[arguments->npubkeys++] = xstrdup (arg); + break; + ++ case 'x': ++ arguments->x509keys = xrealloc (arguments->x509keys, ++ sizeof (arguments->x509keys[0]) ++ * (arguments->nx509keys + 1)); ++ arguments->x509keys[arguments->nx509keys++] = xstrdup (arg); ++ break; ++ + case 'c': + if (arguments->config) + free (arguments->config); +@@ -332,7 +342,8 @@ main (int argc, char *argv[]) + grub_install_generate_image (arguments.dir, arguments.prefix, fp, + arguments.output, arguments.modules, + arguments.memdisk, arguments.pubkeys, +- arguments.npubkeys, arguments.config, ++ arguments.npubkeys, arguments.x509keys, ++ arguments.nx509keys, arguments.config, + arguments.image_target, arguments.note, + arguments.appsig_size, arguments.comp, + arguments.dtb, arguments.sbat, +diff --git a/util/mkimage.c b/util/mkimage.c +index bab1227601..8319e8dfbd 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -867,7 +867,8 @@ void + grub_install_generate_image (const char *dir, const char *prefix, + FILE *out, const char *outname, char *mods[], + char *memdisk_path, char **pubkey_paths, +- size_t npubkeys, char *config_path, ++ size_t npubkeys, char **x509key_paths, ++ size_t nx509keys, char *config_path, + const struct grub_install_image_target_desc *image_target, + int note, size_t appsig_size, grub_compression_t comp, + const char *dtb_path, const char *sbat_path, +@@ -913,6 +914,19 @@ grub_install_generate_image (const char *dir, const char *prefix, + } + } + ++ { ++ size_t i; ++ for (i = 0; i < nx509keys; i++) ++ { ++ size_t curs; ++ curs = ALIGN_ADDR (grub_util_get_image_size (x509key_paths[i])); ++ grub_util_info ("the size of x509 public key %u is 0x%" ++ GRUB_HOST_PRIxLONG_LONG, ++ (unsigned) i, (unsigned long long) curs); ++ total_module_size += curs + sizeof (struct grub_module_header); ++ } ++ } ++ + if (memdisk_path) + { + memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512); +@@ -1034,7 +1048,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + curs = grub_util_get_image_size (pubkey_paths[i]); + + header = (struct grub_module_header *) (kernel_img + offset); +- header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY); ++ header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY); + header->size = grub_host_to_target32 (curs + sizeof (*header)); + offset += sizeof (*header); + +@@ -1043,6 +1057,26 @@ grub_install_generate_image (const char *dir, const char *prefix, + } + } + ++ { ++ size_t i; ++ for (i = 0; i < nx509keys; i++) ++ { ++ size_t curs; ++ struct grub_module_header *header; ++ ++ curs = grub_util_get_image_size (x509key_paths[i]); ++ ++ header = (struct grub_module_header *) (kernel_img + offset); ++ header->type = grub_host_to_target32 (OBJ_TYPE_X509_PUBKEY); ++ header->size = grub_host_to_target32 (curs + sizeof (*header)); ++ offset += sizeof (*header); ++ ++ grub_util_load_image (x509key_paths[i], kernel_img + offset); ++ offset += ALIGN_ADDR (curs); ++ } ++ } ++ ++ + if (memdisk_path) + { + struct grub_module_header *header; +diff --git a/include/grub/kernel.h b/include/grub/kernel.h +index 55849777ea..98edc0863f 100644 +--- a/include/grub/kernel.h ++++ b/include/grub/kernel.h +@@ -30,7 +30,9 @@ enum + OBJ_TYPE_PREFIX, + OBJ_TYPE_PUBKEY, + OBJ_TYPE_DTB, +- OBJ_TYPE_DISABLE_SHIM_LOCK ++ OBJ_TYPE_DISABLE_SHIM_LOCK, ++ OBJ_TYPE_GPG_PUBKEY, ++ OBJ_TYPE_X509_PUBKEY, + }; + + /* The module header. */ +diff --git a/include/grub/util/install.h b/include/grub/util/install.h +index cf4531e02b..51f3b13ac1 100644 +--- a/include/grub/util/install.h ++++ b/include/grub/util/install.h +@@ -67,6 +67,8 @@ + N_("SBAT metadata"), 0 }, \ + { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \ + N_("disable shim_lock verifier"), 0 }, \ ++ { "x509key", 'x', N_("FILE"), 0, \ ++ N_("embed FILE as an x509 certificate for signature checking"), 0}, \ + { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\ + "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \ + 1}, \ +@@ -188,8 +190,9 @@ void + grub_install_generate_image (const char *dir, const char *prefix, + FILE *out, + const char *outname, char *mods[], +- char *memdisk_path, char **pubkey_paths, +- size_t npubkeys, ++ char *memdisk_path, ++ char **pubkey_paths, size_t npubkeys, ++ char **x509key_paths, size_t nx509keys, + char *config_path, + const struct grub_install_image_target_desc *image_target, + int note, size_t appsig_size, diff --git a/SOURCES/0167-systemd-integration.sh-Also-set-old-menu_show_once-g.patch b/SOURCES/0167-systemd-integration.sh-Also-set-old-menu_show_once-g.patch deleted file mode 100644 index 9021de5..0000000 --- a/SOURCES/0167-systemd-integration.sh-Also-set-old-menu_show_once-g.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 23 Jul 2020 09:27:36 +0200 -Subject: [PATCH] systemd-integration.sh: Also set old menu_show_once grubenv - var - -Downstream RH / Fedora patch for compatibility with old, not (yet) -regenerated grub.cfg files which miss the menu_show_once_timeout check. -This older grubenv variable leads to a fixed timeout of 60 seconds. - -Note that the new menu_show_once_timeout will overrule these 60 seconds -if both are set and the grub.cfg does have the menu_show_once_timeout -check. - -Signed-off-by: Hans de Goede ---- - util/systemd/systemd-integration.sh.in | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/util/systemd/systemd-integration.sh.in b/util/systemd/systemd-integration.sh.in -index dc1218597bc..a4c071c5b0c 100644 ---- a/util/systemd/systemd-integration.sh.in -+++ b/util/systemd/systemd-integration.sh.in -@@ -4,3 +4,8 @@ TIMEOUT_USEC=$(cat /run/systemd/reboot-to-boot-loader-menu) - TIMEOUT=$(((TIMEOUT_USEC + 500000) / 1000000)) - - @grub_editenv@ - set menu_show_once_timeout=$TIMEOUT -+ -+# Downstream RH / Fedora patch for compatibility with old, not (yet) -+# regenerated grub.cfg files which miss the menu_show_once_timeout check -+# this older grubenv variable leads to a fixed timeout of 60 seconds -+@grub_editenv@ - set menu_show_once=1 diff --git a/SOURCES/0168-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch b/SOURCES/0168-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch new file mode 100644 index 0000000..0ebc6c7 --- /dev/null +++ b/SOURCES/0168-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch @@ -0,0 +1,639 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 30 Jul 2020 01:35:10 +1000 +Subject: [PATCH] appended signatures: import GNUTLS's ASN.1 description files + +In order to parse PKCS#7 messages and X.509 certificates with libtasn1, +we need some information about how they are encoded. + +We get these from GNUTLS, which has the benefit that they support the +features we need and are well tested. + +The GNUTLS license is LGPLv2.1+, which is GPLv3 compatible, allowing +us to import it without issue. + +Signed-off-by: Daniel Axtens +--- + grub-core/commands/appendedsig/gnutls_asn1_tab.c | 121 ++++++ + grub-core/commands/appendedsig/pkix_asn1_tab.c | 484 +++++++++++++++++++++++ + 2 files changed, 605 insertions(+) + create mode 100644 grub-core/commands/appendedsig/gnutls_asn1_tab.c + create mode 100644 grub-core/commands/appendedsig/pkix_asn1_tab.c + +diff --git a/grub-core/commands/appendedsig/gnutls_asn1_tab.c b/grub-core/commands/appendedsig/gnutls_asn1_tab.c +new file mode 100644 +index 0000000000..ddd1314e63 +--- /dev/null ++++ b/grub-core/commands/appendedsig/gnutls_asn1_tab.c +@@ -0,0 +1,121 @@ ++#include ++#include ++ ++const asn1_static_node gnutls_asn1_tab[] = { ++ { "GNUTLS", 536872976, NULL }, ++ { NULL, 1073741836, NULL }, ++ { "RSAPublicKey", 1610612741, NULL }, ++ { "modulus", 1073741827, NULL }, ++ { "publicExponent", 3, NULL }, ++ { "RSAPrivateKey", 1610612741, NULL }, ++ { "version", 1073741827, NULL }, ++ { "modulus", 1073741827, NULL }, ++ { "publicExponent", 1073741827, NULL }, ++ { "privateExponent", 1073741827, NULL }, ++ { "prime1", 1073741827, NULL }, ++ { "prime2", 1073741827, NULL }, ++ { "exponent1", 1073741827, NULL }, ++ { "exponent2", 1073741827, NULL }, ++ { "coefficient", 1073741827, NULL }, ++ { "otherPrimeInfos", 16386, "OtherPrimeInfos"}, ++ { "ProvableSeed", 1610612741, NULL }, ++ { "algorithm", 1073741836, NULL }, ++ { "seed", 7, NULL }, ++ { "OtherPrimeInfos", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "OtherPrimeInfo"}, ++ { "OtherPrimeInfo", 1610612741, NULL }, ++ { "prime", 1073741827, NULL }, ++ { "exponent", 1073741827, NULL }, ++ { "coefficient", 3, NULL }, ++ { "AlgorithmIdentifier", 1610612741, NULL }, ++ { "algorithm", 1073741836, NULL }, ++ { "parameters", 541081613, NULL }, ++ { "algorithm", 1, NULL }, ++ { "DigestInfo", 1610612741, NULL }, ++ { "digestAlgorithm", 1073741826, "DigestAlgorithmIdentifier"}, ++ { "digest", 7, NULL }, ++ { "DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"}, ++ { "DSAPublicKey", 1073741827, NULL }, ++ { "DSAParameters", 1610612741, NULL }, ++ { "p", 1073741827, NULL }, ++ { "q", 1073741827, NULL }, ++ { "g", 3, NULL }, ++ { "DSASignatureValue", 1610612741, NULL }, ++ { "r", 1073741827, NULL }, ++ { "s", 3, NULL }, ++ { "DSAPrivateKey", 1610612741, NULL }, ++ { "version", 1073741827, NULL }, ++ { "p", 1073741827, NULL }, ++ { "q", 1073741827, NULL }, ++ { "g", 1073741827, NULL }, ++ { "Y", 1073741827, NULL }, ++ { "priv", 3, NULL }, ++ { "DHParameter", 1610612741, NULL }, ++ { "prime", 1073741827, NULL }, ++ { "base", 1073741827, NULL }, ++ { "privateValueLength", 16387, NULL }, ++ { "ECParameters", 1610612754, NULL }, ++ { "namedCurve", 12, NULL }, ++ { "ECPrivateKey", 1610612741, NULL }, ++ { "Version", 1073741827, NULL }, ++ { "privateKey", 1073741831, NULL }, ++ { "parameters", 1610637314, "ECParameters"}, ++ { NULL, 2056, "0"}, ++ { "publicKey", 536895494, NULL }, ++ { NULL, 2056, "1"}, ++ { "PrincipalName", 1610612741, NULL }, ++ { "name-type", 1610620931, NULL }, ++ { NULL, 2056, "0"}, ++ { "name-string", 536879115, NULL }, ++ { NULL, 1073743880, "1"}, ++ { NULL, 27, NULL }, ++ { "KRB5PrincipalName", 1610612741, NULL }, ++ { "realm", 1610620955, NULL }, ++ { NULL, 2056, "0"}, ++ { "principalName", 536879106, "PrincipalName"}, ++ { NULL, 2056, "1"}, ++ { "RSAPSSParameters", 1610612741, NULL }, ++ { "hashAlgorithm", 1610637314, "AlgorithmIdentifier"}, ++ { NULL, 2056, "0"}, ++ { "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"}, ++ { NULL, 2056, "1"}, ++ { "saltLength", 1610653699, NULL }, ++ { NULL, 1073741833, "20"}, ++ { NULL, 2056, "2"}, ++ { "trailerField", 536911875, NULL }, ++ { NULL, 1073741833, "1"}, ++ { NULL, 2056, "3"}, ++ { "GOSTParameters", 1610612741, NULL }, ++ { "publicKeyParamSet", 1073741836, NULL }, ++ { "digestParamSet", 16396, NULL }, ++ { "GOSTParametersOld", 1610612741, NULL }, ++ { "publicKeyParamSet", 1073741836, NULL }, ++ { "digestParamSet", 1073741836, NULL }, ++ { "encryptionParamSet", 16396, NULL }, ++ { "GOSTPrivateKey", 1073741831, NULL }, ++ { "GOSTPrivateKeyOld", 1073741827, NULL }, ++ { "IssuerSignTool", 1610612741, NULL }, ++ { "signTool", 1073741858, NULL }, ++ { "cATool", 1073741858, NULL }, ++ { "signToolCert", 1073741858, NULL }, ++ { "cAToolCert", 34, NULL }, ++ { "Gost28147-89-EncryptedKey", 1610612741, NULL }, ++ { "encryptedKey", 1073741831, NULL }, ++ { "maskKey", 1610637319, NULL }, ++ { NULL, 4104, "0"}, ++ { "macKey", 7, NULL }, ++ { "SubjectPublicKeyInfo", 1610612741, NULL }, ++ { "algorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "subjectPublicKey", 6, NULL }, ++ { "GostR3410-TransportParameters", 1610612741, NULL }, ++ { "encryptionParamSet", 1073741836, NULL }, ++ { "ephemeralPublicKey", 1610637314, "SubjectPublicKeyInfo"}, ++ { NULL, 4104, "0"}, ++ { "ukm", 7, NULL }, ++ { "GostR3410-KeyTransport", 536870917, NULL }, ++ { "sessionEncryptedKey", 1073741826, "Gost28147-89-EncryptedKey"}, ++ { "transportParameters", 536895490, "GostR3410-TransportParameters"}, ++ { NULL, 4104, "0"}, ++ { NULL, 0, NULL } ++}; +diff --git a/grub-core/commands/appendedsig/pkix_asn1_tab.c b/grub-core/commands/appendedsig/pkix_asn1_tab.c +new file mode 100644 +index 0000000000..adef69d95c +--- /dev/null ++++ b/grub-core/commands/appendedsig/pkix_asn1_tab.c +@@ -0,0 +1,484 @@ ++#include ++#include ++ ++const asn1_static_node pkix_asn1_tab[] = { ++ { "PKIX1", 536875024, NULL }, ++ { NULL, 1073741836, NULL }, ++ { "PrivateKeyUsagePeriod", 1610612741, NULL }, ++ { "notBefore", 1610637349, NULL }, ++ { NULL, 4104, "0"}, ++ { "notAfter", 536895525, NULL }, ++ { NULL, 4104, "1"}, ++ { "AuthorityKeyIdentifier", 1610612741, NULL }, ++ { "keyIdentifier", 1610637319, NULL }, ++ { NULL, 4104, "0"}, ++ { "authorityCertIssuer", 1610637314, "GeneralNames"}, ++ { NULL, 4104, "1"}, ++ { "authorityCertSerialNumber", 536895490, "CertificateSerialNumber"}, ++ { NULL, 4104, "2"}, ++ { "SubjectKeyIdentifier", 1073741831, NULL }, ++ { "KeyUsage", 1073741830, NULL }, ++ { "DirectoryString", 1610612754, NULL }, ++ { "teletexString", 1612709918, NULL }, ++ { "MAX", 524298, "1"}, ++ { "printableString", 1612709919, NULL }, ++ { "MAX", 524298, "1"}, ++ { "universalString", 1612709920, NULL }, ++ { "MAX", 524298, "1"}, ++ { "utf8String", 1612709922, NULL }, ++ { "MAX", 524298, "1"}, ++ { "bmpString", 1612709921, NULL }, ++ { "MAX", 524298, "1"}, ++ { "ia5String", 538968093, NULL }, ++ { "MAX", 524298, "1"}, ++ { "SubjectAltName", 1073741826, "GeneralNames"}, ++ { "GeneralNames", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "GeneralName"}, ++ { "GeneralName", 1610612754, NULL }, ++ { "otherName", 1610620930, "AnotherName"}, ++ { NULL, 4104, "0"}, ++ { "rfc822Name", 1610620957, NULL }, ++ { NULL, 4104, "1"}, ++ { "dNSName", 1610620957, NULL }, ++ { NULL, 4104, "2"}, ++ { "x400Address", 1610620941, NULL }, ++ { NULL, 4104, "3"}, ++ { "directoryName", 1610620939, NULL }, ++ { NULL, 1073743880, "4"}, ++ { NULL, 2, "RelativeDistinguishedName"}, ++ { "ediPartyName", 1610620941, NULL }, ++ { NULL, 4104, "5"}, ++ { "uniformResourceIdentifier", 1610620957, NULL }, ++ { NULL, 4104, "6"}, ++ { "iPAddress", 1610620935, NULL }, ++ { NULL, 4104, "7"}, ++ { "registeredID", 536879116, NULL }, ++ { NULL, 4104, "8"}, ++ { "AnotherName", 1610612741, NULL }, ++ { "type-id", 1073741836, NULL }, ++ { "value", 541073421, NULL }, ++ { NULL, 1073743880, "0"}, ++ { "type-id", 1, NULL }, ++ { "IssuerAltName", 1073741826, "GeneralNames"}, ++ { "BasicConstraints", 1610612741, NULL }, ++ { "cA", 1610645508, NULL }, ++ { NULL, 131081, NULL }, ++ { "pathLenConstraint", 537411587, NULL }, ++ { "0", 10, "MAX"}, ++ { "CRLDistributionPoints", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "DistributionPoint"}, ++ { "DistributionPoint", 1610612741, NULL }, ++ { "distributionPoint", 1610637314, "DistributionPointName"}, ++ { NULL, 2056, "0"}, ++ { "reasons", 1610637314, "ReasonFlags"}, ++ { NULL, 4104, "1"}, ++ { "cRLIssuer", 536895490, "GeneralNames"}, ++ { NULL, 4104, "2"}, ++ { "DistributionPointName", 1610612754, NULL }, ++ { "fullName", 1610620930, "GeneralNames"}, ++ { NULL, 4104, "0"}, ++ { "nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"}, ++ { NULL, 4104, "1"}, ++ { "ReasonFlags", 1073741830, NULL }, ++ { "ExtKeyUsageSyntax", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 12, NULL }, ++ { "AuthorityInfoAccessSyntax", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "AccessDescription"}, ++ { "AccessDescription", 1610612741, NULL }, ++ { "accessMethod", 1073741836, NULL }, ++ { "accessLocation", 2, "GeneralName"}, ++ { "Attribute", 1610612741, NULL }, ++ { "type", 1073741836, NULL }, ++ { "values", 536870927, NULL }, ++ { NULL, 13, NULL }, ++ { "AttributeTypeAndValue", 1610612741, NULL }, ++ { "type", 1073741836, NULL }, ++ { "value", 13, NULL }, ++ { "Name", 1610612754, NULL }, ++ { "rdnSequence", 536870923, NULL }, ++ { NULL, 2, "RelativeDistinguishedName"}, ++ { "DistinguishedName", 1610612747, NULL }, ++ { NULL, 2, "RelativeDistinguishedName"}, ++ { "RelativeDistinguishedName", 1612709903, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "AttributeTypeAndValue"}, ++ { "Certificate", 1610612741, NULL }, ++ { "tbsCertificate", 1073741826, "TBSCertificate"}, ++ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "signature", 6, NULL }, ++ { "TBSCertificate", 1610612741, NULL }, ++ { "version", 1610653699, NULL }, ++ { NULL, 1073741833, "0"}, ++ { NULL, 2056, "0"}, ++ { "serialNumber", 1073741826, "CertificateSerialNumber"}, ++ { "signature", 1073741826, "AlgorithmIdentifier"}, ++ { "issuer", 1073741826, "Name"}, ++ { "validity", 1073741826, "Validity"}, ++ { "subject", 1073741826, "Name"}, ++ { "subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"}, ++ { "issuerUniqueID", 1610637314, "UniqueIdentifier"}, ++ { NULL, 4104, "1"}, ++ { "subjectUniqueID", 1610637314, "UniqueIdentifier"}, ++ { NULL, 4104, "2"}, ++ { "extensions", 536895490, "Extensions"}, ++ { NULL, 2056, "3"}, ++ { "CertificateSerialNumber", 1073741827, NULL }, ++ { "Validity", 1610612741, NULL }, ++ { "notBefore", 1073741826, "Time"}, ++ { "notAfter", 2, "Time"}, ++ { "Time", 1610612754, NULL }, ++ { "utcTime", 1073741860, NULL }, ++ { "generalTime", 37, NULL }, ++ { "UniqueIdentifier", 1073741830, NULL }, ++ { "SubjectPublicKeyInfo", 1610612741, NULL }, ++ { "algorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "subjectPublicKey", 6, NULL }, ++ { "Extensions", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "Extension"}, ++ { "Extension", 1610612741, NULL }, ++ { "extnID", 1073741836, NULL }, ++ { "critical", 1610645508, NULL }, ++ { NULL, 131081, NULL }, ++ { "extnValue", 7, NULL }, ++ { "CertificateList", 1610612741, NULL }, ++ { "tbsCertList", 1073741826, "TBSCertList"}, ++ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "signature", 6, NULL }, ++ { "TBSCertList", 1610612741, NULL }, ++ { "version", 1073758211, NULL }, ++ { "signature", 1073741826, "AlgorithmIdentifier"}, ++ { "issuer", 1073741826, "Name"}, ++ { "thisUpdate", 1073741826, "Time"}, ++ { "nextUpdate", 1073758210, "Time"}, ++ { "revokedCertificates", 1610629131, NULL }, ++ { NULL, 536870917, NULL }, ++ { "userCertificate", 1073741826, "CertificateSerialNumber"}, ++ { "revocationDate", 1073741826, "Time"}, ++ { "crlEntryExtensions", 16386, "Extensions"}, ++ { "crlExtensions", 536895490, "Extensions"}, ++ { NULL, 2056, "0"}, ++ { "AlgorithmIdentifier", 1610612741, NULL }, ++ { "algorithm", 1073741836, NULL }, ++ { "parameters", 541081613, NULL }, ++ { "algorithm", 1, NULL }, ++ { "Dss-Sig-Value", 1610612741, NULL }, ++ { "r", 1073741827, NULL }, ++ { "s", 3, NULL }, ++ { "Dss-Parms", 1610612741, NULL }, ++ { "p", 1073741827, NULL }, ++ { "q", 1073741827, NULL }, ++ { "g", 3, NULL }, ++ { "pkcs-7-ContentInfo", 1610612741, NULL }, ++ { "contentType", 1073741836, NULL }, ++ { "content", 541073421, NULL }, ++ { NULL, 1073743880, "0"}, ++ { "contentType", 1, NULL }, ++ { "pkcs-7-DigestInfo", 1610612741, NULL }, ++ { "digestAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "digest", 7, NULL }, ++ { "pkcs-7-SignedData", 1610612741, NULL }, ++ { "version", 1073741827, NULL }, ++ { "digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"}, ++ { "encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"}, ++ { "certificates", 1610637314, "pkcs-7-CertificateSet"}, ++ { NULL, 4104, "0"}, ++ { "crls", 1610637314, "pkcs-7-CertificateRevocationLists"}, ++ { NULL, 4104, "1"}, ++ { "signerInfos", 2, "pkcs-7-SignerInfos"}, ++ { "pkcs-7-DigestAlgorithmIdentifiers", 1610612751, NULL }, ++ { NULL, 2, "AlgorithmIdentifier"}, ++ { "pkcs-7-EncapsulatedContentInfo", 1610612741, NULL }, ++ { "eContentType", 1073741836, NULL }, ++ { "eContent", 536895501, NULL }, ++ { NULL, 2056, "0"}, ++ { "pkcs-7-CertificateRevocationLists", 1610612751, NULL }, ++ { NULL, 13, NULL }, ++ { "pkcs-7-CertificateChoices", 1610612754, NULL }, ++ { "certificate", 13, NULL }, ++ { "pkcs-7-CertificateSet", 1610612751, NULL }, ++ { NULL, 2, "pkcs-7-CertificateChoices"}, ++ { "IssuerAndSerialNumber", 1610612741, NULL }, ++ { "issuer", 1073741826, "Name"}, ++ { "serialNumber", 2, "CertificateSerialNumber"}, ++ { "pkcs-7-SignerInfo", 1610612741, NULL }, ++ { "version", 1073741827, NULL }, ++ { "sid", 1073741826, "SignerIdentifier"}, ++ { "digestAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "signedAttrs", 1610637314, "SignedAttributes"}, ++ { NULL, 4104, "0"}, ++ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "signature", 1073741831, NULL }, ++ { "unsignedAttrs", 536895490, "SignedAttributes"}, ++ { NULL, 4104, "1"}, ++ { "SignedAttributes", 1612709903, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "Attribute"}, ++ { "SignerIdentifier", 1610612754, NULL }, ++ { "issuerAndSerialNumber", 1073741826, "IssuerAndSerialNumber"}, ++ { "subjectKeyIdentifier", 536879111, NULL }, ++ { NULL, 4104, "0"}, ++ { "pkcs-7-SignerInfos", 1610612751, NULL }, ++ { NULL, 2, "pkcs-7-SignerInfo"}, ++ { "pkcs-10-CertificationRequestInfo", 1610612741, NULL }, ++ { "version", 1073741827, NULL }, ++ { "subject", 1073741826, "Name"}, ++ { "subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"}, ++ { "attributes", 536879106, "Attributes"}, ++ { NULL, 4104, "0"}, ++ { "Attributes", 1610612751, NULL }, ++ { NULL, 2, "Attribute"}, ++ { "pkcs-10-CertificationRequest", 1610612741, NULL }, ++ { "certificationRequestInfo", 1073741826, "pkcs-10-CertificationRequestInfo"}, ++ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "signature", 6, NULL }, ++ { "pkcs-9-at-challengePassword", 1879048204, NULL }, ++ { "iso", 1073741825, "1"}, ++ { "member-body", 1073741825, "2"}, ++ { "us", 1073741825, "840"}, ++ { "rsadsi", 1073741825, "113549"}, ++ { "pkcs", 1073741825, "1"}, ++ { NULL, 1073741825, "9"}, ++ { NULL, 1, "7"}, ++ { "pkcs-9-challengePassword", 1610612754, NULL }, ++ { "printableString", 1073741855, NULL }, ++ { "utf8String", 34, NULL }, ++ { "pkcs-9-localKeyId", 1073741831, NULL }, ++ { "pkcs-8-PrivateKeyInfo", 1610612741, NULL }, ++ { "version", 1073741827, NULL }, ++ { "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "privateKey", 1073741831, NULL }, ++ { "attributes", 536895490, "Attributes"}, ++ { NULL, 4104, "0"}, ++ { "pkcs-8-EncryptedPrivateKeyInfo", 1610612741, NULL }, ++ { "encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "encryptedData", 2, "pkcs-8-EncryptedData"}, ++ { "pkcs-8-EncryptedData", 1073741831, NULL }, ++ { "pkcs-5-des-CBC-params", 1612709895, NULL }, ++ { NULL, 1048586, "8"}, ++ { "pkcs-5-des-EDE3-CBC-params", 1612709895, NULL }, ++ { NULL, 1048586, "8"}, ++ { "pkcs-5-aes128-CBC-params", 1612709895, NULL }, ++ { NULL, 1048586, "16"}, ++ { "pkcs-5-aes192-CBC-params", 1612709895, NULL }, ++ { NULL, 1048586, "16"}, ++ { "pkcs-5-aes256-CBC-params", 1612709895, NULL }, ++ { NULL, 1048586, "16"}, ++ { "Gost28147-89-Parameters", 1610612741, NULL }, ++ { "iv", 1073741831, NULL }, ++ { "encryptionParamSet", 12, NULL }, ++ { "pkcs-5-PBE-params", 1610612741, NULL }, ++ { "salt", 1073741831, NULL }, ++ { "iterationCount", 3, NULL }, ++ { "pkcs-5-PBES2-params", 1610612741, NULL }, ++ { "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"}, ++ { "encryptionScheme", 2, "AlgorithmIdentifier"}, ++ { "pkcs-5-PBKDF2-params", 1610612741, NULL }, ++ { "salt", 1610612754, NULL }, ++ { "specified", 1073741831, NULL }, ++ { "otherSource", 2, "AlgorithmIdentifier"}, ++ { "iterationCount", 1611137027, NULL }, ++ { "1", 10, "MAX"}, ++ { "keyLength", 1611153411, NULL }, ++ { "1", 10, "MAX"}, ++ { "prf", 16386, "AlgorithmIdentifier"}, ++ { "pkcs-12-PFX", 1610612741, NULL }, ++ { "version", 1610874883, NULL }, ++ { "v3", 1, "3"}, ++ { "authSafe", 1073741826, "pkcs-7-ContentInfo"}, ++ { "macData", 16386, "pkcs-12-MacData"}, ++ { "pkcs-12-PbeParams", 1610612741, NULL }, ++ { "salt", 1073741831, NULL }, ++ { "iterations", 3, NULL }, ++ { "pkcs-12-MacData", 1610612741, NULL }, ++ { "mac", 1073741826, "pkcs-7-DigestInfo"}, ++ { "macSalt", 1073741831, NULL }, ++ { "iterations", 536903683, NULL }, ++ { NULL, 9, "1"}, ++ { "pkcs-12-AuthenticatedSafe", 1610612747, NULL }, ++ { NULL, 2, "pkcs-7-ContentInfo"}, ++ { "pkcs-12-SafeContents", 1610612747, NULL }, ++ { NULL, 2, "pkcs-12-SafeBag"}, ++ { "pkcs-12-SafeBag", 1610612741, NULL }, ++ { "bagId", 1073741836, NULL }, ++ { "bagValue", 1614815245, NULL }, ++ { NULL, 1073743880, "0"}, ++ { "badId", 1, NULL }, ++ { "bagAttributes", 536887311, NULL }, ++ { NULL, 2, "Attribute"}, ++ { "pkcs-12-CertBag", 1610612741, NULL }, ++ { "certId", 1073741836, NULL }, ++ { "certValue", 541073421, NULL }, ++ { NULL, 1073743880, "0"}, ++ { "certId", 1, NULL }, ++ { "pkcs-12-CRLBag", 1610612741, NULL }, ++ { "crlId", 1073741836, NULL }, ++ { "crlValue", 541073421, NULL }, ++ { NULL, 1073743880, "0"}, ++ { "crlId", 1, NULL }, ++ { "pkcs-12-SecretBag", 1610612741, NULL }, ++ { "secretTypeId", 1073741836, NULL }, ++ { "secretValue", 541073421, NULL }, ++ { NULL, 1073743880, "0"}, ++ { "secretTypeId", 1, NULL }, ++ { "pkcs-7-Data", 1073741831, NULL }, ++ { "pkcs-7-EncryptedData", 1610612741, NULL }, ++ { "version", 1073741827, NULL }, ++ { "encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"}, ++ { "unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"}, ++ { NULL, 4104, "1"}, ++ { "pkcs-7-EncryptedContentInfo", 1610612741, NULL }, ++ { "contentType", 1073741836, NULL }, ++ { "contentEncryptionAlgorithm", 1073741826, "pkcs-7-ContentEncryptionAlgorithmIdentifier"}, ++ { "encryptedContent", 536895495, NULL }, ++ { NULL, 4104, "0"}, ++ { "pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"}, ++ { "pkcs-7-UnprotectedAttributes", 1612709903, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "Attribute"}, ++ { "ProxyCertInfo", 1610612741, NULL }, ++ { "pCPathLenConstraint", 1611153411, NULL }, ++ { "0", 10, "MAX"}, ++ { "proxyPolicy", 2, "ProxyPolicy"}, ++ { "ProxyPolicy", 1610612741, NULL }, ++ { "policyLanguage", 1073741836, NULL }, ++ { "policy", 16391, NULL }, ++ { "certificatePolicies", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "PolicyInformation"}, ++ { "PolicyInformation", 1610612741, NULL }, ++ { "policyIdentifier", 1073741836, NULL }, ++ { "policyQualifiers", 538984459, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "PolicyQualifierInfo"}, ++ { "PolicyQualifierInfo", 1610612741, NULL }, ++ { "policyQualifierId", 1073741836, NULL }, ++ { "qualifier", 541065229, NULL }, ++ { "policyQualifierId", 1, NULL }, ++ { "CPSuri", 1073741853, NULL }, ++ { "UserNotice", 1610612741, NULL }, ++ { "noticeRef", 1073758210, "NoticeReference"}, ++ { "explicitText", 16386, "DisplayText"}, ++ { "NoticeReference", 1610612741, NULL }, ++ { "organization", 1073741826, "DisplayText"}, ++ { "noticeNumbers", 536870923, NULL }, ++ { NULL, 3, NULL }, ++ { "DisplayText", 1610612754, NULL }, ++ { "ia5String", 1612709917, NULL }, ++ { "200", 524298, "1"}, ++ { "visibleString", 1612709923, NULL }, ++ { "200", 524298, "1"}, ++ { "bmpString", 1612709921, NULL }, ++ { "200", 524298, "1"}, ++ { "utf8String", 538968098, NULL }, ++ { "200", 524298, "1"}, ++ { "OCSPRequest", 1610612741, NULL }, ++ { "tbsRequest", 1073741826, "TBSRequest"}, ++ { "optionalSignature", 536895490, "Signature"}, ++ { NULL, 2056, "0"}, ++ { "TBSRequest", 1610612741, NULL }, ++ { "version", 1610653699, NULL }, ++ { NULL, 1073741833, "0"}, ++ { NULL, 2056, "0"}, ++ { "requestorName", 1610637314, "GeneralName"}, ++ { NULL, 2056, "1"}, ++ { "requestList", 1610612747, NULL }, ++ { NULL, 2, "Request"}, ++ { "requestExtensions", 536895490, "Extensions"}, ++ { NULL, 2056, "2"}, ++ { "Signature", 1610612741, NULL }, ++ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "signature", 1073741830, NULL }, ++ { "certs", 536895499, NULL }, ++ { NULL, 1073743880, "0"}, ++ { NULL, 2, "Certificate"}, ++ { "Request", 1610612741, NULL }, ++ { "reqCert", 1073741826, "CertID"}, ++ { "singleRequestExtensions", 536895490, "Extensions"}, ++ { NULL, 2056, "0"}, ++ { "CertID", 1610612741, NULL }, ++ { "hashAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "issuerNameHash", 1073741831, NULL }, ++ { "issuerKeyHash", 1073741831, NULL }, ++ { "serialNumber", 2, "CertificateSerialNumber"}, ++ { "OCSPResponse", 1610612741, NULL }, ++ { "responseStatus", 1073741826, "OCSPResponseStatus"}, ++ { "responseBytes", 536895490, "ResponseBytes"}, ++ { NULL, 2056, "0"}, ++ { "OCSPResponseStatus", 1610874901, NULL }, ++ { "successful", 1073741825, "0"}, ++ { "malformedRequest", 1073741825, "1"}, ++ { "internalError", 1073741825, "2"}, ++ { "tryLater", 1073741825, "3"}, ++ { "sigRequired", 1073741825, "5"}, ++ { "unauthorized", 1, "6"}, ++ { "ResponseBytes", 1610612741, NULL }, ++ { "responseType", 1073741836, NULL }, ++ { "response", 7, NULL }, ++ { "BasicOCSPResponse", 1610612741, NULL }, ++ { "tbsResponseData", 1073741826, "ResponseData"}, ++ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, ++ { "signature", 1073741830, NULL }, ++ { "certs", 536895499, NULL }, ++ { NULL, 1073743880, "0"}, ++ { NULL, 2, "Certificate"}, ++ { "ResponseData", 1610612741, NULL }, ++ { "version", 1610653699, NULL }, ++ { NULL, 1073741833, "0"}, ++ { NULL, 2056, "0"}, ++ { "responderID", 1073741826, "ResponderID"}, ++ { "producedAt", 1073741861, NULL }, ++ { "responses", 1610612747, NULL }, ++ { NULL, 2, "SingleResponse"}, ++ { "responseExtensions", 536895490, "Extensions"}, ++ { NULL, 2056, "1"}, ++ { "ResponderID", 1610612754, NULL }, ++ { "byName", 1610620939, NULL }, ++ { NULL, 1073743880, "1"}, ++ { NULL, 2, "RelativeDistinguishedName"}, ++ { "byKey", 536879111, NULL }, ++ { NULL, 2056, "2"}, ++ { "SingleResponse", 1610612741, NULL }, ++ { "certID", 1073741826, "CertID"}, ++ { "certStatus", 1073741826, "CertStatus"}, ++ { "thisUpdate", 1073741861, NULL }, ++ { "nextUpdate", 1610637349, NULL }, ++ { NULL, 2056, "0"}, ++ { "singleExtensions", 536895490, "Extensions"}, ++ { NULL, 2056, "1"}, ++ { "CertStatus", 1610612754, NULL }, ++ { "good", 1610620948, NULL }, ++ { NULL, 4104, "0"}, ++ { "revoked", 1610620930, "RevokedInfo"}, ++ { NULL, 4104, "1"}, ++ { "unknown", 536879106, "UnknownInfo"}, ++ { NULL, 4104, "2"}, ++ { "RevokedInfo", 1610612741, NULL }, ++ { "revocationTime", 1073741861, NULL }, ++ { "revocationReason", 537157653, NULL }, ++ { NULL, 1073743880, "0"}, ++ { "unspecified", 1, "0"}, ++ { "UnknownInfo", 1073741844, NULL }, ++ { "NameConstraints", 1610612741, NULL }, ++ { "permittedSubtrees", 1610637314, "GeneralSubtrees"}, ++ { NULL, 4104, "0"}, ++ { "excludedSubtrees", 536895490, "GeneralSubtrees"}, ++ { NULL, 4104, "1"}, ++ { "GeneralSubtrees", 1612709899, NULL }, ++ { "MAX", 1074266122, "1"}, ++ { NULL, 2, "GeneralSubtree"}, ++ { "GeneralSubtree", 1610612741, NULL }, ++ { "base", 1073741826, "GeneralName"}, ++ { "minimum", 1610653699, NULL }, ++ { NULL, 1073741833, "0"}, ++ { NULL, 4104, "0"}, ++ { "maximum", 536895491, NULL }, ++ { NULL, 4104, "1"}, ++ { "TlsFeatures", 536870923, NULL }, ++ { NULL, 3, NULL }, ++ { NULL, 0, NULL } ++}; diff --git a/SOURCES/0168-at_keyboard-use-set-1-when-keyboard-is-in-Translate-.patch b/SOURCES/0168-at_keyboard-use-set-1-when-keyboard-is-in-Translate-.patch deleted file mode 100644 index c338840..0000000 --- a/SOURCES/0168-at_keyboard-use-set-1-when-keyboard-is-in-Translate-.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Thu, 3 Dec 2020 09:13:24 +0100 -Subject: [PATCH] at_keyboard: use set 1 when keyboard is in Translate mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When keyboard controller acts in Translate mode (0x40 mask), then use -set 1 since translation is done. -Otherwise use the mode queried from the controller (usually set 2). - -Added "atkeyb" debugging messages in at_keyboard module as well. - -Resolves: rhbz#1897587 - -Tested on: -- Asus N53SN (set 1 used) -- Dell Precision (set 1 used) -- HP Elitebook (set 2 used) -- HP G5430 (set 1 used, keyboard in XT mode!) -- Lenovo P71 & Lenovo T460s (set 2 used) -- QEMU/KVM (set 1 used) - -Signed-off-by: Renaud Métrich ---- - grub-core/term/at_keyboard.c | 29 ++++++++++++++++++++++++----- - include/grub/at_keyboard.h | 4 ++++ - 2 files changed, 28 insertions(+), 5 deletions(-) - -diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c -index 597111077bd..26014382608 100644 ---- a/grub-core/term/at_keyboard.c -+++ b/grub-core/term/at_keyboard.c -@@ -135,20 +135,28 @@ query_mode (void) - int e; - - e = write_mode (0); -- if (!e) -+ if (!e) { -+ grub_dprintf("atkeyb", "query_mode: write_mode(0) failed\n"); - return 0; -+ } - - do { - keyboard_controller_wait_until_ready (); - ret = grub_inb (KEYBOARD_REG_DATA); - } while (ret == GRUB_AT_ACK); - /* QEMU translates the set even in no-translate mode. */ -- if (ret == 0x43 || ret == 1) -+ if (ret == 0x43 || ret == 1) { -+ grub_dprintf("atkeyb", "query_mode: returning 1 (ret=0x%x)\n", ret); - return 1; -- if (ret == 0x41 || ret == 2) -+ } -+ if (ret == 0x41 || ret == 2) { -+ grub_dprintf("atkeyb", "query_mode: returning 2 (ret=0x%x)\n", ret); - return 2; -- if (ret == 0x3f || ret == 3) -+ } -+ if (ret == 0x3f || ret == 3) { -+ grub_dprintf("atkeyb", "query_mode: returning 3 (ret=0x%x)\n", ret); - return 3; -+ } - return 0; - } - -@@ -165,7 +173,13 @@ set_scancodes (void) - } - - #if !USE_SCANCODE_SET -- ps2_state.current_set = 1; -+ if ((grub_keyboard_controller_orig & KEYBOARD_AT_TRANSLATE) == KEYBOARD_AT_TRANSLATE) { -+ grub_dprintf ("atkeyb", "queried set is %d but keyboard in Translate mode, so actually in set 1\n", grub_keyboard_orig_set); -+ ps2_state.current_set = 1; -+ } else { -+ grub_dprintf ("atkeyb", "using queried set %d\n", grub_keyboard_orig_set); -+ ps2_state.current_set = grub_keyboard_orig_set; -+ } - return; - #else - -@@ -266,6 +280,7 @@ grub_keyboard_controller_init (void) - grub_keyboard_orig_set = 2; - #else - grub_keyboard_controller_orig = grub_keyboard_controller_read (); -+ grub_dprintf ("atkeyb", "grub_keyboard_controller_orig = 0x%x\n", grub_keyboard_controller_orig); - grub_keyboard_orig_set = query_mode (); - #endif - set_scancodes (); -@@ -275,11 +290,15 @@ grub_keyboard_controller_init (void) - static grub_err_t - grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) - { -+/* In !USE_SCANCODE_SET mode, we didn't change anything, so nothing to restore */ -+#if USE_SCANCODE_SET - if (ps2_state.current_set == 0) - return GRUB_ERR_NONE; -+ grub_dprintf ("atkeyb", "restoring set %d, controller 0x%x\n", grub_keyboard_orig_set, grub_keyboard_controller_orig); - if (grub_keyboard_orig_set) - write_mode (grub_keyboard_orig_set); - grub_keyboard_controller_write (grub_keyboard_controller_orig); -+#endif - return GRUB_ERR_NONE; - } - -diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h -index bcb4d9ba78f..9414dc1b996 100644 ---- a/include/grub/at_keyboard.h -+++ b/include/grub/at_keyboard.h -@@ -19,6 +19,10 @@ - #ifndef GRUB_AT_KEYBOARD_HEADER - #define GRUB_AT_KEYBOARD_HEADER 1 - -+/* -+ * Refer to https://wiki.osdev.org/%228042%22_PS/2_Controller for details. -+ */ -+ - /* Used for sending commands to the controller. */ - #define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02) - #define KEYBOARD_COMMAND_READ 0x20 diff --git a/SOURCES/0169-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch b/SOURCES/0169-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch new file mode 100644 index 0000000..5a13d5b --- /dev/null +++ b/SOURCES/0169-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch @@ -0,0 +1,1528 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 30 Jul 2020 01:33:46 +1000 +Subject: [PATCH] appended signatures: parse PKCS#7 signedData and X.509 + certificates + +This code allows us to parse: + + - PKCS#7 signedData messages. Only a single signerInfo is supported, + which is all that the Linux sign-file utility supports creating + out-of-the-box. Only RSA, SHA-256 and SHA-512 are supported. + Any certificate embedded in the PKCS#7 message will be ignored. + + - X.509 certificates: at least enough to verify the signatures on the + PKCS#7 messages. We expect that the certificates embedded in grub will + be leaf certificates, not CA certificates. The parser enforces this. + +Signed-off-by: Daniel Axtens +--- + grub-core/commands/appendedsig/asn1util.c | 102 +++ + grub-core/commands/appendedsig/pkcs7.c | 305 +++++++++ + grub-core/commands/appendedsig/x509.c | 958 +++++++++++++++++++++++++++ + grub-core/commands/appendedsig/appendedsig.h | 110 +++ + 4 files changed, 1475 insertions(+) + create mode 100644 grub-core/commands/appendedsig/asn1util.c + create mode 100644 grub-core/commands/appendedsig/pkcs7.c + create mode 100644 grub-core/commands/appendedsig/x509.c + create mode 100644 grub-core/commands/appendedsig/appendedsig.h + +diff --git a/grub-core/commands/appendedsig/asn1util.c b/grub-core/commands/appendedsig/asn1util.c +new file mode 100644 +index 0000000000..eff095a9df +--- /dev/null ++++ b/grub-core/commands/appendedsig/asn1util.c +@@ -0,0 +1,102 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "appendedsig.h" ++ ++asn1_node _gnutls_gnutls_asn = ASN1_TYPE_EMPTY; ++asn1_node _gnutls_pkix_asn = ASN1_TYPE_EMPTY; ++ ++extern const ASN1_ARRAY_TYPE gnutls_asn1_tab[]; ++extern const ASN1_ARRAY_TYPE pkix_asn1_tab[]; ++ ++/* ++ * Read a value from an ASN1 node, allocating memory to store it. ++ * ++ * It will work for anything where the size libtasn1 returns is right: ++ * - Integers ++ * - Octet strings ++ * - DER encoding of other structures ++ * It will _not_ work for things where libtasn1 size requires adjustment: ++ * - Strings that require an extra NULL byte at the end ++ * - Bit strings because libtasn1 returns the length in bits, not bytes. ++ * ++ * If the function returns a non-NULL value, the caller must free it. ++ */ ++void * ++grub_asn1_allocate_and_read (asn1_node node, const char *name, ++ const char *friendly_name, int *content_size) ++{ ++ int result; ++ grub_uint8_t *tmpstr = NULL; ++ int tmpstr_size = 0; ++ ++ result = asn1_read_value (node, name, NULL, &tmpstr_size); ++ if (result != ASN1_MEM_ERROR) ++ { ++ grub_snprintf (grub_errmsg, sizeof (grub_errmsg), ++ _ ++ ("Reading size of %s did not return expected status: %s"), ++ friendly_name, asn1_strerror (result)); ++ grub_errno = GRUB_ERR_BAD_FILE_TYPE; ++ return NULL; ++ } ++ ++ tmpstr = grub_malloc (tmpstr_size); ++ if (tmpstr == NULL) ++ { ++ grub_snprintf (grub_errmsg, sizeof (grub_errmsg), ++ "Could not allocate memory to store %s", friendly_name); ++ grub_errno = GRUB_ERR_OUT_OF_MEMORY; ++ return NULL; ++ } ++ ++ result = asn1_read_value (node, name, tmpstr, &tmpstr_size); ++ if (result != ASN1_SUCCESS) ++ { ++ grub_free (tmpstr); ++ grub_snprintf (grub_errmsg, sizeof (grub_errmsg), ++ "Error reading %s: %s", ++ friendly_name, asn1_strerror (result)); ++ grub_errno = GRUB_ERR_BAD_FILE_TYPE; ++ return NULL; ++ } ++ ++ *content_size = tmpstr_size; ++ ++ return tmpstr; ++} ++ ++int ++asn1_init (void) ++{ ++ int res; ++ res = asn1_array2tree (gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL); ++ if (res != ASN1_SUCCESS) ++ { ++ return res; ++ } ++ res = asn1_array2tree (pkix_asn1_tab, &_gnutls_pkix_asn, NULL); ++ return res; ++} +diff --git a/grub-core/commands/appendedsig/pkcs7.c b/grub-core/commands/appendedsig/pkcs7.c +new file mode 100644 +index 0000000000..dc6afe203f +--- /dev/null ++++ b/grub-core/commands/appendedsig/pkcs7.c +@@ -0,0 +1,305 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include "appendedsig.h" ++#include ++#include ++#include ++ ++ ++static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; ++ ++/* ++ * RFC 5652 s 5.1 ++ */ ++const char *signedData_oid = "1.2.840.113549.1.7.2"; ++ ++/* ++ * RFC 4055 s 2.1 ++ */ ++const char *sha256_oid = "2.16.840.1.101.3.4.2.1"; ++const char *sha512_oid = "2.16.840.1.101.3.4.2.3"; ++ ++static grub_err_t ++process_content (grub_uint8_t * content, int size, ++ struct pkcs7_signedData *msg) ++{ ++ int res; ++ asn1_node signed_part; ++ grub_err_t err = GRUB_ERR_NONE; ++ char algo_oid[MAX_OID_LEN]; ++ int algo_oid_size = sizeof (algo_oid); ++ int algo_count; ++ char version; ++ int version_size = sizeof (version); ++ grub_uint8_t *result_buf; ++ int result_size = 0; ++ int crls_size = 0; ++ gcry_error_t gcry_err; ++ ++ res = asn1_create_element (_gnutls_pkix_asn, "PKIX1.pkcs-7-SignedData", ++ &signed_part); ++ if (res != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for PKCS#7 signed part."); ++ } ++ ++ res = asn1_der_decoding2 (&signed_part, content, &size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (res != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Error reading PKCS#7 signed data: %s", asn1_error); ++ goto cleanup_signed_part; ++ } ++ ++ /* SignedData ::= SEQUENCE { ++ * version CMSVersion, ++ * digestAlgorithms DigestAlgorithmIdentifiers, ++ * encapContentInfo EncapsulatedContentInfo, ++ * certificates [0] IMPLICIT CertificateSet OPTIONAL, ++ * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL, ++ * signerInfos SignerInfos } ++ */ ++ ++ /* version per the algo in 5.1, must be 1 */ ++ res = asn1_read_value (signed_part, "version", &version, &version_size); ++ if (res != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Error reading signedData version: %s", ++ asn1_strerror (res)); ++ goto cleanup_signed_part; ++ } ++ ++ if (version != 1) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Unexpected signature version v%d, only v1 supported", ++ version); ++ goto cleanup_signed_part; ++ } ++ ++ /* ++ * digestAlgorithms DigestAlgorithmIdentifiers ++ * ++ * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier ++ * DigestAlgorithmIdentifer is an X.509 AlgorithmIdentifier (10.1.1) ++ * ++ * RFC 4055 s 2.1: ++ * sha256Identifier AlgorithmIdentifier ::= { id-sha256, NULL } ++ * sha512Identifier AlgorithmIdentifier ::= { id-sha512, NULL } ++ * ++ * We only support 1 element in the set, and we do not check parameters atm. ++ */ ++ res = ++ asn1_number_of_elements (signed_part, "digestAlgorithms", &algo_count); ++ if (res != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Error counting number of digest algorithms: %s", ++ asn1_strerror (res)); ++ goto cleanup_signed_part; ++ } ++ ++ if (algo_count != 1) ++ { ++ err = ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ "Only 1 digest algorithm is supported"); ++ goto cleanup_signed_part; ++ } ++ ++ res = ++ asn1_read_value (signed_part, "digestAlgorithms.?1.algorithm", algo_oid, ++ &algo_oid_size); ++ if (res != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Error reading digest algorithm: %s", ++ asn1_strerror (res)); ++ goto cleanup_signed_part; ++ } ++ ++ if (grub_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0) ++ { ++ msg->hash = grub_crypto_lookup_md_by_name ("sha512"); ++ } ++ else if (grub_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0) ++ { ++ msg->hash = grub_crypto_lookup_md_by_name ("sha256"); ++ } ++ else ++ { ++ err = ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ "Only SHA-256 and SHA-512 hashes are supported, found OID %s", ++ algo_oid); ++ goto cleanup_signed_part; ++ } ++ ++ if (!msg->hash) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Hash algorithm for OID %s not loaded", algo_oid); ++ goto cleanup_signed_part; ++ } ++ ++ /* ++ * We ignore the certificates, but we don't permit CRLs. ++ * A CRL entry might be revoking the certificate we're using, and we have ++ * no way of dealing with that at the moment. ++ */ ++ res = asn1_read_value (signed_part, "crls", NULL, &crls_size); ++ if (res != ASN1_ELEMENT_NOT_FOUND) ++ { ++ err = ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ "PKCS#7 messages with embedded CRLs are not supported"); ++ goto cleanup_signed_part; ++ } ++ ++ /* read the signature */ ++ result_buf = ++ grub_asn1_allocate_and_read (signed_part, "signerInfos.?1.signature", ++ "signature data", &result_size); ++ if (!result_buf) ++ { ++ err = grub_errno; ++ goto cleanup_signed_part; ++ } ++ ++ gcry_err = ++ gcry_mpi_scan (&(msg->sig_mpi), GCRYMPI_FMT_USG, result_buf, result_size, ++ NULL); ++ if (gcry_err != GPG_ERR_NO_ERROR) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Error loading signature into MPI structure: %d", ++ gcry_err); ++ goto cleanup_result; ++ } ++ ++cleanup_result: ++ grub_free (result_buf); ++cleanup_signed_part: ++ asn1_delete_structure (&signed_part); ++ ++ return err; ++} ++ ++grub_err_t ++parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size, ++ struct pkcs7_signedData *msg) ++{ ++ int res; ++ asn1_node content_info; ++ grub_err_t err = GRUB_ERR_NONE; ++ char content_oid[MAX_OID_LEN]; ++ grub_uint8_t *content; ++ int content_size; ++ int content_oid_size = sizeof (content_oid); ++ int size; ++ ++ if (data_size > GRUB_INT_MAX) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ "Cannot parse a PKCS#7 message where data size > INT_MAX"); ++ size = (int) data_size; ++ ++ res = asn1_create_element (_gnutls_pkix_asn, ++ "PKIX1.pkcs-7-ContentInfo", &content_info); ++ if (res != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for PKCS#7 data: %s", ++ asn1_strerror (res)); ++ } ++ ++ res = asn1_der_decoding2 (&content_info, sigbuf, &size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (res != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Error decoding PKCS#7 message DER: %s", asn1_error); ++ goto cleanup; ++ } ++ ++ /* ++ * ContentInfo ::= SEQUENCE { ++ * contentType ContentType, ++ * content [0] EXPLICIT ANY DEFINED BY contentType } ++ * ++ * ContentType ::= OBJECT IDENTIFIER ++ */ ++ res = ++ asn1_read_value (content_info, "contentType", content_oid, ++ &content_oid_size); ++ if (res != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Error reading PKCS#7 content type: %s", ++ asn1_strerror (res)); ++ goto cleanup; ++ } ++ ++ /* OID for SignedData defined in 5.1 */ ++ if (grub_strncmp (signedData_oid, content_oid, content_oid_size) != 0) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_SIGNATURE, ++ "Unexpected content type in PKCS#7 message: OID %s", ++ content_oid); ++ goto cleanup; ++ } ++ ++ content = ++ grub_asn1_allocate_and_read (content_info, "content", ++ "PKCS#7 message content", &content_size); ++ if (!content) ++ { ++ err = grub_errno; ++ goto cleanup; ++ } ++ ++ err = process_content (content, content_size, msg); ++ grub_free (content); ++ ++cleanup: ++ asn1_delete_structure (&content_info); ++ return err; ++} ++ ++/* ++ * Release all the storage associated with the PKCS#7 message. ++ * If the caller dynamically allocated the message, it must free it. ++ */ ++void ++pkcs7_signedData_release (struct pkcs7_signedData *msg) ++{ ++ gcry_mpi_release (msg->sig_mpi); ++} +diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c +new file mode 100644 +index 0000000000..2b38b3670a +--- /dev/null ++++ b/grub-core/commands/appendedsig/x509.c +@@ -0,0 +1,958 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "appendedsig.h" ++ ++static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; ++ ++/* ++ * RFC 3279 2.3.1 RSA Keys ++ */ ++const char *rsaEncryption_oid = "1.2.840.113549.1.1.1"; ++ ++/* ++ * RFC 5280 Appendix A ++ */ ++const char *commonName_oid = "2.5.4.3"; ++ ++/* ++ * RFC 5280 4.2.1.3 Key Usage ++ */ ++const char *keyUsage_oid = "2.5.29.15"; ++ ++/* ++ * RFC 5280 4.2.1.9 Basic Constraints ++ */ ++const char *basicConstraints_oid = "2.5.29.19"; ++ ++/* ++ * RFC 3279 2.3.1 ++ * ++ * The RSA public key MUST be encoded using the ASN.1 type RSAPublicKey: ++ * ++ * RSAPublicKey ::= SEQUENCE { ++ * modulus INTEGER, -- n ++ * publicExponent INTEGER } -- e ++ * ++ * where modulus is the modulus n, and publicExponent is the public ++ * exponent e. ++ */ ++static grub_err_t ++grub_parse_rsa_pubkey (grub_uint8_t * der, int dersize, ++ struct x509_certificate *certificate) ++{ ++ int result; ++ asn1_node spk = ASN1_TYPE_EMPTY; ++ grub_uint8_t *m_data, *e_data; ++ int m_size, e_size; ++ grub_err_t err = GRUB_ERR_NONE; ++ gcry_error_t gcry_err; ++ ++ result = ++ asn1_create_element (_gnutls_gnutls_asn, "GNUTLS.RSAPublicKey", &spk); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Cannot create storage for public key ASN.1 data"); ++ } ++ ++ result = asn1_der_decoding2 (&spk, der, &dersize, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Cannot decode certificate public key DER: %s", ++ asn1_error); ++ goto cleanup; ++ } ++ ++ m_data = ++ grub_asn1_allocate_and_read (spk, "modulus", "RSA modulus", &m_size); ++ if (!m_data) ++ { ++ err = grub_errno; ++ goto cleanup; ++ } ++ ++ e_data = ++ grub_asn1_allocate_and_read (spk, "publicExponent", "RSA public exponent", ++ &e_size); ++ if (!e_data) ++ { ++ err = grub_errno; ++ goto cleanup_m_data; ++ } ++ ++ /* ++ * convert m, e to mpi ++ * ++ * nscanned is not set for FMT_USG, it's only set for FMT_PGP, ++ * so we can't verify it ++ */ ++ gcry_err = ++ gcry_mpi_scan (&certificate->mpis[0], GCRYMPI_FMT_USG, m_data, m_size, ++ NULL); ++ if (gcry_err != GPG_ERR_NO_ERROR) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error loading RSA modulus into MPI structure: %d", ++ gcry_err); ++ goto cleanup_e_data; ++ } ++ ++ gcry_err = ++ gcry_mpi_scan (&certificate->mpis[1], GCRYMPI_FMT_USG, e_data, e_size, ++ NULL); ++ if (gcry_err != GPG_ERR_NO_ERROR) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error loading RSA exponent into MPI structure: %d", ++ gcry_err); ++ goto cleanup_m_mpi; ++ } ++ ++ grub_free (e_data); ++ grub_free (m_data); ++ asn1_delete_structure (&spk); ++ return GRUB_ERR_NONE; ++ ++cleanup_m_mpi: ++ gcry_mpi_release (certificate->mpis[0]); ++cleanup_e_data: ++ grub_free (e_data); ++cleanup_m_data: ++ grub_free (m_data); ++cleanup: ++ asn1_delete_structure (&spk); ++ return err; ++} ++ ++ ++/* ++ * RFC 5280: ++ * SubjectPublicKeyInfo ::= SEQUENCE { ++ * algorithm AlgorithmIdentifier, ++ * subjectPublicKey BIT STRING } ++ * ++ * AlgorithmIdentifiers come from RFC 3279, we are not strictly compilant as we ++ * only support RSA Encryption. ++ */ ++ ++static grub_err_t ++grub_x509_read_subject_public_key (asn1_node asn, ++ struct x509_certificate *results) ++{ ++ int result; ++ grub_err_t err; ++ const char *algo_name = ++ "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm"; ++ const char *params_name = ++ "tbsCertificate.subjectPublicKeyInfo.algorithm.parameters"; ++ const char *pk_name = ++ "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey"; ++ char algo_oid[MAX_OID_LEN]; ++ int algo_size = sizeof (algo_oid); ++ char params_value[2]; ++ int params_size = sizeof (params_value); ++ grub_uint8_t *key_data = NULL; ++ int key_size = 0; ++ unsigned int key_type; ++ ++ /* algorithm: see notes for rsaEncryption_oid */ ++ result = asn1_read_value (asn, algo_name, algo_oid, &algo_size); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading x509 public key algorithm: %s", ++ asn1_strerror (result)); ++ } ++ ++ if (grub_strncmp (algo_oid, rsaEncryption_oid, sizeof (rsaEncryption_oid)) ++ != 0) ++ { ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ "Unsupported x509 public key algorithm: %s", ++ algo_oid); ++ } ++ ++ /* ++ * RFC 3279 2.3.1 ++ * The rsaEncryption OID is intended to be used in the algorithm field ++ * of a value of type AlgorithmIdentifier. The parameters field MUST ++ * have ASN.1 type NULL for this algorithm identifier. ++ */ ++ result = asn1_read_value (asn, params_name, params_value, ¶ms_size); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading x509 public key parameters: %s", ++ asn1_strerror (result)); ++ } ++ ++ if (params_value[0] != ASN1_TAG_NULL) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Invalid x509 public key parameters: expected NULL"); ++ } ++ ++ /* ++ * RFC 3279 2.3.1: The DER encoded RSAPublicKey is the value of the BIT ++ * STRING subjectPublicKey. ++ */ ++ result = asn1_read_value_type (asn, pk_name, NULL, &key_size, &key_type); ++ if (result != ASN1_MEM_ERROR) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading size of x509 public key: %s", ++ asn1_strerror (result)); ++ } ++ if (key_type != ASN1_ETYPE_BIT_STRING) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unexpected ASN.1 type when reading x509 public key: %x", ++ key_type); ++ } ++ ++ /* length is in bits */ ++ key_size = (key_size + 7) / 8; ++ ++ key_data = grub_malloc (key_size); ++ if (!key_data) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Out of memory for x509 public key"); ++ } ++ ++ result = asn1_read_value (asn, pk_name, key_data, &key_size); ++ if (result != ASN1_SUCCESS) ++ { ++ grub_free (key_data); ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading public key data"); ++ } ++ key_size = (key_size + 7) / 8; ++ ++ err = grub_parse_rsa_pubkey (key_data, key_size, results); ++ grub_free (key_data); ++ ++ return err; ++} ++ ++/* Decode a string as defined in Appendix A */ ++static grub_err_t ++decode_string (char *der, int der_size, char **string, ++ grub_size_t * string_size) ++{ ++ asn1_node strasn; ++ int result; ++ char *choice; ++ int choice_size = 0; ++ int tmp_size = 0; ++ grub_err_t err = GRUB_ERR_NONE; ++ ++ result = ++ asn1_create_element (_gnutls_pkix_asn, "PKIX1.DirectoryString", &strasn); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for certificate: %s", ++ asn1_strerror (result)); ++ } ++ ++ result = asn1_der_decoding2 (&strasn, der, &der_size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Could not parse DER for DirectoryString: %s", ++ asn1_error); ++ goto cleanup; ++ } ++ ++ choice = ++ grub_asn1_allocate_and_read (strasn, "", "DirectoryString choice", ++ &choice_size); ++ if (!choice) ++ { ++ err = grub_errno; ++ goto cleanup; ++ } ++ ++ if (grub_strncmp ("utf8String", choice, choice_size)) ++ { ++ err = ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ "Only UTF-8 DirectoryStrings are supported, got %s", ++ choice); ++ goto cleanup_choice; ++ } ++ ++ result = asn1_read_value (strasn, "utf8String", NULL, &tmp_size); ++ if (result != ASN1_MEM_ERROR) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading size of UTF-8 string: %s", ++ asn1_strerror (result)); ++ goto cleanup_choice; ++ } ++ ++ /* read size does not include trailing null */ ++ tmp_size++; ++ ++ *string = grub_malloc (tmp_size); ++ if (!*string) ++ { ++ err = ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Cannot allocate memory for DirectoryString contents"); ++ goto cleanup_choice; ++ } ++ ++ result = asn1_read_value (strasn, "utf8String", *string, &tmp_size); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading out UTF-8 string in DirectoryString: %s", ++ asn1_strerror (result)); ++ grub_free (*string); ++ goto cleanup_choice; ++ } ++ *string_size = tmp_size + 1; ++ (*string)[tmp_size] = '\0'; ++ ++cleanup_choice: ++ grub_free (choice); ++cleanup: ++ asn1_delete_structure (&strasn); ++ return err; ++} ++ ++/* ++ * TBSCertificate ::= SEQUENCE { ++ * version [0] EXPLICIT Version DEFAULT v1, ++ * ... ++ * ++ * Version ::= INTEGER { v1(0), v2(1), v3(2) } ++ */ ++static grub_err_t ++check_version (asn1_node certificate) ++{ ++ int rc; ++ const char *name = "tbsCertificate.version"; ++ grub_uint8_t version; ++ int len = 1; ++ ++ rc = asn1_read_value (certificate, name, &version, &len); ++ ++ /* require version 3 */ ++ if (rc != ASN1_SUCCESS || len != 1) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading certificate version"); ++ ++ if (version != 0x02) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Invalid x509 certificate version, expected v3 (0x02), got 0x%02x", ++ version); ++ ++ return GRUB_ERR_NONE; ++} ++ ++/* ++ * This is an X.501 Name, which is complex. ++ * ++ * For simplicity, we extract only the CN. ++ */ ++static grub_err_t ++read_name (asn1_node asn, const char *name_path, char **name, ++ grub_size_t * name_size) ++{ ++ int seq_components, set_components; ++ int result; ++ int i, j; ++ char *top_path, *set_path, *type_path, *val_path; ++ char type[MAX_OID_LEN]; ++ int type_len = sizeof (type); ++ int string_size = 0; ++ char *string_der; ++ grub_err_t err; ++ ++ *name = NULL; ++ ++ top_path = grub_xasprintf ("%s.rdnSequence", name_path); ++ if (!top_path) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not allocate memory for %s name parsing path", ++ name_path); ++ ++ result = asn1_number_of_elements (asn, top_path, &seq_components); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error counting name components: %s", ++ asn1_strerror (result)); ++ goto cleanup; ++ } ++ ++ for (i = 1; i <= seq_components; i++) ++ { ++ set_path = grub_xasprintf ("%s.?%d", top_path, i); ++ if (!set_path) ++ { ++ err = ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not allocate memory for %s name set parsing path", ++ name_path); ++ goto cleanup_set; ++ } ++ /* this brings us, hopefully, to a set */ ++ result = asn1_number_of_elements (asn, set_path, &set_components); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error counting name sub-components components (element %d): %s", ++ i, asn1_strerror (result)); ++ goto cleanup_set; ++ } ++ for (j = 1; j <= set_components; j++) ++ { ++ type_path = grub_xasprintf ("%s.?%d.?%d.type", top_path, i, j); ++ if (!type_path) ++ { ++ err = ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not allocate memory for %s name component type path", ++ name_path); ++ goto cleanup_set; ++ } ++ type_len = sizeof (type); ++ result = asn1_read_value (asn, type_path, type, &type_len); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading %s name component type: %s", ++ name_path, asn1_strerror (result)); ++ goto cleanup_type; ++ } ++ ++ if (grub_strncmp (type, commonName_oid, type_len) != 0) ++ { ++ grub_free (type_path); ++ continue; ++ } ++ ++ val_path = grub_xasprintf ("%s.?%d.?%d.value", top_path, i, j); ++ if (!val_path) ++ { ++ err = ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not allocate memory for %s name component value path", ++ name_path); ++ goto cleanup_set; ++ } ++ ++ string_der = ++ grub_asn1_allocate_and_read (asn, val_path, name_path, ++ &string_size); ++ if (!string_der) ++ { ++ err = grub_errno; ++ goto cleanup_val_path; ++ } ++ ++ err = decode_string (string_der, string_size, name, name_size); ++ if (err) ++ goto cleanup_string; ++ ++ grub_free (string_der); ++ grub_free (type_path); ++ grub_free (val_path); ++ break; ++ } ++ grub_free (set_path); ++ ++ if (*name) ++ break; ++ } ++ ++ return GRUB_ERR_NONE; ++ ++cleanup_string: ++ grub_free (string_der); ++cleanup_val_path: ++ grub_free (val_path); ++cleanup_type: ++ grub_free (type_path); ++cleanup_set: ++ grub_free (set_path); ++cleanup: ++ grub_free (top_path); ++ return err; ++} ++ ++/* ++ * details here ++ */ ++static grub_err_t ++verify_key_usage (grub_uint8_t * value, int value_size) ++{ ++ asn1_node usageasn; ++ int result; ++ grub_err_t err = GRUB_ERR_NONE; ++ grub_uint8_t usage = 0xff; ++ int usage_size = 1; ++ ++ result = ++ asn1_create_element (_gnutls_pkix_asn, "PKIX1.KeyUsage", &usageasn); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for key usage"); ++ } ++ ++ result = asn1_der_decoding2 (&usageasn, value, &value_size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error parsing DER for Key Usage: %s", asn1_error); ++ goto cleanup; ++ } ++ ++ result = asn1_read_value (usageasn, "", &usage, &usage_size); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading Key Usage value: %s", ++ asn1_strerror (result)); ++ goto cleanup; ++ } ++ ++ /* Only the first bit is permitted to be set */ ++ if (usage != 0x80) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unexpected Key Usage value: %x", ++ usage); ++ goto cleanup; ++ } ++ ++cleanup: ++ asn1_delete_structure (&usageasn); ++ return err; ++} ++ ++/* ++ * BasicConstraints ::= SEQUENCE { ++ * cA BOOLEAN DEFAULT FALSE, ++ * pathLenConstraint INTEGER (0..MAX) OPTIONAL } ++ */ ++static grub_err_t ++verify_basic_constraints (grub_uint8_t * value, int value_size) ++{ ++ asn1_node basicasn; ++ int result; ++ grub_err_t err = GRUB_ERR_NONE; ++ char cA[6]; /* FALSE or TRUE */ ++ int cA_size = sizeof (cA); ++ ++ result = ++ asn1_create_element (_gnutls_pkix_asn, "PKIX1.BasicConstraints", ++ &basicasn); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for Basic Constraints"); ++ } ++ ++ result = asn1_der_decoding2 (&basicasn, value, &value_size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error parsing DER for Basic Constraints: %s", ++ asn1_error); ++ goto cleanup; ++ } ++ ++ result = asn1_read_value (basicasn, "cA", cA, &cA_size); ++ if (result == ASN1_ELEMENT_NOT_FOUND) ++ { ++ /* Not present, default is False, so this is OK */ ++ err = GRUB_ERR_NONE; ++ goto cleanup; ++ } ++ else if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading Basic Constraints cA value: %s", ++ asn1_strerror (result)); ++ goto cleanup; ++ } ++ ++ /* The certificate must not be a CA certificate */ ++ if (grub_strncmp ("FALSE", cA, cA_size) != 0) ++ { ++ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unexpected CA value: %s", ++ cA); ++ goto cleanup; ++ } ++ ++cleanup: ++ asn1_delete_structure (&basicasn); ++ return err; ++} ++ ++ ++/* ++ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension ++ * ++ * Extension ::= SEQUENCE { ++ * extnID OBJECT IDENTIFIER, ++ * critical BOOLEAN DEFAULT FALSE, ++ * extnValue OCTET STRING ++ * -- contains the DER encoding of an ASN.1 value ++ * -- corresponding to the extension type identified ++ * -- by extnID ++ * } ++ * ++ * We require that a certificate: ++ * - contain the Digital Signature usage only ++ * - not be a CA ++ * - MUST not contain any other critical extensions (RFC 5280 s 4.2) ++ */ ++static grub_err_t ++verify_extensions (asn1_node cert) ++{ ++ int result; ++ int ext, num_extensions = 0; ++ int usage_present = 0, constraints_present = 0; ++ char *oid_path, *critical_path, *value_path; ++ char extnID[MAX_OID_LEN]; ++ int extnID_size; ++ grub_err_t err; ++ char critical[6]; /* we get either "TRUE" or "FALSE" */ ++ int critical_size; ++ grub_uint8_t *value; ++ int value_size; ++ ++ result = ++ asn1_number_of_elements (cert, "tbsCertificate.extensions", ++ &num_extensions); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error counting number of extensions: %s", ++ asn1_strerror (result)); ++ } ++ ++ if (num_extensions < 2) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Insufficient number of extensions for certificate, need at least 2, got %d", ++ num_extensions); ++ } ++ ++ for (ext = 1; ext <= num_extensions; ext++) ++ { ++ oid_path = grub_xasprintf ("tbsCertificate.extensions.?%d.extnID", ext); ++ ++ extnID_size = sizeof (extnID); ++ result = asn1_read_value (cert, oid_path, extnID, &extnID_size); ++ if (result != GRUB_ERR_NONE) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading extension OID: %s", ++ asn1_strerror (result)); ++ goto cleanup_oid_path; ++ } ++ ++ critical_path = ++ grub_xasprintf ("tbsCertificate.extensions.?%d.critical", ext); ++ critical_size = sizeof (critical); ++ result = ++ asn1_read_value (cert, critical_path, critical, &critical_size); ++ if (result == ASN1_ELEMENT_NOT_FOUND) ++ { ++ critical[0] = '\0'; ++ } ++ else if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading extension criticality: %s", ++ asn1_strerror (result)); ++ goto cleanup_critical_path; ++ } ++ ++ value_path = ++ grub_xasprintf ("tbsCertificate.extensions.?%d.extnValue", ext); ++ value = ++ grub_asn1_allocate_and_read (cert, value_path, ++ "certificate extension value", ++ &value_size); ++ if (!value) ++ { ++ err = grub_errno; ++ goto cleanup_value_path; ++ } ++ ++ /* ++ * Now we must see if we recognise the OID. ++ * If we have an unrecognised critical extension we MUST bail. ++ */ ++ if (grub_strncmp (keyUsage_oid, extnID, extnID_size) == 0) ++ { ++ err = verify_key_usage (value, value_size); ++ if (err != GRUB_ERR_NONE) ++ { ++ goto cleanup_value; ++ } ++ usage_present++; ++ } ++ else if (grub_strncmp (basicConstraints_oid, extnID, extnID_size) == 0) ++ { ++ err = verify_basic_constraints (value, value_size); ++ if (err != GRUB_ERR_NONE) ++ { ++ goto cleanup_value; ++ } ++ constraints_present++; ++ } ++ else if (grub_strncmp ("TRUE", critical, critical_size) == 0) ++ { ++ /* ++ * per the RFC, we must not process a certificate with ++ * a critical extension we do not understand. ++ */ ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unhandled critical x509 extension with OID %s", ++ extnID); ++ goto cleanup_value; ++ } ++ ++ grub_free (value); ++ grub_free (value_path); ++ grub_free (critical_path); ++ grub_free (oid_path); ++ } ++ ++ if (usage_present != 1) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unexpected number of Key Usage extensions - expected 1, got %d", ++ usage_present); ++ } ++ if (constraints_present != 1) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unexpected number of basic constraints extensions - expected 1, got %d", ++ constraints_present); ++ } ++ return GRUB_ERR_NONE; ++ ++cleanup_value: ++ grub_free (value); ++cleanup_value_path: ++ grub_free (value_path); ++cleanup_critical_path: ++ grub_free (critical_path); ++cleanup_oid_path: ++ grub_free (oid_path); ++ return err; ++} ++ ++/* ++ * Parse a certificate whose DER-encoded form is in @data, of size @data_size. ++ * Return the results in @results, which must point to an allocated x509 certificate. ++ */ ++grub_err_t ++certificate_import (void *data, grub_size_t data_size, ++ struct x509_certificate *results) ++{ ++ int result = 0; ++ asn1_node cert; ++ grub_err_t err; ++ int size; ++ int tmp_size; ++ ++ if (data_size > GRUB_INT_MAX) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ "Cannot parse a certificate where data size > INT_MAX"); ++ size = (int) data_size; ++ ++ result = asn1_create_element (_gnutls_pkix_asn, "PKIX1.Certificate", &cert); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for certificate: %s", ++ asn1_strerror (result)); ++ } ++ ++ result = asn1_der_decoding2 (&cert, data, &size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Could not parse DER for certificate: %s", asn1_error); ++ goto cleanup; ++ } ++ ++ /* ++ * TBSCertificate ::= SEQUENCE { ++ * version [0] EXPLICIT Version DEFAULT v1 ++ */ ++ err = check_version (cert); ++ if (err != GRUB_ERR_NONE) ++ { ++ goto cleanup; ++ } ++ ++ /* ++ * serialNumber CertificateSerialNumber, ++ * ++ * CertificateSerialNumber ::= INTEGER ++ */ ++ results->serial = ++ grub_asn1_allocate_and_read (cert, "tbsCertificate.serialNumber", ++ "certificate serial number", &tmp_size); ++ if (!results->serial) ++ { ++ err = grub_errno; ++ goto cleanup; ++ } ++ /* ++ * It's safe to cast the signed int to an unsigned here, we know ++ * length is non-negative ++ */ ++ results->serial_len = tmp_size; ++ ++ /* ++ * signature AlgorithmIdentifier, ++ * ++ * We don't load the signature or issuer at the moment, ++ * as we don't attempt x509 verification. ++ */ ++ ++ /* ++ * issuer Name, ++ * ++ * The RFC only requires the serial number to be unique within ++ * issuers, so to avoid ambiguity we _technically_ ought to make ++ * this available. ++ */ ++ ++ /* ++ * validity Validity, ++ * ++ * Validity ::= SEQUENCE { ++ * notBefore Time, ++ * notAfter Time } ++ * ++ * We can't validate this reasonably, we have no true time source on several ++ * platforms. For now we do not parse them. ++ */ ++ ++ /* ++ * subject Name, ++ * ++ * This is an X501 name, we parse out just the CN. ++ */ ++ err = ++ read_name (cert, "tbsCertificate.subject", &results->subject, ++ &results->subject_len); ++ if (err != GRUB_ERR_NONE) ++ goto cleanup_serial; ++ ++ /* ++ * TBSCertificate ::= SEQUENCE { ++ * ... ++ * subjectPublicKeyInfo SubjectPublicKeyInfo, ++ * ... ++ */ ++ err = grub_x509_read_subject_public_key (cert, results); ++ if (err != GRUB_ERR_NONE) ++ goto cleanup_name; ++ ++ /* ++ * TBSCertificate ::= SEQUENCE { ++ * ... ++ * extensions [3] EXPLICIT Extensions OPTIONAL ++ * -- If present, version MUST be v3 ++ * } ++ */ ++ ++ err = verify_extensions (cert); ++ if (err != GRUB_ERR_NONE) ++ goto cleanup_name; ++ ++ ++ /* ++ * We do not read or check the signature on the certificate: ++ * as discussed we do not try to validate the certificate but trust ++ * it implictly. ++ */ ++ ++ asn1_delete_structure (&cert); ++ return GRUB_ERR_NONE; ++ ++ ++cleanup_name: ++ grub_free (results->subject); ++cleanup_serial: ++ grub_free (results->serial); ++cleanup: ++ asn1_delete_structure (&cert); ++ return err; ++} ++ ++/* ++ * Release all the storage associated with the x509 certificate. ++ * If the caller dynamically allocated the certificate, it must free it. ++ * The caller is also responsible for maintenance of the linked list. ++ */ ++void ++certificate_release (struct x509_certificate *cert) ++{ ++ grub_free (cert->subject); ++ grub_free (cert->serial); ++ gcry_mpi_release (cert->mpis[0]); ++ gcry_mpi_release (cert->mpis[1]); ++} +diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h +new file mode 100644 +index 0000000000..9792ef3901 +--- /dev/null ++++ b/grub-core/commands/appendedsig/appendedsig.h +@@ -0,0 +1,110 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ ++extern asn1_node _gnutls_gnutls_asn; ++extern asn1_node _gnutls_pkix_asn; ++ ++#define MAX_OID_LEN 32 ++ ++/* ++ * One or more x509 certificates. ++ * ++ * We do limited parsing: extracting only the serial, CN and RSA public key. ++ */ ++struct x509_certificate ++{ ++ struct x509_certificate *next; ++ ++ grub_uint8_t *serial; ++ grub_size_t serial_len; ++ ++ char *subject; ++ grub_size_t subject_len; ++ ++ /* We only support RSA public keys. This encodes [modulus, publicExponent] */ ++ gcry_mpi_t mpis[2]; ++}; ++ ++/* ++ * A PKCS#7 signedData message. ++ * ++ * We make no attempt to match intelligently, so we don't save any info about ++ * the signer. We also support only 1 signerInfo, so we only store a single ++ * MPI for the signature. ++ */ ++struct pkcs7_signedData ++{ ++ const gcry_md_spec_t *hash; ++ gcry_mpi_t sig_mpi; ++}; ++ ++ ++/* Do libtasn1 init */ ++int asn1_init (void); ++ ++/* ++ * Import a DER-encoded certificate at 'data', of size 'size'. ++ * ++ * Place the results into 'results', which must be already allocated. ++ */ ++grub_err_t ++certificate_import (void *data, grub_size_t size, ++ struct x509_certificate *results); ++ ++/* ++ * Release all the storage associated with the x509 certificate. ++ * If the caller dynamically allocated the certificate, it must free it. ++ * The caller is also responsible for maintenance of the linked list. ++ */ ++void certificate_release (struct x509_certificate *cert); ++ ++/* ++ * Parse a PKCS#7 message, which must be a signedData message. ++ * ++ * The message must be in 'sigbuf' and of size 'data_size'. The result is ++ * placed in 'msg', which must already be allocated. ++ */ ++grub_err_t ++parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size, ++ struct pkcs7_signedData *msg); ++ ++/* ++ * Release all the storage associated with the PKCS#7 message. ++ * If the caller dynamically allocated the message, it must free it. ++ */ ++void pkcs7_signedData_release (struct pkcs7_signedData *msg); ++ ++/* ++ * Read a value from an ASN1 node, allocating memory to store it. ++ * ++ * It will work for anything where the size libtasn1 returns is right: ++ * - Integers ++ * - Octet strings ++ * - DER encoding of other structures ++ * It will _not_ work for things where libtasn1 size requires adjustment: ++ * - Strings that require an extra NULL byte at the end ++ * - Bit strings because libtasn1 returns the length in bits, not bytes. ++ * ++ * If the function returns a non-NULL value, the caller must free it. ++ */ ++void *grub_asn1_allocate_and_read (asn1_node node, const char *name, ++ const char *friendly_name, ++ int *content_size); diff --git a/SOURCES/0169-grub-install-disable-support-for-EFI-platforms.patch b/SOURCES/0169-grub-install-disable-support-for-EFI-platforms.patch deleted file mode 100644 index 41003e2..0000000 --- a/SOURCES/0169-grub-install-disable-support-for-EFI-platforms.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jan Hlavac -Date: Fri, 20 Nov 2020 23:51:47 +0100 -Subject: [PATCH] grub-install: disable support for EFI platforms - -For each platform, GRUB is shipped as a kernel image and a set of -modules. These files are then used by the grub-install utility to -install GRUB on a specific device. However, in order to support UEFI -Secure Boot, the resulting EFI binary must be signed by a recognized -private key. For this reason, for EFI platforms, most distributions also -ship prebuilt EFI binaries signed by a distribution-specific private -key. In this case, however, the grub-install utility should not be used -because it would overwrite the signed EFI binary. - -The current fix is suboptimal because it preserves all EFI-related code. -A better solution could be to modularize the code and provide a -build-time option. - -Resolves: rhbz#1737444 - -Signed-off-by: Jan Hlavac ---- - util/grub-install.c | 37 ++++++++++++++++--------------------- - docs/grub.texi | 7 +++++++ - util/grub-install.8 | 4 +++- - 3 files changed, 26 insertions(+), 22 deletions(-) - -diff --git a/util/grub-install.c b/util/grub-install.c -index a2bec7446cb..5babc7af551 100644 ---- a/util/grub-install.c -+++ b/util/grub-install.c -@@ -899,6 +899,22 @@ main (int argc, char *argv[]) - - platform = grub_install_get_target (grub_install_source_directory); - -+ switch (platform) -+ { -+ case GRUB_INSTALL_PLATFORM_ARM_EFI: -+ case GRUB_INSTALL_PLATFORM_ARM64_EFI: -+ case GRUB_INSTALL_PLATFORM_I386_EFI: -+ case GRUB_INSTALL_PLATFORM_IA64_EFI: -+ case GRUB_INSTALL_PLATFORM_X86_64_EFI: -+ is_efi = 1; -+ grub_util_error (_("this utility cannot be used for EFI platforms" -+ " because it does not support UEFI Secure Boot")); -+ break; -+ default: -+ is_efi = 0; -+ break; -+ } -+ - { - char *platname = grub_install_get_platform_name (platform); - fprintf (stderr, _("Installing for %s platform.\n"), platname); -@@ -1011,28 +1027,7 @@ main (int argc, char *argv[]) - grub_hostfs_init (); - grub_host_init (); - -- switch (platform) -- { -- case GRUB_INSTALL_PLATFORM_I386_EFI: -- case GRUB_INSTALL_PLATFORM_X86_64_EFI: -- case GRUB_INSTALL_PLATFORM_ARM_EFI: -- case GRUB_INSTALL_PLATFORM_ARM64_EFI: -- case GRUB_INSTALL_PLATFORM_RISCV32_EFI: -- case GRUB_INSTALL_PLATFORM_RISCV64_EFI: -- case GRUB_INSTALL_PLATFORM_IA64_EFI: -- is_efi = 1; -- break; -- default: -- is_efi = 0; -- break; -- -- /* pacify warning. */ -- case GRUB_INSTALL_PLATFORM_MAX: -- break; -- } -- - /* Find the EFI System Partition. */ -- - if (is_efi) - { - grub_fs_t fs; -diff --git a/docs/grub.texi b/docs/grub.texi -index 04ed6ac1f07..4870faaa00a 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -6509,6 +6509,13 @@ grub2-install @var{install_device} - The device name @var{install_device} is an OS device name or a GRUB - device name. - -+In order to support UEFI Secure Boot, the resulting GRUB EFI binary must -+be signed by a recognized private key. For this reason, for EFI -+platforms, most distributions also ship prebuilt GRUB EFI binaries -+signed by a distribution-specific private key. In this case, however, -+@command{grub2-install} should not be used because it would overwrite -+the signed EFI binary. -+ - @command{grub2-install} accepts the following options: - - @table @option -diff --git a/util/grub-install.8 b/util/grub-install.8 -index 1db89e94b3b..811d441b16c 100644 ---- a/util/grub-install.8 -+++ b/util/grub-install.8 -@@ -1,4 +1,4 @@ --.TH GRUB-INSTALL 1 "Wed Feb 26 2014" -+.TH GRUB-INSTALL 1 "Fri Nov 20 2020" - .SH NAME - \fBgrub-install\fR \(em Install GRUB on a device. - -@@ -31,6 +31,8 @@ - .SH DESCRIPTION - \fBgrub-install\fR installs GRUB onto a device. This includes copying GRUB images into the target directory (generally \fI/boot/grub\fR), and on some platforms may also include installing GRUB onto a boot sector. - -+In order to support UEFI Secure Boot, the resulting GRUB EFI binary must be signed by a recognized private key. For this reason, for EFI platforms, most distributions also ship prebuilt GRUB EFI binaries signed by a distribution-specific private key. In this case, however, the \fBgrub-install\fR utility should not be used because it would overwrite the signed EFI binary. -+ - .SH OPTIONS - .TP - \fB--modules\fR=\fIMODULES\fR\! diff --git a/SOURCES/0170-New-with-debug-timestamps-configure-flag-to-prepend-.patch b/SOURCES/0170-New-with-debug-timestamps-configure-flag-to-prepend-.patch deleted file mode 100644 index 3eb0d00..0000000 --- a/SOURCES/0170-New-with-debug-timestamps-configure-flag-to-prepend-.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Sat, 23 Nov 2019 14:57:41 +0100 -Subject: [PATCH] New --with-debug-timestamps configure flag to prepend debug - traces with absolute and relative timestamp -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Renaud Métrich ---- - configure.ac | 18 ++++++++++++++++++ - grub-core/kern/misc.c | 20 ++++++++++++++++++++ - config.h.in | 1 + - 3 files changed, 39 insertions(+) - -diff --git a/configure.ac b/configure.ac -index 907477a585c..d5d2a28b4ef 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1613,6 +1613,17 @@ else - fi - AC_SUBST([BOOT_TIME_STATS]) - -+AC_ARG_WITH([debug-timestamps], -+ AS_HELP_STRING([--with-debug-timestamps], -+ [prepend debug traces with absolute and relative timestamps])) -+ -+if test x$with_debug_timestamps = xyes; then -+ DEBUG_WITH_TIMESTAMPS=1 -+else -+ DEBUG_WITH_TIMESTAMPS=0 -+fi -+AC_SUBST([DEBUG_WITH_TIMESTAMPS]) -+ - AC_ARG_ENABLE([grub-emu-sdl], - [AS_HELP_STRING([--enable-grub-emu-sdl], - [build and install the `grub-emu' debugging utility with SDL support (default=guessed)])]) -@@ -2200,6 +2211,7 @@ AM_CONDITIONAL([COND_APPLE_LINKER], [test x$TARGET_APPLE_LINKER = x1]) - AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) - AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1]) - AM_CONDITIONAL([COND_ENABLE_BOOT_TIME_STATS], [test x$BOOT_TIME_STATS = x1]) -+AM_CONDITIONAL([COND_DEBUG_WITH_TIMESTAMPS], [test x$DEBUG_WITH_TIMESTAMPS = x1]) - - AM_CONDITIONAL([COND_HAVE_CXX], [test x$HAVE_CXX = xyes]) - -@@ -2295,6 +2307,12 @@ else - echo With boot time statistics: No - fi - -+if [ x"$with_debug_timestamps" = xyes ]; then -+echo Debug traces with timestamps: Yes -+else -+echo Debug traces with timestamps: No -+fi -+ - if [ x"$efiemu_excuse" = x ]; then - echo efiemu runtime: Yes - else -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index 578bf51a5fc..9f54b6b7d2d 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -25,6 +25,9 @@ - #include - #include - #include -+#if DEBUG_WITH_TIMESTAMPS -+#include -+#endif - - union printf_arg - { -@@ -192,9 +195,26 @@ grub_real_dprintf (const char *file, const int line, const char *condition, - const char *fmt, ...) - { - va_list args; -+#if DEBUG_WITH_TIMESTAMPS -+ static long unsigned int last_time = 0; -+ static int last_had_cr = 1; -+#endif - - if (grub_debug_enabled (condition)) - { -+#if DEBUG_WITH_TIMESTAMPS -+ /* Don't print timestamp if last printed message isn't terminated yet */ -+ if (last_had_cr) { -+ long unsigned int tmabs = (long unsigned int) grub_get_time_ms(); -+ long unsigned int tmrel = tmabs - last_time; -+ last_time = tmabs; -+ grub_printf ("%3lu.%03lus +%2lu.%03lus ", tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000); -+ } -+ if (fmt[grub_strlen(fmt)-1] == '\n') -+ last_had_cr = 1; -+ else -+ last_had_cr = 0; -+#endif - grub_printf ("%s:%d: ", file, line); - va_start (args, fmt); - grub_vprintf (fmt, args); -diff --git a/config.h.in b/config.h.in -index c7e316f0f1f..c80e3e0aba3 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -12,6 +12,7 @@ - /* Define to 1 to enable disk cache statistics. */ - #define DISK_CACHE_STATS @DISK_CACHE_STATS@ - #define BOOT_TIME_STATS @BOOT_TIME_STATS@ -+#define DEBUG_WITH_TIMESTAMPS @DEBUG_WITH_TIMESTAMPS@ - - /* We don't need those. */ - #define MINILZO_CFG_SKIP_LZO_PTR 1 diff --git a/SOURCES/0170-appended-signatures-support-verifying-appended-signa.patch b/SOURCES/0170-appended-signatures-support-verifying-appended-signa.patch new file mode 100644 index 0000000..9e90d3b --- /dev/null +++ b/SOURCES/0170-appended-signatures-support-verifying-appended-signa.patch @@ -0,0 +1,718 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 30 Jul 2020 01:35:43 +1000 +Subject: [PATCH] appended signatures: support verifying appended signatures + +Building on the parsers and the ability to embed x509 certificates, as +well as the existing gcrypt functionality, add a module for verifying +appended signatures. + +This includes a verifier that requires that Linux kernels and grub modules +have appended signatures, and commands to manage the list of trusted +certificates for verification. + +Verification must be enabled by setting check_appended_signatures. If +GRUB is locked down when the module is loaded, verification will be +enabled and locked automatically. + +As with the PGP verifier, it is not a complete secure-boot solution: +other mechanisms, such as a password or lockdown, must be used to ensure +that a user cannot drop to the grub shell and disable verification. + +Signed-off-by: Daniel Axtens +[pjones: fix missing format specifier] +Signed-off-by: Robbie Harwood +--- + grub-core/Makefile.core.def | 12 + + grub-core/commands/appendedsig/appendedsig.c | 645 +++++++++++++++++++++++++++ + include/grub/file.h | 2 + + 3 files changed, 659 insertions(+) + create mode 100644 grub-core/commands/appendedsig/appendedsig.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index a32e6ada59..6404384d90 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -980,6 +980,18 @@ module = { + cppflags = '-I$(srcdir)/lib/posix_wrap'; + }; + ++module = { ++ name = appendedsig; ++ common = commands/appendedsig/appendedsig.c; ++ common = commands/appendedsig/x509.c; ++ common = commands/appendedsig/pkcs7.c; ++ common = commands/appendedsig/asn1util.c; ++ common = commands/appendedsig/gnutls_asn1_tab.c; ++ common = commands/appendedsig/pkix_asn1_tab.c; ++ cflags = '$(CFLAGS_POSIX)'; ++ cppflags = '-I$(srcdir)/lib/posix_wrap'; ++}; ++ + module = { + name = hdparm; + common = commands/hdparm.c; +diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c +new file mode 100644 +index 0000000000..bf8b18b620 +--- /dev/null ++++ b/grub-core/commands/appendedsig/appendedsig.c +@@ -0,0 +1,645 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020-2021 IBM Corporation. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "appendedsig.h" ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++const char magic[] = "~Module signature appended~\n"; ++ ++/* ++ * This structure is extracted from scripts/sign-file.c in the linux kernel ++ * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible. ++ */ ++struct module_signature ++{ ++ grub_uint8_t algo; /* Public-key crypto algorithm [0] */ ++ grub_uint8_t hash; /* Digest algorithm [0] */ ++ grub_uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */ ++ grub_uint8_t signer_len; /* Length of signer's name [0] */ ++ grub_uint8_t key_id_len; /* Length of key identifier [0] */ ++ grub_uint8_t __pad[3]; ++ grub_uint32_t sig_len; /* Length of signature data */ ++} GRUB_PACKED; ++ ++ ++/* This represents an entire, parsed, appended signature */ ++struct grub_appended_signature ++{ ++ grub_size_t signature_len; /* Length of PKCS#7 data + ++ * metadata + magic */ ++ ++ struct module_signature sig_metadata; /* Module signature metadata */ ++ struct pkcs7_signedData pkcs7; /* Parsed PKCS#7 data */ ++}; ++ ++/* Trusted certificates for verifying appended signatures */ ++struct x509_certificate *grub_trusted_key; ++ ++/* ++ * Force gcry_rsa to be a module dependency. ++ * ++ * If we use grub_crypto_pk_rsa, then then the gcry_rsa module won't be built ++ * in if you add 'appendedsig' to grub-install --modules. You would need to ++ * add 'gcry_rsa' too. That's confusing and seems suboptimal, especially when ++ * we only support RSA. ++ * ++ * Dynamic loading also causes some concerns. We can't load gcry_rsa from the ++ * the filesystem after we install the verifier - we won't be able to verify ++ * it without having it already present. We also shouldn't load it before we ++ * install the verifier, because that would mean it wouldn't be verified - an ++ * attacker could insert any code they wanted into the module. ++ * ++ * So instead, reference the internal symbol from gcry_rsa. That creates a ++ * direct dependency on gcry_rsa, so it will be built in when this module ++ * is built in. Being built in (assuming the core image is itself signed!) ++ * also resolves our concerns about loading from the filesystem. ++ */ ++extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; ++ ++static int check_sigs = 0; ++ ++static const char * ++grub_env_read_sec (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ if (check_sigs == 2) ++ return "forced"; ++ else if (check_sigs == 1) ++ return "enforce"; ++ else ++ return "no"; ++} ++ ++static char * ++grub_env_write_sec (struct grub_env_var *var __attribute__((unused)), ++ const char *val) ++{ ++ /* Do not allow the value to be changed if set to forced */ ++ if (check_sigs == 2) ++ return grub_strdup ("forced"); ++ ++ if ((*val == '2') || (*val == 'f')) ++ check_sigs = 2; ++ else if ((*val == '1') || (*val == 'e')) ++ check_sigs = 1; ++ else if ((*val == '0') || (*val == 'n')) ++ check_sigs = 0; ++ ++ return grub_strdup (grub_env_read_sec (NULL, NULL)); ++} ++ ++static grub_err_t ++read_cert_from_file (grub_file_t f, struct x509_certificate *certificate) ++{ ++ grub_err_t err; ++ grub_uint8_t *buf = NULL; ++ grub_ssize_t read_size; ++ grub_off_t total_read_size = 0; ++ grub_off_t file_size = grub_file_size (f); ++ ++ ++ if (file_size == GRUB_FILE_SIZE_UNKNOWN) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("Cannot parse a certificate file of unknown size")); ++ ++ buf = grub_zalloc (file_size); ++ if (!buf) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ N_("Could not allocate buffer for certificate file contents")); ++ ++ while (total_read_size < file_size) ++ { ++ read_size = ++ grub_file_read (f, &buf[total_read_size], ++ file_size - total_read_size); ++ if (read_size < 0) ++ { ++ err = grub_error (GRUB_ERR_READ_ERROR, ++ N_("Error reading certificate file")); ++ goto cleanup_buf; ++ } ++ total_read_size += read_size; ++ } ++ ++ err = certificate_import (buf, total_read_size, certificate); ++ if (err != GRUB_ERR_NONE) ++ goto cleanup_buf; ++ ++ return GRUB_ERR_NONE; ++ ++cleanup_buf: ++ grub_free (buf); ++ return err; ++} ++ ++static grub_err_t ++extract_appended_signature (grub_uint8_t * buf, grub_size_t bufsize, ++ struct grub_appended_signature *sig) ++{ ++ grub_err_t err; ++ grub_size_t pkcs7_size; ++ grub_size_t remaining_len; ++ grub_uint8_t *appsigdata = buf + bufsize - grub_strlen (magic); ++ ++ if (bufsize < grub_strlen (magic)) ++ return grub_error (GRUB_ERR_BAD_SIGNATURE, ++ N_("File too short for signature magic")); ++ ++ if (grub_memcmp (appsigdata, (grub_uint8_t *) magic, grub_strlen (magic))) ++ return grub_error (GRUB_ERR_BAD_SIGNATURE, ++ N_("Missing or invalid signature magic")); ++ ++ remaining_len = bufsize - grub_strlen (magic); ++ ++ if (remaining_len < sizeof (struct module_signature)) ++ return grub_error (GRUB_ERR_BAD_SIGNATURE, ++ N_("File too short for signature metadata")); ++ ++ appsigdata -= sizeof (struct module_signature); ++ ++ /* extract the metadata */ ++ grub_memcpy (&(sig->sig_metadata), appsigdata, ++ sizeof (struct module_signature)); ++ ++ remaining_len -= sizeof (struct module_signature); ++ ++ if (sig->sig_metadata.id_type != 2) ++ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("Wrong signature type")); ++ ++#ifdef GRUB_TARGET_WORDS_BIGENDIAN ++ pkcs7_size = sig->sig_metadata.sig_len; ++#else ++ pkcs7_size = __builtin_bswap32 (sig->sig_metadata.sig_len); ++#endif ++ ++ if (pkcs7_size > remaining_len) ++ return grub_error (GRUB_ERR_BAD_SIGNATURE, ++ N_("File too short for PKCS#7 message")); ++ ++ grub_dprintf ("appendedsig", "sig len %" PRIuGRUB_SIZE "\n", pkcs7_size); ++ ++ sig->signature_len = ++ grub_strlen (magic) + sizeof (struct module_signature) + pkcs7_size; ++ ++ /* rewind pointer and parse pkcs7 data */ ++ appsigdata -= pkcs7_size; ++ ++ err = parse_pkcs7_signedData (appsigdata, pkcs7_size, &sig->pkcs7); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_verify_appended_signature (grub_uint8_t * buf, grub_size_t bufsize) ++{ ++ grub_err_t err = GRUB_ERR_NONE; ++ grub_size_t datasize; ++ void *context; ++ unsigned char *hash; ++ gcry_mpi_t hashmpi; ++ gcry_err_code_t rc; ++ struct x509_certificate *pk; ++ struct grub_appended_signature sig; ++ ++ if (!grub_trusted_key) ++ return grub_error (GRUB_ERR_BAD_SIGNATURE, ++ N_("No trusted keys to verify against")); ++ ++ err = extract_appended_signature (buf, bufsize, &sig); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ ++ datasize = bufsize - sig.signature_len; ++ ++ context = grub_zalloc (sig.pkcs7.hash->contextsize); ++ if (!context) ++ return grub_errno; ++ ++ sig.pkcs7.hash->init (context); ++ sig.pkcs7.hash->write (context, buf, datasize); ++ sig.pkcs7.hash->final (context); ++ hash = sig.pkcs7.hash->read (context); ++ grub_dprintf ("appendedsig", ++ "data size %" PRIxGRUB_SIZE ", hash %02x%02x%02x%02x...\n", ++ datasize, hash[0], hash[1], hash[2], hash[3]); ++ ++ err = GRUB_ERR_BAD_SIGNATURE; ++ for (pk = grub_trusted_key; pk; pk = pk->next) ++ { ++ rc = grub_crypto_rsa_pad (&hashmpi, hash, sig.pkcs7.hash, pk->mpis[0]); ++ if (rc) ++ { ++ err = grub_error (GRUB_ERR_BAD_SIGNATURE, ++ N_("Error padding hash for RSA verification: %d"), ++ rc); ++ goto cleanup; ++ } ++ ++ rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &sig.pkcs7.sig_mpi, ++ pk->mpis, NULL, NULL); ++ gcry_mpi_release (hashmpi); ++ ++ if (rc == 0) ++ { ++ grub_dprintf ("appendedsig", "verify with key '%s' succeeded\n", ++ pk->subject); ++ err = GRUB_ERR_NONE; ++ break; ++ } ++ ++ grub_dprintf ("appendedsig", "verify with key '%s' failed with %d\n", ++ pk->subject, rc); ++ } ++ ++ /* If we didn't verify, provide a neat message */ ++ if (err != GRUB_ERR_NONE) ++ err = grub_error (GRUB_ERR_BAD_SIGNATURE, ++ N_("Failed to verify signature against a trusted key")); ++ ++cleanup: ++ grub_free (context); ++ pkcs7_signedData_release (&sig.pkcs7); ++ ++ return err; ++} ++ ++static grub_err_t ++grub_cmd_verify_signature (grub_command_t cmd __attribute__((unused)), ++ int argc, char **args) ++{ ++ grub_file_t f; ++ grub_err_t err = GRUB_ERR_NONE; ++ grub_uint8_t *data; ++ grub_ssize_t read_size; ++ grub_off_t file_size, total_read_size = 0; ++ ++ if (argc < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); ++ ++ grub_dprintf ("appendedsig", "verifying %s\n", args[0]); ++ ++ f = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE); ++ if (!f) ++ { ++ err = grub_errno; ++ goto cleanup; ++ } ++ ++ file_size = grub_file_size (f); ++ if (file_size == GRUB_FILE_SIZE_UNKNOWN) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("Cannot verify the signature of a file of unknown size")); ++ ++ data = grub_malloc (file_size); ++ if (!data) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ N_("Could not allocate data buffer size %" ++ PRIuGRUB_UINT64_T " for verification"), file_size); ++ ++ while (total_read_size < file_size) ++ { ++ read_size = ++ grub_file_read (f, &data[total_read_size], ++ file_size - total_read_size); ++ if (read_size < 0) ++ { ++ err = grub_error (GRUB_ERR_READ_ERROR, ++ N_("Error reading file to verify")); ++ goto cleanup_data; ++ } ++ total_read_size += read_size; ++ } ++ ++ err = grub_verify_appended_signature (data, file_size); ++ ++cleanup_data: ++ grub_free (data); ++cleanup: ++ if (f) ++ grub_file_close (f); ++ return err; ++} ++ ++static grub_err_t ++grub_cmd_distrust (grub_command_t cmd __attribute__((unused)), ++ int argc, char **args) ++{ ++ unsigned long cert_num, i; ++ struct x509_certificate *cert, *prev; ++ ++ if (argc != 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("One argument expected")); ++ ++ grub_errno = GRUB_ERR_NONE; ++ cert_num = grub_strtoul (args[0], NULL, 10); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ ++ if (cert_num < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("Certificate number too small - numbers start at 1")); ++ ++ if (cert_num == 1) ++ { ++ cert = grub_trusted_key; ++ grub_trusted_key = cert->next; ++ ++ certificate_release (cert); ++ grub_free (cert); ++ return GRUB_ERR_NONE; ++ } ++ i = 2; ++ prev = grub_trusted_key; ++ cert = grub_trusted_key->next; ++ while (cert) ++ { ++ if (i == cert_num) ++ { ++ prev->next = cert->next; ++ certificate_release (cert); ++ grub_free (cert); ++ return GRUB_ERR_NONE; ++ } ++ i++; ++ prev = cert; ++ cert = cert->next; ++ } ++ ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("No certificate number %d found - only %d certificates in the store"), ++ cert_num, i - 1); ++} ++ ++static grub_err_t ++grub_cmd_trust (grub_command_t cmd __attribute__((unused)), ++ int argc, char **args) ++{ ++ grub_file_t certf; ++ struct x509_certificate *cert = NULL; ++ grub_err_t err; ++ ++ if (argc != 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); ++ ++ certf = grub_file_open (args[0], ++ GRUB_FILE_TYPE_CERTIFICATE_TRUST ++ | GRUB_FILE_TYPE_NO_DECOMPRESS); ++ if (!certf) ++ return grub_errno; ++ ++ ++ cert = grub_zalloc (sizeof (struct x509_certificate)); ++ if (!cert) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ N_("Could not allocate memory for certificate")); ++ ++ err = read_cert_from_file (certf, cert); ++ grub_file_close (certf); ++ if (err != GRUB_ERR_NONE) ++ { ++ grub_free (cert); ++ return err; ++ } ++ grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n", ++ cert->subject); ++ ++ cert->next = grub_trusted_key; ++ grub_trusted_key = cert; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_list (grub_command_t cmd __attribute__((unused)), ++ int argc __attribute__((unused)), ++ char **args __attribute__((unused))) ++{ ++ struct x509_certificate *cert; ++ int cert_num = 1; ++ grub_size_t i; ++ ++ for (cert = grub_trusted_key; cert; cert = cert->next) ++ { ++ grub_printf (N_("Certificate %d:\n"), cert_num); ++ ++ grub_printf (N_("\tSerial: ")); ++ for (i = 0; i < cert->serial_len - 1; i++) ++ { ++ grub_printf ("%02x:", cert->serial[i]); ++ } ++ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]); ++ ++ grub_printf ("\tCN: %s\n\n", cert->subject); ++ cert_num++; ++ ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++appendedsig_init (grub_file_t io __attribute__((unused)), ++ enum grub_file_type type, ++ void **context __attribute__((unused)), ++ enum grub_verify_flags *flags) ++{ ++ if (!check_sigs) ++ { ++ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; ++ return GRUB_ERR_NONE; ++ } ++ ++ switch (type & GRUB_FILE_TYPE_MASK) ++ { ++ case GRUB_FILE_TYPE_CERTIFICATE_TRUST: ++ /* ++ * This is a certificate to add to trusted keychain. ++ * ++ * This needs to be verified or blocked. Ideally we'd write an x509 ++ * verifier, but we lack the hubris required to take this on. Instead, ++ * require that it have an appended signature. ++ */ ++ ++ /* Fall through */ ++ ++ case GRUB_FILE_TYPE_LINUX_KERNEL: ++ case GRUB_FILE_TYPE_GRUB_MODULE: ++ /* ++ * Appended signatures are only defined for ELF binaries. ++ * Out of an abundance of caution, we only verify Linux kernels and ++ * GRUB modules at this point. ++ */ ++ *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; ++ return GRUB_ERR_NONE; ++ ++ case GRUB_FILE_TYPE_ACPI_TABLE: ++ case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: ++ /* ++ * It is possible to use appended signature verification without ++ * lockdown - like the PGP verifier. When combined with an embedded ++ * config file in a signed grub binary, this could still be a meaningful ++ * secure-boot chain - so long as it isn't subverted by something like a ++ * rouge ACPI table or DT image. Defer them explicitly. ++ */ ++ *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; ++ return GRUB_ERR_NONE; ++ ++ default: ++ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; ++ return GRUB_ERR_NONE; ++ } ++} ++ ++static grub_err_t ++appendedsig_write (void *ctxt __attribute__((unused)), ++ void *buf, grub_size_t size) ++{ ++ return grub_verify_appended_signature (buf, size); ++} ++ ++struct grub_file_verifier grub_appendedsig_verifier = { ++ .name = "appendedsig", ++ .init = appendedsig_init, ++ .write = appendedsig_write, ++}; ++ ++static grub_ssize_t ++pseudo_read (struct grub_file *file, char *buf, grub_size_t len) ++{ ++ grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len); ++ return len; ++} ++ ++/* Filesystem descriptor. */ ++static struct grub_fs pseudo_fs = { ++ .name = "pseudo", ++ .fs_read = pseudo_read ++}; ++ ++static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust; ++ ++GRUB_MOD_INIT (appendedsig) ++{ ++ int rc; ++ struct grub_module_header *header; ++ ++ /* If in lockdown, immediately enter forced mode */ ++ if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) ++ check_sigs = 2; ++ ++ grub_trusted_key = NULL; ++ ++ grub_register_variable_hook ("check_appended_signatures", ++ grub_env_read_sec, ++ grub_env_write_sec); ++ grub_env_export ("check_appended_signatures"); ++ ++ rc = asn1_init (); ++ if (rc) ++ grub_fatal ("Error initing ASN.1 data structures: %d: %s\n", rc, ++ asn1_strerror (rc)); ++ ++ FOR_MODULES (header) ++ { ++ struct grub_file pseudo_file; ++ struct x509_certificate *pk = NULL; ++ grub_err_t err; ++ ++ /* Not an ELF module, skip. */ ++ if (header->type != OBJ_TYPE_X509_PUBKEY) ++ continue; ++ ++ grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); ++ pseudo_file.fs = &pseudo_fs; ++ pseudo_file.size = header->size - sizeof (struct grub_module_header); ++ pseudo_file.data = (char *) header + sizeof (struct grub_module_header); ++ ++ grub_dprintf ("appendedsig", ++ "Found an x509 key, size=%" PRIuGRUB_UINT64_T "\n", ++ pseudo_file.size); ++ ++ pk = grub_zalloc (sizeof (struct x509_certificate)); ++ if (!pk) ++ { ++ grub_fatal ("Out of memory loading initial certificates"); ++ } ++ ++ err = read_cert_from_file (&pseudo_file, pk); ++ if (err != GRUB_ERR_NONE) ++ grub_fatal ("Error loading initial key: %s", grub_errmsg); ++ ++ grub_dprintf ("appendedsig", "loaded certificate CN='%s'\n", pk->subject); ++ ++ pk->next = grub_trusted_key; ++ grub_trusted_key = pk; ++ } ++ ++ cmd_trust = ++ grub_register_command ("trust_certificate", grub_cmd_trust, ++ N_("X509_CERTIFICATE"), ++ N_("Add X509_CERTIFICATE to trusted certificates.")); ++ cmd_list = ++ grub_register_command ("list_certificates", grub_cmd_list, 0, ++ N_("Show the list of trusted x509 certificates.")); ++ cmd_verify = ++ grub_register_command ("verify_appended", grub_cmd_verify_signature, ++ N_("FILE"), ++ N_("Verify FILE against the trusted x509 certificates.")); ++ cmd_distrust = ++ grub_register_command ("distrust_certificate", grub_cmd_distrust, ++ N_("CERT_NUMBER"), ++ N_("Remove CERT_NUMBER (as listed by list_certificates) from trusted certificates.")); ++ ++ grub_verifier_register (&grub_appendedsig_verifier); ++ grub_dl_set_persistent (mod); ++} ++ ++GRUB_MOD_FINI (appendedsig) ++{ ++ /* ++ * grub_dl_set_persistent should prevent this from actually running, but ++ * it does still run under emu. ++ */ ++ ++ grub_verifier_unregister (&grub_appendedsig_verifier); ++ grub_unregister_command (cmd_verify); ++ grub_unregister_command (cmd_list); ++ grub_unregister_command (cmd_trust); ++ grub_unregister_command (cmd_distrust); ++} +diff --git a/include/grub/file.h b/include/grub/file.h +index 31567483cc..96827a4f89 100644 +--- a/include/grub/file.h ++++ b/include/grub/file.h +@@ -80,6 +80,8 @@ enum grub_file_type + GRUB_FILE_TYPE_PUBLIC_KEY, + /* File holding public key to add to trused keys. */ + GRUB_FILE_TYPE_PUBLIC_KEY_TRUST, ++ /* File holding x509 certificiate to add to trusted keys. */ ++ GRUB_FILE_TYPE_CERTIFICATE_TRUST, + /* File of which we intend to print a blocklist to the user. */ + GRUB_FILE_TYPE_PRINT_BLOCKLIST, + /* File we intend to use for test loading or testing speed. */ diff --git a/SOURCES/0171-Added-debug-statements-to-grub_disk_open-and-grub_di.patch b/SOURCES/0171-Added-debug-statements-to-grub_disk_open-and-grub_di.patch deleted file mode 100644 index cbb1a38..0000000 --- a/SOURCES/0171-Added-debug-statements-to-grub_disk_open-and-grub_di.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Sat, 23 Nov 2019 15:22:16 +0100 -Subject: [PATCH] Added debug statements to grub_disk_open() and - grub_disk_close() on success -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Renaud Métrich ---- - grub-core/kern/disk.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c -index e1b0e073e09..05a28ab1429 100644 ---- a/grub-core/kern/disk.c -+++ b/grub-core/kern/disk.c -@@ -285,6 +285,8 @@ grub_disk_open (const char *name) - return 0; - } - -+ grub_dprintf ("disk", "Opening `%s' succeeded.\n", name); -+ - return disk; - } - -@@ -292,7 +294,7 @@ void - grub_disk_close (grub_disk_t disk) - { - grub_partition_t part; -- grub_dprintf ("disk", "Closing `%s'.\n", disk->name); -+ grub_dprintf ("disk", "Closing `%s'...\n", disk->name); - - if (disk->dev && disk->dev->disk_close) - (disk->dev->disk_close) (disk); -@@ -306,8 +308,10 @@ grub_disk_close (grub_disk_t disk) - grub_free (disk->partition); - disk->partition = part; - } -+ grub_dprintf ("disk", "Closing `%s' succeeded.\n", disk->name); - grub_free ((void *) disk->name); - grub_free (disk); -+ - } - - /* Small read (less than cache size and not pass across cache unit boundaries). diff --git a/SOURCES/0171-appended-signatures-verification-tests.patch b/SOURCES/0171-appended-signatures-verification-tests.patch new file mode 100644 index 0000000..b39a5af --- /dev/null +++ b/SOURCES/0171-appended-signatures-verification-tests.patch @@ -0,0 +1,897 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 30 Jul 2020 01:31:02 +1000 +Subject: [PATCH] appended signatures: verification tests + +These tests are run through all_functional_test and test a range +of commands and behaviours. + +Signed-off-by: Daniel Axtens +--- + grub-core/Makefile.core.def | 6 + + grub-core/tests/appended_signature_test.c | 281 +++++++++++++++ + grub-core/tests/lib/functional_test.c | 1 + + grub-core/tests/appended_signatures.h | 557 ++++++++++++++++++++++++++++++ + 4 files changed, 845 insertions(+) + create mode 100644 grub-core/tests/appended_signature_test.c + create mode 100644 grub-core/tests/appended_signatures.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 6404384d90..9ea5fb38f1 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2162,6 +2162,12 @@ module = { + common = tests/setjmp_test.c; + }; + ++module = { ++ name = appended_signature_test; ++ common = tests/appended_signature_test.c; ++ common = tests/appended_signatures.h; ++}; ++ + module = { + name = signature_test; + common = tests/signature_test.c; +diff --git a/grub-core/tests/appended_signature_test.c b/grub-core/tests/appended_signature_test.c +new file mode 100644 +index 0000000000..88a485200d +--- /dev/null ++++ b/grub-core/tests/appended_signature_test.c +@@ -0,0 +1,281 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2020 IBM Corporation. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "appended_signatures.h" ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#define DEFINE_TEST_CASE(case_name) \ ++static char * \ ++get_ ## case_name (grub_size_t *sz) \ ++{ \ ++ char *ret; \ ++ *sz = case_name ## _len; \ ++ ret = grub_malloc (*sz); \ ++ if (ret) \ ++ grub_memcpy (ret, case_name, *sz); \ ++ return ret; \ ++} \ ++\ ++static struct grub_procfs_entry case_name ## _entry = \ ++{ \ ++ .name = #case_name, \ ++ .get_contents = get_ ## case_name \ ++} ++ ++#define DO_TEST(case_name, is_valid) \ ++{ \ ++ grub_procfs_register (#case_name, &case_name ## _entry); \ ++ do_verify ("(proc)/" #case_name, is_valid); \ ++ grub_procfs_unregister (&case_name ## _entry); \ ++} ++ ++ ++DEFINE_TEST_CASE (hi_signed); ++DEFINE_TEST_CASE (hi_signed_sha256); ++DEFINE_TEST_CASE (hj_signed); ++DEFINE_TEST_CASE (short_msg); ++DEFINE_TEST_CASE (unsigned_msg); ++DEFINE_TEST_CASE (hi_signed_2nd); ++ ++static char * ++get_certificate_der (grub_size_t * sz) ++{ ++ char *ret; ++ *sz = certificate_der_len; ++ ret = grub_malloc (*sz); ++ if (ret) ++ grub_memcpy (ret, certificate_der, *sz); ++ return ret; ++} ++ ++static struct grub_procfs_entry certificate_der_entry = { ++ .name = "certificate.der", ++ .get_contents = get_certificate_der ++}; ++ ++static char * ++get_certificate2_der (grub_size_t * sz) ++{ ++ char *ret; ++ *sz = certificate2_der_len; ++ ret = grub_malloc (*sz); ++ if (ret) ++ grub_memcpy (ret, certificate2_der, *sz); ++ return ret; ++} ++ ++static struct grub_procfs_entry certificate2_der_entry = { ++ .name = "certificate2.der", ++ .get_contents = get_certificate2_der ++}; ++ ++static char * ++get_certificate_printable_der (grub_size_t * sz) ++{ ++ char *ret; ++ *sz = certificate_printable_der_len; ++ ret = grub_malloc (*sz); ++ if (ret) ++ grub_memcpy (ret, certificate_printable_der, *sz); ++ return ret; ++} ++ ++static struct grub_procfs_entry certificate_printable_der_entry = { ++ .name = "certificate_printable.der", ++ .get_contents = get_certificate_printable_der ++}; ++ ++ ++static void ++do_verify (const char *f, int is_valid) ++{ ++ grub_command_t cmd; ++ char *args[] = { (char *) f, NULL }; ++ grub_err_t err; ++ ++ cmd = grub_command_find ("verify_appended"); ++ if (!cmd) ++ { ++ grub_test_assert (0, "can't find command `%s'", "verify_appended"); ++ return; ++ } ++ err = (cmd->func) (cmd, 1, args); ++ if (is_valid) ++ { ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "verification of %s failed: %d: %s", f, grub_errno, ++ grub_errmsg); ++ } ++ else ++ { ++ grub_test_assert (err == GRUB_ERR_BAD_SIGNATURE, ++ "verification of %s unexpectedly succeeded", f); ++ } ++ grub_errno = GRUB_ERR_NONE; ++ ++} ++ ++static void ++appended_signature_test (void) ++{ ++ grub_command_t cmd_trust, cmd_distrust; ++ char *trust_args[] = { (char *) "(proc)/certificate.der", NULL }; ++ char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL }; ++ char *trust_args_printable[] = { (char *) "(proc)/certificate_printable.der", ++ NULL }; ++ char *distrust_args[] = { (char *) "1", NULL }; ++ char *distrust2_args[] = { (char *) "2", NULL }; ++ grub_err_t err; ++ ++ grub_procfs_register ("certificate.der", &certificate_der_entry); ++ grub_procfs_register ("certificate2.der", &certificate2_der_entry); ++ grub_procfs_register ("certificate_printable.der", ++ &certificate_printable_der_entry); ++ ++ cmd_trust = grub_command_find ("trust_certificate"); ++ if (!cmd_trust) ++ { ++ grub_test_assert (0, "can't find command `%s'", "trust_certificate"); ++ return; ++ } ++ err = (cmd_trust->func) (cmd_trust, 1, trust_args); ++ ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "loading certificate failed: %d: %s", grub_errno, ++ grub_errmsg); ++ ++ /* If we have no certificate the remainder of the tests are meaningless */ ++ if (err != GRUB_ERR_NONE) ++ return; ++ ++ /* ++ * Reload the command: this works around some 'interesting' behaviour in the ++ * dynamic command dispatcher. The first time you call cmd->func you get a ++ * dispatcher that loads the module, finds the real cmd, calls it, and then ++ * releases some internal storage. This means it's not safe to call a second ++ * time and we need to reload it. ++ */ ++ cmd_trust = grub_command_find ("trust_certificate"); ++ ++ DO_TEST (hi_signed, 1); ++ DO_TEST (hi_signed_sha256, 1); ++ DO_TEST (hj_signed, 0); ++ DO_TEST (short_msg, 0); ++ DO_TEST (unsigned_msg, 0); ++ ++ /* ++ * in enforcing mode, we shouldn't be able to load a certificate that isn't ++ * signed by an existing trusted key. ++ * ++ * However, procfs files automatically skip the verification test, so we can't ++ * easily test this. ++ */ ++ ++ /* ++ * verify that testing with 2 trusted certs works ++ */ ++ DO_TEST (hi_signed_2nd, 0); ++ ++ err = (cmd_trust->func) (cmd_trust, 1, trust_args2); ++ ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "loading certificate 2 failed: %d: %s", grub_errno, ++ grub_errmsg); ++ ++ if (err != GRUB_ERR_NONE) ++ return; ++ ++ DO_TEST (hi_signed_2nd, 1); ++ DO_TEST (hi_signed, 1); ++ ++ /* ++ * Check certificate removal. They're added to the _top_ of the list and ++ * removed by position in the list. Current the list looks like [#2, #1]. ++ * ++ * First test removing the second certificate in the list, which is ++ * certificate #1, giving us just [#2]. ++ */ ++ cmd_distrust = grub_command_find ("distrust_certificate"); ++ if (!cmd_distrust) ++ { ++ grub_test_assert (0, "can't find command `%s'", "distrust_certificate"); ++ return; ++ } ++ ++ err = (cmd_distrust->func) (cmd_distrust, 1, distrust2_args); ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "distrusting certificate 1 failed: %d: %s", grub_errno, ++ grub_errmsg); ++ DO_TEST (hi_signed_2nd, 1); ++ DO_TEST (hi_signed, 0); ++ ++ /* ++ * Now reload certificate #1. This will make the list look like [#1, #2] ++ */ ++ err = (cmd_trust->func) (cmd_trust, 1, trust_args); ++ ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "reloading certificate 1 failed: %d: %s", grub_errno, ++ grub_errmsg); ++ DO_TEST (hi_signed, 1); ++ ++ /* Remove the first certificate in the list, giving us just [#2] */ ++ err = (cmd_distrust->func) (cmd_distrust, 1, distrust_args); ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "distrusting certificate 1 (first time) failed: %d: %s", ++ grub_errno, grub_errmsg); ++ DO_TEST (hi_signed_2nd, 1); ++ DO_TEST (hi_signed, 0); ++ ++ /* ++ * Remove the first certificate again, giving an empty list. ++ * ++ * verify_appended should fail if there are no certificates to verify against. ++ */ ++ err = (cmd_distrust->func) (cmd_distrust, 1, distrust_args); ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "distrusting certificate 1 (second time) failed: %d: %s", ++ grub_errno, grub_errmsg); ++ DO_TEST (hi_signed_2nd, 0); ++ ++ /* ++ * Lastly, check a certificate that uses printableString rather than ++ * utf8String loads properly. ++ */ ++ err = (cmd_trust->func) (cmd_trust, 1, trust_args_printable); ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "distrusting printable certificate failed: %d: %s", ++ grub_errno, grub_errmsg); ++ ++ grub_procfs_unregister (&certificate_der_entry); ++ grub_procfs_unregister (&certificate2_der_entry); ++ grub_procfs_unregister (&certificate_printable_der_entry); ++} ++ ++GRUB_FUNCTIONAL_TEST (appended_signature_test, appended_signature_test); +diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c +index 96781fb39b..403fa5c789 100644 +--- a/grub-core/tests/lib/functional_test.c ++++ b/grub-core/tests/lib/functional_test.c +@@ -73,6 +73,7 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)), + grub_dl_load ("xnu_uuid_test"); + grub_dl_load ("pbkdf2_test"); + grub_dl_load ("signature_test"); ++ grub_dl_load ("appended_signature_test"); + grub_dl_load ("sleep_test"); + grub_dl_load ("bswap_test"); + grub_dl_load ("ctz_test"); +diff --git a/grub-core/tests/appended_signatures.h b/grub-core/tests/appended_signatures.h +new file mode 100644 +index 0000000000..aa3dc6278e +--- /dev/null ++++ b/grub-core/tests/appended_signatures.h +@@ -0,0 +1,557 @@ ++unsigned char certificate_der[] = { ++ 0x30, 0x82, 0x03, 0x88, 0x30, 0x82, 0x02, 0x70, 0xa0, 0x03, 0x02, 0x01, ++ 0x02, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, ++ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, ++ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, ++ 0x05, 0x00, 0x30, 0x49, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, ++ 0x03, 0x0c, 0x1f, 0x47, 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, ++ 0x6e, 0x64, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, ++ 0x72, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, ++ 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, ++ 0x01, 0x16, 0x0e, 0x64, 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, ++ 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x30, 0x30, ++ 0x37, 0x30, 0x39, 0x30, 0x36, 0x32, 0x32, 0x30, 0x37, 0x5a, 0x18, 0x0f, ++ 0x32, 0x31, 0x32, 0x30, 0x30, 0x36, 0x31, 0x35, 0x30, 0x36, 0x32, 0x32, ++ 0x30, 0x37, 0x5a, 0x30, 0x52, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, ++ 0x04, 0x03, 0x0c, 0x28, 0x47, 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, ++ 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, ++ 0x75, 0x72, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, ++ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x65, 0x79, 0x31, 0x1d, 0x30, 0x1b, ++ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, ++ 0x0e, 0x64, 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, ++ 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, ++ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, ++ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, ++ 0xcd, 0xe8, 0x1c, 0x08, 0x68, 0x2e, 0xcb, 0xfe, 0x8c, 0x4b, 0x3b, 0x61, ++ 0xe7, 0x8e, 0x80, 0x58, 0x85, 0x85, 0xea, 0xc8, 0x3b, 0x42, 0xba, 0x72, ++ 0x84, 0x65, 0x20, 0xbc, 0x48, 0xa2, 0x25, 0x49, 0x6e, 0x1c, 0xb9, 0x7d, ++ 0xeb, 0xc1, 0x0c, 0xa8, 0xb7, 0xcc, 0x13, 0x78, 0xba, 0x11, 0xa4, 0x98, ++ 0xd7, 0xd0, 0x7c, 0xdd, 0xf5, 0x5a, 0xb7, 0xcd, 0x31, 0x0e, 0xcd, 0x9e, ++ 0xa7, 0x19, 0xf0, 0xbd, 0x0f, 0xa6, 0xfe, 0x8a, 0x11, 0x97, 0xed, 0x8b, ++ 0xe5, 0x16, 0xa6, 0x21, 0x13, 0x36, 0xad, 0x05, 0x49, 0xec, 0x29, 0x12, ++ 0x38, 0xa7, 0x4b, 0x0f, 0xa1, 0xfb, 0x72, 0xc0, 0xc0, 0x09, 0x67, 0x78, ++ 0xa8, 0xb6, 0xd6, 0x1a, 0x39, 0xc0, 0xa8, 0xbf, 0x5f, 0x14, 0x89, 0x5c, ++ 0xbc, 0x41, 0x0c, 0x0c, 0x5d, 0x42, 0x2e, 0x1c, 0xdf, 0x1f, 0x1d, 0xc9, ++ 0x43, 0x94, 0x5b, 0x6e, 0x8f, 0x15, 0x8c, 0x8f, 0x94, 0x73, 0x4f, 0x97, ++ 0x54, 0xf1, 0x86, 0x8a, 0xbc, 0xe4, 0xe4, 0x93, 0xc1, 0x5e, 0xc2, 0x3e, ++ 0x31, 0x5e, 0xd4, 0x85, 0x57, 0x14, 0xd0, 0x11, 0x07, 0x65, 0xf4, 0x7c, ++ 0x8f, 0x07, 0x57, 0xe1, 0x22, 0xd4, 0x78, 0x47, 0x65, 0x4e, 0xa9, 0xb3, ++ 0xaa, 0xce, 0xc7, 0x36, 0xfe, 0xda, 0x66, 0x02, 0xb6, 0x8d, 0x18, 0x2f, ++ 0x3b, 0x41, 0x8d, 0x02, 0x08, 0x72, 0x4b, 0x69, 0xbd, 0x1e, 0x58, 0xfc, ++ 0x1b, 0x64, 0x04, 0x52, 0x35, 0x35, 0xe2, 0x3d, 0x3e, 0xde, 0xd6, 0x64, ++ 0xf4, 0xec, 0x57, 0x7e, 0x65, 0x59, 0x00, 0xa6, 0xd3, 0x4b, 0x09, 0x93, ++ 0x2a, 0x95, 0x0f, 0x30, 0xb6, 0xa1, 0x8c, 0xe7, 0x8b, 0x49, 0xa4, 0x1d, ++ 0x25, 0x2d, 0x65, 0x48, 0x8a, 0x0f, 0xcf, 0x2a, 0xa2, 0xe1, 0xef, 0x72, ++ 0x92, 0xc3, 0xf5, 0x21, 0x37, 0x83, 0x9b, 0x6d, 0x0b, 0x1b, 0xb3, 0xa2, ++ 0x32, 0x38, 0x11, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x5d, 0x30, ++ 0x5b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, ++ 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, ++ 0x03, 0x02, 0x07, 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, ++ 0x16, 0x04, 0x14, 0xe5, 0x2a, 0x4f, 0xf2, 0x84, 0x91, 0x57, 0x91, 0xaf, ++ 0x12, 0xd2, 0xf1, 0xa1, 0x87, 0x73, 0x0f, 0x90, 0x25, 0xa0, 0x7a, 0x30, ++ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, ++ 0x56, 0xd1, 0xfd, 0xe2, 0x1e, 0x7e, 0x1c, 0x63, 0x4f, 0x47, 0xdb, 0xe4, ++ 0xc4, 0x51, 0x04, 0x03, 0x9a, 0x48, 0x35, 0x6e, 0x30, 0x0d, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, ++ 0x82, 0x01, 0x01, 0x00, 0x65, 0x82, 0xd5, 0x88, 0x30, 0xe2, 0x2c, 0x47, ++ 0xf3, 0x31, 0x39, 0xa1, 0x75, 0x9a, 0xb0, 0x8a, 0x6c, 0x4b, 0xac, 0xdf, ++ 0x09, 0x7b, 0x90, 0xb6, 0x9e, 0x76, 0x62, 0x94, 0xc1, 0x3a, 0x99, 0x49, ++ 0x68, 0x29, 0x47, 0x42, 0xc3, 0x06, 0xcb, 0x88, 0x75, 0xe6, 0x79, 0x13, ++ 0x8c, 0x4b, 0x49, 0x6a, 0xb5, 0x56, 0x95, 0xc0, 0x42, 0x21, 0x9b, 0xd4, ++ 0x61, 0xd0, 0x02, 0x41, 0xdd, 0x20, 0x61, 0xe5, 0x91, 0xdf, 0x75, 0x00, ++ 0x25, 0x0e, 0x99, 0x65, 0x5c, 0x54, 0x49, 0x32, 0xa3, 0xe2, 0xcd, 0xa1, ++ 0x5f, 0x40, 0xf3, 0xc5, 0x81, 0xd9, 0x3c, 0xa3, 0x63, 0x5a, 0x38, 0x79, ++ 0xab, 0x77, 0x98, 0xde, 0x8f, 0x4e, 0x9e, 0x26, 0xbc, 0x4e, 0x80, 0x9e, ++ 0x8f, 0xbe, 0xf1, 0x00, 0xb3, 0x78, 0xb9, 0x4b, 0x1d, 0xc7, 0xa4, 0x83, ++ 0x59, 0x56, 0x11, 0xd1, 0x11, 0x1e, 0x50, 0x39, 0xd5, 0x78, 0x14, 0xf3, ++ 0xb9, 0x1d, 0xda, 0xe4, 0xc4, 0x63, 0x74, 0x26, 0xab, 0xa3, 0xfd, 0x9d, ++ 0x58, 0xa2, 0xee, 0x7b, 0x28, 0x34, 0xa3, 0xbe, 0x85, 0x7e, 0xaa, 0x97, ++ 0xb7, 0x5b, 0x9d, 0xa9, 0x4d, 0x96, 0xdb, 0x6b, 0x21, 0xe1, 0x96, 0x5d, ++ 0xc7, 0xad, 0x23, 0x03, 0x9a, 0x16, 0xdb, 0xa4, 0x1f, 0x63, 0xef, 0xaf, ++ 0x1e, 0x4f, 0xf8, 0x27, 0xdc, 0x4b, 0xfc, 0x2b, 0x68, 0x2e, 0xa0, 0xd3, ++ 0xae, 0xf2, 0xce, 0xf5, 0xfc, 0x97, 0x92, 0xd2, 0x29, 0x0f, 0x4f, 0x4b, ++ 0x29, 0xeb, 0x06, 0xcb, 0xf8, 0x21, 0x6e, 0xbc, 0x8b, 0x5c, 0xc5, 0xc9, ++ 0xf7, 0xe2, 0x7c, 0x47, 0xcd, 0x43, 0x98, 0xc4, 0xa3, 0x9a, 0xd7, 0x3e, ++ 0xdc, 0x01, 0x13, 0x28, 0x96, 0xc4, 0x60, 0x83, 0xe2, 0x79, 0xa1, 0x46, ++ 0xef, 0xf5, 0xa4, 0x7b, 0x00, 0xe3, 0x3d, 0x7d, 0xbc, 0xa8, 0x98, 0x49, ++ 0xa8, 0xcf, 0x3b, 0x41, 0xb6, 0x09, 0x97, 0x07 ++}; ++unsigned int certificate_der_len = 908; ++ ++unsigned char hi_signed[] = { ++ 0x68, 0x69, 0x0a, 0x30, 0x82, 0x01, 0xc0, 0x06, 0x09, 0x2a, 0x86, 0x48, ++ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x01, 0xb1, 0x30, 0x82, ++ 0x01, 0xad, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, ++ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x01, ++ 0x8a, 0x30, 0x82, 0x01, 0x86, 0x02, 0x01, 0x01, 0x30, 0x61, 0x30, 0x49, ++ 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1f, 0x47, ++ 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, ++ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, ++ 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0e, 0x64, ++ 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, 0x6e, 0x65, ++ 0x74, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, ++ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, ++ 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc7, 0x69, 0x35, 0x21, 0x66, ++ 0x4d, 0x50, 0xd4, 0x73, 0xde, 0xbd, 0x3a, 0xf6, 0x45, 0xe3, 0xe4, 0xd0, ++ 0xb6, 0xa1, 0xe7, 0xc0, 0xa2, 0xc9, 0xf4, 0xf0, 0x05, 0x8c, 0xa4, 0x16, ++ 0x9e, 0x81, 0x0d, 0x21, 0x68, 0xf3, 0xfe, 0x03, 0x96, 0x77, 0x31, 0x69, ++ 0x01, 0xd8, 0x26, 0xd9, 0x48, 0x95, 0xcf, 0xd1, 0x17, 0xb1, 0x0b, 0x6b, ++ 0x2c, 0xf1, 0xb0, 0xab, 0x65, 0x65, 0x56, 0xf8, 0x0c, 0xa7, 0xf7, 0xbb, ++ 0xf6, 0x5a, 0x55, 0x98, 0x14, 0x07, 0x8d, 0x2a, 0xbc, 0x16, 0x48, 0x94, ++ 0xab, 0x2f, 0x85, 0x97, 0x90, 0x51, 0x78, 0xa0, 0xda, 0x60, 0xb5, 0x41, ++ 0x4b, 0xe8, 0x78, 0xc5, 0xa6, 0x04, 0x9d, 0x54, 0x2a, 0x85, 0xfd, 0x86, ++ 0x0b, 0x6d, 0xc2, 0xd2, 0xad, 0x07, 0xff, 0x16, 0x42, 0x82, 0xe3, 0x5c, ++ 0xaa, 0x22, 0x59, 0x78, 0x92, 0xea, 0x94, 0xc3, 0x41, 0xb7, 0xa1, 0x86, ++ 0x44, 0xea, 0xd1, 0xdb, 0xe5, 0xac, 0x30, 0x32, 0xfb, 0x7d, 0x3f, 0xf7, ++ 0x8b, 0x11, 0x7f, 0x80, 0x3b, 0xe5, 0xc7, 0x82, 0x0f, 0x92, 0x07, 0x14, ++ 0x66, 0x01, 0x6e, 0x85, 0xab, 0x3a, 0x14, 0xcf, 0x76, 0xd1, 0x7e, 0x14, ++ 0x85, 0xca, 0x01, 0x73, 0x72, 0x38, 0xdc, 0xde, 0x30, 0x5c, 0xfb, 0xc0, ++ 0x3d, 0x93, 0xef, 0x9c, 0xbc, 0xf8, 0xcc, 0xd2, 0xbf, 0x47, 0xec, 0xf8, ++ 0x88, 0x9b, 0xe1, 0x43, 0xbe, 0xa7, 0x47, 0x96, 0xb6, 0x5d, 0x46, 0x0e, ++ 0x7a, 0x78, 0x38, 0x19, 0xbc, 0xb5, 0xbc, 0x9b, 0x3c, 0x39, 0x92, 0x70, ++ 0x0d, 0x9d, 0x8a, 0x35, 0xaf, 0xb4, 0x9e, 0xf4, 0xef, 0xc1, 0xb8, 0x25, ++ 0xd0, 0x14, 0x91, 0xd6, 0xc2, 0xb6, 0xc7, 0x3c, 0x72, 0x91, 0x0f, 0xad, ++ 0xde, 0xb2, 0x36, 0xf8, 0x4e, 0x59, 0xd4, 0xa4, 0x21, 0x9f, 0x03, 0x95, ++ 0x48, 0x01, 0xb4, 0x05, 0xc3, 0x39, 0x60, 0x51, 0x08, 0xd0, 0xbe, 0x00, ++ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x7e, ++ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, ++ 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, ++ 0x64, 0x7e, 0x0a ++}; ++unsigned int hi_signed_len = 495; ++ ++unsigned char hj_signed[] = { ++ 0x68, 0x6a, 0x0a, 0x30, 0x82, 0x01, 0xc0, 0x06, 0x09, 0x2a, 0x86, 0x48, ++ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x01, 0xb1, 0x30, 0x82, ++ 0x01, 0xad, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, ++ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x01, ++ 0x8a, 0x30, 0x82, 0x01, 0x86, 0x02, 0x01, 0x01, 0x30, 0x61, 0x30, 0x49, ++ 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1f, 0x47, ++ 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, ++ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, ++ 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0e, 0x64, ++ 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, 0x6e, 0x65, ++ 0x74, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, ++ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, ++ 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc7, 0x69, 0x35, 0x21, 0x66, ++ 0x4d, 0x50, 0xd4, 0x73, 0xde, 0xbd, 0x3a, 0xf6, 0x45, 0xe3, 0xe4, 0xd0, ++ 0xb6, 0xa1, 0xe7, 0xc0, 0xa2, 0xc9, 0xf4, 0xf0, 0x05, 0x8c, 0xa4, 0x16, ++ 0x9e, 0x81, 0x0d, 0x21, 0x68, 0xf3, 0xfe, 0x03, 0x96, 0x77, 0x31, 0x69, ++ 0x01, 0xd8, 0x26, 0xd9, 0x48, 0x95, 0xcf, 0xd1, 0x17, 0xb1, 0x0b, 0x6b, ++ 0x2c, 0xf1, 0xb0, 0xab, 0x65, 0x65, 0x56, 0xf8, 0x0c, 0xa7, 0xf7, 0xbb, ++ 0xf6, 0x5a, 0x55, 0x98, 0x14, 0x07, 0x8d, 0x2a, 0xbc, 0x16, 0x48, 0x94, ++ 0xab, 0x2f, 0x85, 0x97, 0x90, 0x51, 0x78, 0xa0, 0xda, 0x60, 0xb5, 0x41, ++ 0x4b, 0xe8, 0x78, 0xc5, 0xa6, 0x04, 0x9d, 0x54, 0x2a, 0x85, 0xfd, 0x86, ++ 0x0b, 0x6d, 0xc2, 0xd2, 0xad, 0x07, 0xff, 0x16, 0x42, 0x82, 0xe3, 0x5c, ++ 0xaa, 0x22, 0x59, 0x78, 0x92, 0xea, 0x94, 0xc3, 0x41, 0xb7, 0xa1, 0x86, ++ 0x44, 0xea, 0xd1, 0xdb, 0xe5, 0xac, 0x30, 0x32, 0xfb, 0x7d, 0x3f, 0xf7, ++ 0x8b, 0x11, 0x7f, 0x80, 0x3b, 0xe5, 0xc7, 0x82, 0x0f, 0x92, 0x07, 0x14, ++ 0x66, 0x01, 0x6e, 0x85, 0xab, 0x3a, 0x14, 0xcf, 0x76, 0xd1, 0x7e, 0x14, ++ 0x85, 0xca, 0x01, 0x73, 0x72, 0x38, 0xdc, 0xde, 0x30, 0x5c, 0xfb, 0xc0, ++ 0x3d, 0x93, 0xef, 0x9c, 0xbc, 0xf8, 0xcc, 0xd2, 0xbf, 0x47, 0xec, 0xf8, ++ 0x88, 0x9b, 0xe1, 0x43, 0xbe, 0xa7, 0x47, 0x96, 0xb6, 0x5d, 0x46, 0x0e, ++ 0x7a, 0x78, 0x38, 0x19, 0xbc, 0xb5, 0xbc, 0x9b, 0x3c, 0x39, 0x92, 0x70, ++ 0x0d, 0x9d, 0x8a, 0x35, 0xaf, 0xb4, 0x9e, 0xf4, 0xef, 0xc1, 0xb8, 0x25, ++ 0xd0, 0x14, 0x91, 0xd6, 0xc2, 0xb6, 0xc7, 0x3c, 0x72, 0x91, 0x0f, 0xad, ++ 0xde, 0xb2, 0x36, 0xf8, 0x4e, 0x59, 0xd4, 0xa4, 0x21, 0x9f, 0x03, 0x95, ++ 0x48, 0x01, 0xb4, 0x05, 0xc3, 0x39, 0x60, 0x51, 0x08, 0xd0, 0xbe, 0x00, ++ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x7e, ++ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, ++ 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, ++ 0x64, 0x7e, 0x0a ++}; ++unsigned int hj_signed_len = 495; ++ ++unsigned char hi_signed_sha256[] = { ++ 0x68, 0x69, 0x0a, 0x30, 0x82, 0x01, 0xc0, 0x06, 0x09, 0x2a, 0x86, 0x48, ++ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x01, 0xb1, 0x30, 0x82, ++ 0x01, 0xad, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, ++ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x01, ++ 0x8a, 0x30, 0x82, 0x01, 0x86, 0x02, 0x01, 0x01, 0x30, 0x61, 0x30, 0x49, ++ 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1f, 0x47, ++ 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, ++ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, ++ 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0e, 0x64, ++ 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, 0x6e, 0x65, ++ 0x74, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, ++ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, ++ 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x7b, 0x5e, 0x82, 0x1d, 0x21, ++ 0xb6, 0x40, 0xd3, 0x33, 0x79, 0xa7, 0x52, 0x2b, 0xfc, 0x46, 0x51, 0x26, ++ 0xfe, 0x0f, 0x81, 0x90, 0x81, 0xab, 0x57, 0x5e, 0xf6, 0x45, 0x41, 0xa3, ++ 0x7b, 0x48, 0xdd, 0xd6, 0x59, 0x60, 0x51, 0x31, 0x14, 0x14, 0x7b, 0xb4, ++ 0x55, 0x7b, 0x4d, 0xfe, 0x09, 0x7a, 0x5d, 0xae, 0xc4, 0x58, 0x50, 0x80, ++ 0x75, 0xf2, 0x23, 0x20, 0x62, 0xe3, 0x7c, 0x26, 0x1d, 0x2a, 0x4d, 0x9f, ++ 0x89, 0xf0, 0x4f, 0x95, 0x8a, 0x80, 0x6e, 0x1a, 0xea, 0x87, 0xdb, 0x1f, ++ 0xf3, 0xda, 0x04, 0x91, 0x37, 0xea, 0x0a, 0xfb, 0x6c, 0xc9, 0x3d, 0x73, ++ 0xf9, 0x58, 0x7c, 0x15, 0x6b, 0xa2, 0x52, 0x5a, 0x97, 0xff, 0xd6, 0xb0, ++ 0xf1, 0xbf, 0xa5, 0x04, 0x6d, 0x91, 0xc1, 0x54, 0x05, 0xdc, 0x7f, 0x5d, ++ 0x19, 0xaf, 0x55, 0xec, 0x51, 0xfb, 0x66, 0x0a, 0xa4, 0x4e, 0x96, 0x47, ++ 0x43, 0x54, 0x7c, 0x64, 0xa8, 0xaa, 0xb4, 0x90, 0x02, 0xf3, 0xa7, 0x0b, ++ 0xb7, 0xbf, 0x06, 0xdb, 0x5e, 0x9c, 0x32, 0x6d, 0x45, 0x14, 0x1c, 0xaf, ++ 0x46, 0x30, 0x08, 0x55, 0x49, 0x78, 0xfa, 0x57, 0xda, 0x3d, 0xf5, 0xa0, ++ 0xef, 0x11, 0x0a, 0x81, 0x0d, 0x82, 0xcd, 0xaf, 0xdb, 0xda, 0x0e, 0x1a, ++ 0x44, 0xd1, 0xee, 0xc4, 0xb8, 0xde, 0x97, 0xb4, 0xda, 0xb4, 0x8b, 0x4f, ++ 0x58, 0x24, 0x59, 0xc0, 0xe0, 0x08, 0x97, 0x14, 0x68, 0xbe, 0x31, 0x09, ++ 0x5e, 0x67, 0x45, 0xf0, 0xcb, 0x81, 0x4f, 0x17, 0x44, 0x61, 0xe0, 0xe2, ++ 0xf0, 0xfc, 0x1e, 0xb9, 0x73, 0xaf, 0x42, 0xff, 0x33, 0xde, 0x61, 0x6b, ++ 0x7f, 0xc2, 0x69, 0x0d, 0x66, 0x54, 0xae, 0xf6, 0xde, 0x20, 0x47, 0x44, ++ 0x9b, 0x73, 0xd1, 0x07, 0x6e, 0x77, 0x37, 0x0a, 0xbb, 0x7f, 0xa0, 0x93, ++ 0x2d, 0x8d, 0x44, 0xba, 0xe2, 0xdd, 0x34, 0x32, 0xd7, 0x56, 0x71, 0x00, ++ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x7e, ++ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, ++ 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, ++ 0x64, 0x7e, 0x0a ++}; ++unsigned int hi_signed_sha256_len = 495; ++ ++unsigned char short_msg[] = { ++ 0x68, 0x69, 0x0a ++}; ++unsigned int short_msg_len = 3; ++ ++unsigned char unsigned_msg[] = { ++ 0x53, 0x65, 0x64, 0x20, 0x75, 0x74, 0x20, 0x70, 0x65, 0x72, 0x73, 0x70, ++ 0x69, 0x63, 0x69, 0x61, 0x74, 0x69, 0x73, 0x20, 0x75, 0x6e, 0x64, 0x65, ++ 0x20, 0x6f, 0x6d, 0x6e, 0x69, 0x73, 0x20, 0x69, 0x73, 0x74, 0x65, 0x20, ++ 0x6e, 0x61, 0x74, 0x75, 0x73, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, ++ 0x73, 0x69, 0x74, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, ++ 0x65, 0x6d, 0x20, 0x61, 0x63, 0x63, 0x75, 0x73, 0x61, 0x6e, 0x74, 0x69, ++ 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x71, 0x75, ++ 0x65, 0x20, 0x6c, 0x61, 0x75, 0x64, 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, ++ 0x2c, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x6d, 0x20, ++ 0x61, 0x70, 0x65, 0x72, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x65, 0x61, 0x71, ++ 0x75, 0x65, 0x20, 0x69, 0x70, 0x73, 0x61, 0x20, 0x71, 0x75, 0x61, 0x65, ++ 0x20, 0x61, 0x62, 0x20, 0x69, 0x6c, 0x6c, 0x6f, 0x20, 0x69, 0x6e, 0x76, ++ 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x69, 0x74, ++ 0x61, 0x74, 0x69, 0x73, 0x20, 0x65, 0x74, 0x20, 0x71, 0x75, 0x61, 0x73, ++ 0x69, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x6f, ++ 0x20, 0x62, 0x65, 0x61, 0x74, 0x61, 0x65, 0x20, 0x76, 0x69, 0x74, 0x61, ++ 0x65, 0x20, 0x64, 0x69, 0x63, 0x74, 0x61, 0x20, 0x73, 0x75, 0x6e, 0x74, ++ 0x20, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6f, 0x2e, 0x20, ++ 0x4e, 0x65, 0x6d, 0x6f, 0x20, 0x65, 0x6e, 0x69, 0x6d, 0x20, 0x69, 0x70, ++ 0x73, 0x61, 0x6d, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, ++ 0x65, 0x6d, 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, ++ 0x70, 0x74, 0x61, 0x73, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x73, 0x70, ++ 0x65, 0x72, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x20, 0x61, 0x75, 0x74, 0x20, ++ 0x6f, 0x64, 0x69, 0x74, 0x20, 0x61, 0x75, 0x74, 0x20, 0x66, 0x75, 0x67, ++ 0x69, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x64, 0x20, 0x71, 0x75, 0x69, 0x61, ++ 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x75, 0x6e, 0x74, 0x75, ++ 0x72, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x65, 0x73, 0x20, 0x65, 0x6f, 0x73, 0x20, 0x71, 0x75, 0x69, 0x20, ++ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x6c, 0x75, ++ 0x70, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x20, 0x73, 0x65, 0x71, 0x75, 0x69, ++ 0x20, 0x6e, 0x65, 0x73, 0x63, 0x69, 0x75, 0x6e, 0x74, 0x2e, 0x20, 0x4e, ++ 0x65, 0x71, 0x75, 0x65, 0x20, 0x70, 0x6f, 0x72, 0x72, 0x6f, 0x20, 0x71, ++ 0x75, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x65, 0x73, 0x74, 0x2c, ++ 0x20, 0x71, 0x75, 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, ++ 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, ++ 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, ++ 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, ++ 0x74, 0x75, 0x72, 0x2c, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, ++ 0x69, 0x20, 0x76, 0x65, 0x6c, 0x69, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x64, ++ 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, 0x6e, 0x6f, 0x6e, 0x20, 0x6e, 0x75, ++ 0x6d, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x65, 0x69, 0x75, 0x73, 0x20, 0x6d, ++ 0x6f, 0x64, 0x69, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x20, ++ 0x69, 0x6e, 0x63, 0x69, 0x64, 0x75, 0x6e, 0x74, 0x20, 0x75, 0x74, 0x20, ++ 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x65, 0x20, 0x65, 0x74, 0x20, 0x64, 0x6f, ++ 0x6c, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x61, 0x6d, 0x20, ++ 0x61, 0x6c, 0x69, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x71, 0x75, 0x61, 0x65, ++ 0x72, 0x61, 0x74, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, ++ 0x65, 0x6d, 0x2e, 0x20, 0x55, 0x74, 0x20, 0x65, 0x6e, 0x69, 0x6d, 0x20, ++ 0x61, 0x64, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x20, 0x76, 0x65, ++ 0x6e, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x71, 0x75, 0x69, 0x73, 0x20, 0x6e, ++ 0x6f, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x20, 0x65, 0x78, 0x65, 0x72, 0x63, ++ 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x6d, 0x20, 0x75, 0x6c, ++ 0x6c, 0x61, 0x6d, 0x20, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x69, 0x73, ++ 0x20, 0x73, 0x75, 0x73, 0x63, 0x69, 0x70, 0x69, 0x74, 0x20, 0x6c, 0x61, ++ 0x62, 0x6f, 0x72, 0x69, 0x6f, 0x73, 0x61, 0x6d, 0x2c, 0x20, 0x6e, 0x69, ++ 0x73, 0x69, 0x20, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x71, 0x75, 0x69, ++ 0x64, 0x20, 0x65, 0x78, 0x20, 0x65, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, ++ 0x6f, 0x64, 0x69, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x61, ++ 0x74, 0x75, 0x72, 0x3f, 0x20, 0x51, 0x75, 0x69, 0x73, 0x20, 0x61, 0x75, ++ 0x74, 0x65, 0x6d, 0x20, 0x76, 0x65, 0x6c, 0x20, 0x65, 0x75, 0x6d, 0x20, ++ 0x69, 0x75, 0x72, 0x65, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x68, 0x65, ++ 0x6e, 0x64, 0x65, 0x72, 0x69, 0x74, 0x20, 0x71, 0x75, 0x69, 0x20, 0x69, ++ 0x6e, 0x20, 0x65, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, ++ 0x74, 0x65, 0x20, 0x76, 0x65, 0x6c, 0x69, 0x74, 0x20, 0x65, 0x73, 0x73, ++ 0x65, 0x20, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x6e, 0x69, 0x68, 0x69, 0x6c, ++ 0x20, 0x6d, 0x6f, 0x6c, 0x65, 0x73, 0x74, 0x69, 0x61, 0x65, 0x20, 0x63, ++ 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x61, 0x74, 0x75, 0x72, 0x2c, 0x20, ++ 0x76, 0x65, 0x6c, 0x20, 0x69, 0x6c, 0x6c, 0x75, 0x6d, 0x20, 0x71, 0x75, ++ 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x65, 0x75, ++ 0x6d, 0x20, 0x66, 0x75, 0x67, 0x69, 0x61, 0x74, 0x20, 0x71, 0x75, 0x6f, ++ 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x73, 0x20, 0x6e, 0x75, ++ 0x6c, 0x6c, 0x61, 0x20, 0x70, 0x61, 0x72, 0x69, 0x61, 0x74, 0x75, 0x72, ++ 0x3f, 0x0a ++}; ++unsigned int unsigned_msg_len = 866; ++ ++unsigned char certificate2_der[] = { ++ 0x30, 0x82, 0x05, 0x52, 0x30, 0x82, 0x03, 0x3a, 0xa0, 0x03, 0x02, 0x01, ++ 0x02, 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, ++ 0x3a, 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, ++ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, ++ 0x05, 0x00, 0x30, 0x3a, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, ++ 0x03, 0x0c, 0x2f, 0x47, 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, ++ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, ++ 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, ++ 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, ++ 0x74, 0x79, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x37, 0x32, 0x38, ++ 0x31, 0x33, 0x32, 0x34, 0x32, 0x39, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x32, ++ 0x30, 0x30, 0x37, 0x30, 0x34, 0x31, 0x33, 0x32, 0x34, 0x32, 0x39, 0x5a, ++ 0x30, 0x2b, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, ++ 0x20, 0x47, 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, ++ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, ++ 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x65, 0x79, 0x30, 0x82, 0x02, ++ 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, ++ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, ++ 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb0, 0x2f, 0x50, 0x01, 0x9c, 0x0e, ++ 0xd6, 0x8c, 0x07, 0xca, 0xc1, 0xcf, 0xbc, 0x03, 0xdd, 0xd3, 0xfa, 0xe3, ++ 0x4f, 0x71, 0xc1, 0x30, 0xaa, 0x09, 0x96, 0xe4, 0xd0, 0x6c, 0x42, 0x93, ++ 0xdb, 0x35, 0xf6, 0x7e, 0x1b, 0x67, 0xc0, 0xc2, 0x2d, 0x5b, 0xec, 0xca, ++ 0x35, 0x06, 0x32, 0x6c, 0x7b, 0x2c, 0xd3, 0x71, 0x2b, 0xe9, 0x7a, 0x19, ++ 0xd1, 0xf2, 0xa0, 0x7f, 0xd7, 0x4d, 0x6e, 0x28, 0xbb, 0xae, 0x49, 0x4a, ++ 0xbc, 0xea, 0x47, 0x67, 0xb8, 0x36, 0xa6, 0xf5, 0x0d, 0x0e, 0x20, 0x14, ++ 0x0c, 0x66, 0x67, 0x28, 0xb5, 0x97, 0x8b, 0x1f, 0x5e, 0x32, 0x06, 0x29, ++ 0x9c, 0x99, 0x92, 0x0f, 0x73, 0xac, 0xfd, 0xd2, 0x1d, 0xf2, 0xa8, 0x55, ++ 0x9d, 0x1b, 0xd8, 0x3d, 0xb0, 0x76, 0x9a, 0xb6, 0x6c, 0x9f, 0x62, 0x37, ++ 0x2f, 0xc0, 0xef, 0x44, 0xb3, 0x0d, 0x4a, 0x3e, 0x4f, 0x7d, 0xbd, 0xdb, ++ 0xd8, 0x75, 0x5f, 0x68, 0xe3, 0xf0, 0xec, 0x82, 0x66, 0x7c, 0x31, 0x70, ++ 0xa9, 0xa1, 0x6f, 0x38, 0x9f, 0xdf, 0xf5, 0xf0, 0x7d, 0x23, 0x9d, 0x34, ++ 0xa5, 0x85, 0xd3, 0xdf, 0x68, 0x41, 0xfc, 0x4f, 0x89, 0x45, 0x3c, 0x24, ++ 0x81, 0xa6, 0xf2, 0x3c, 0x02, 0x26, 0x09, 0x48, 0xdd, 0xfe, 0x4b, 0xb6, ++ 0x66, 0xbf, 0x8f, 0xe5, 0x5f, 0xf0, 0x5d, 0x8a, 0x61, 0x2e, 0x5f, 0x9f, ++ 0x80, 0xd9, 0xd5, 0xe6, 0x41, 0xd8, 0x10, 0x5e, 0x7a, 0xc6, 0xdb, 0x89, ++ 0xc7, 0xca, 0x6c, 0x5b, 0xb1, 0x4e, 0x7d, 0x0c, 0x03, 0xfd, 0x50, 0xca, ++ 0xbf, 0xbb, 0xe2, 0x69, 0x4b, 0x4e, 0xc2, 0x3d, 0x75, 0xfa, 0xd1, 0xcc, ++ 0xd6, 0xf9, 0x39, 0xb9, 0xdc, 0x53, 0xad, 0x62, 0xfb, 0x1b, 0x94, 0x26, ++ 0x7f, 0x21, 0x54, 0x5c, 0xb7, 0xdc, 0xe7, 0x96, 0x8c, 0xce, 0x75, 0xe0, ++ 0x17, 0x01, 0x3a, 0x3c, 0x77, 0x6e, 0xa4, 0x8b, 0x7a, 0x83, 0x28, 0x7a, ++ 0xf7, 0xb0, 0x5f, 0xfc, 0x7f, 0x2d, 0x2e, 0xec, 0xf5, 0xeb, 0x9c, 0x63, ++ 0x74, 0xd0, 0xe5, 0xdc, 0x19, 0xe4, 0x71, 0xc5, 0x4a, 0x8a, 0x54, 0xa4, ++ 0xe0, 0x7d, 0x4e, 0xbf, 0x53, 0x30, 0xaf, 0xd0, 0xeb, 0x96, 0xc3, 0xbb, ++ 0x65, 0xf7, 0x67, 0xf5, 0xae, 0xd3, 0x96, 0xf2, 0x63, 0xc8, 0x69, 0xf7, ++ 0x47, 0xcb, 0x27, 0x79, 0xe1, 0xff, 0x2f, 0x68, 0xdf, 0x1e, 0xb3, 0xb8, ++ 0x0c, 0xc5, 0x58, 0x73, 0xcc, 0xfe, 0x8c, 0xda, 0x4e, 0x3b, 0x01, 0x04, ++ 0xcd, 0xcb, 0xb8, 0x3e, 0x06, 0xfd, 0x4c, 0x0a, 0x9f, 0x5e, 0x76, 0x8c, ++ 0x0c, 0x83, 0x75, 0x09, 0x08, 0xb2, 0xdb, 0xf4, 0x49, 0x4e, 0xa0, 0xf2, ++ 0x0c, 0x7b, 0x87, 0x38, 0x9e, 0x22, 0x67, 0xbd, 0xd1, 0x97, 0x57, 0x24, ++ 0xf1, 0x46, 0x07, 0xf9, 0xd2, 0x1b, 0xec, 0x25, 0x5e, 0x67, 0xd9, 0x66, ++ 0x23, 0x1b, 0xd3, 0xe4, 0xaa, 0xec, 0x88, 0xf0, 0x7e, 0x15, 0x83, 0x51, ++ 0x31, 0x67, 0x51, 0x76, 0x5f, 0x55, 0xd7, 0x36, 0xdf, 0x4a, 0x84, 0x0b, ++ 0x6f, 0x5c, 0xbb, 0x5b, 0x8f, 0x37, 0x23, 0x7f, 0xf8, 0x17, 0x84, 0xa2, ++ 0x70, 0x20, 0x07, 0x0c, 0x90, 0x3a, 0x04, 0xfd, 0xf0, 0x08, 0x4a, 0xb1, ++ 0x16, 0x0f, 0xe6, 0xf6, 0x40, 0x51, 0x83, 0xd2, 0x87, 0x40, 0x9c, 0x1c, ++ 0x9f, 0x13, 0x38, 0x17, 0xd3, 0x34, 0x58, 0xad, 0x05, 0x71, 0xa0, 0x73, ++ 0xca, 0x40, 0xa6, 0xa4, 0x81, 0x02, 0xee, 0xa8, 0x72, 0x41, 0xa1, 0x41, ++ 0x18, 0x64, 0x8a, 0x86, 0x8a, 0x5d, 0xe6, 0x4f, 0x0a, 0xc5, 0x95, 0x98, ++ 0xf9, 0x78, 0xfe, 0x19, 0x0d, 0xc9, 0xb3, 0x89, 0xc1, 0x2b, 0x09, 0xbe, ++ 0xf1, 0xd2, 0x04, 0x5d, 0xcc, 0x28, 0xf5, 0x4b, 0xd2, 0x20, 0x4f, 0xc5, ++ 0x41, 0x9d, 0x8c, 0x85, 0xd8, 0xb0, 0x68, 0x5e, 0xc1, 0x0c, 0xb7, 0x24, ++ 0x4d, 0x67, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x5d, 0x30, 0x5b, 0x30, ++ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, ++ 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, ++ 0x07, 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, ++ 0x14, 0xac, 0xf5, 0x47, 0x17, 0xd9, 0x7d, 0xc1, 0xb1, 0xc4, 0x41, 0xe1, ++ 0x41, 0x60, 0xcb, 0x37, 0x11, 0x60, 0x28, 0x78, 0x5f, 0x30, 0x1f, 0x06, ++ 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x21, 0x94, ++ 0xfb, 0xf9, 0xb2, 0x43, 0xe9, 0x33, 0xd7, 0x50, 0x7d, 0xc7, 0x37, 0xdb, ++ 0xd5, 0x82, 0x5a, 0x4e, 0xbe, 0x1b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, ++ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, ++ 0x01, 0x00, 0x96, 0x70, 0x65, 0x26, 0x42, 0xf8, 0xdc, 0x69, 0xde, 0xcf, ++ 0x41, 0x3a, 0x2e, 0x7f, 0x5b, 0xf1, 0xf9, 0x3b, 0x9b, 0xd2, 0x4e, 0x64, ++ 0x48, 0x81, 0xe4, 0x5d, 0x1e, 0x22, 0xce, 0x68, 0x63, 0x62, 0xe5, 0x1b, ++ 0x9b, 0xf2, 0xc7, 0x12, 0xda, 0x1e, 0x9b, 0x90, 0x84, 0x79, 0x48, 0x12, ++ 0xe6, 0x21, 0x6f, 0x2f, 0x7e, 0x18, 0x77, 0xdb, 0x8c, 0xc4, 0xd1, 0x0d, ++ 0x91, 0xbf, 0x39, 0x22, 0x0f, 0x64, 0xcf, 0x25, 0x2e, 0x8c, 0x1f, 0x91, ++ 0x81, 0xb5, 0xe9, 0x6c, 0x02, 0x3a, 0xf8, 0x07, 0xa2, 0x6f, 0x46, 0x5d, ++ 0x7b, 0xfd, 0x43, 0xff, 0x41, 0x0f, 0xe2, 0x57, 0x1c, 0xbd, 0x48, 0x60, ++ 0x53, 0x11, 0x48, 0x87, 0x88, 0x9d, 0x13, 0x82, 0x40, 0x68, 0x44, 0x2c, ++ 0xc6, 0xc8, 0x95, 0x27, 0x4f, 0xb6, 0xb9, 0x4a, 0x22, 0x0a, 0xfd, 0xe4, ++ 0x46, 0x8f, 0x35, 0x12, 0x98, 0x5a, 0x34, 0x6f, 0x2b, 0x57, 0x62, 0xa1, ++ 0x4d, 0x8d, 0x79, 0x37, 0xe4, 0x6b, 0x8a, 0x32, 0x5b, 0xcb, 0xef, 0x79, ++ 0x11, 0xed, 0xa7, 0xf8, 0x7a, 0x1c, 0xbd, 0x86, 0xdc, 0x0e, 0x2e, 0xfd, ++ 0xd3, 0x51, 0xbb, 0x73, 0xad, 0x00, 0xa0, 0x1b, 0xf9, 0x1d, 0xd1, 0x4a, ++ 0xe4, 0xd4, 0x02, 0x63, 0x2b, 0x39, 0x5f, 0x18, 0x08, 0x2f, 0x42, 0xb7, ++ 0x23, 0x4b, 0x48, 0x46, 0x1f, 0x63, 0x87, 0xae, 0x6d, 0xd5, 0xdb, 0x60, ++ 0xf8, 0x5f, 0xd3, 0x13, 0xec, 0xca, 0xdd, 0x60, 0x60, 0x79, 0x52, 0x70, ++ 0x47, 0xae, 0x1d, 0x38, 0x78, 0x71, 0xcf, 0xb3, 0x04, 0x03, 0xbe, 0xba, ++ 0x81, 0xba, 0x74, 0xb1, 0x30, 0x35, 0xdc, 0xea, 0x21, 0x4a, 0x9b, 0x70, ++ 0xfb, 0xd6, 0x60, 0x59, 0x78, 0x0c, 0x4d, 0x39, 0x19, 0x1d, 0xe5, 0x75, ++ 0xba, 0x07, 0xf4, 0x22, 0x37, 0x64, 0xb7, 0xf2, 0x9a, 0xc9, 0x11, 0x2d, ++ 0x8e, 0x58, 0xa6, 0xcf, 0x83, 0xf1, 0xcb, 0x6c, 0x7f, 0x02, 0xbd, 0xda, ++ 0x03, 0x92, 0xa9, 0x45, 0x24, 0x56, 0xc5, 0xbd, 0x41, 0xd1, 0x20, 0x86, ++ 0xc0, 0xb6, 0xb7, 0xe8, 0xa7, 0xb2, 0x46, 0xf7, 0x8e, 0xa9, 0x38, 0x0e, ++ 0x23, 0x77, 0x3c, 0x0d, 0x66, 0x83, 0x6a, 0x1a, 0x6b, 0x7f, 0x54, 0x11, ++ 0x58, 0x0d, 0x4a, 0xb5, 0x74, 0x60, 0xca, 0xed, 0xff, 0x91, 0x47, 0xd9, ++ 0x29, 0xe0, 0xaa, 0x8c, 0xa8, 0x8f, 0x10, 0x4c, 0x15, 0x7d, 0xce, 0x95, ++ 0xf9, 0x87, 0x1e, 0x18, 0x38, 0x18, 0xfc, 0xcc, 0xaf, 0x91, 0x17, 0x3f, ++ 0xfa, 0xf0, 0x8a, 0x09, 0x6f, 0xba, 0x4e, 0x53, 0xf7, 0xfa, 0x4f, 0x20, ++ 0xa3, 0xf4, 0x4a, 0x5a, 0xde, 0x17, 0x1c, 0x29, 0x6a, 0x6f, 0x03, 0x48, ++ 0xdf, 0xad, 0x4f, 0xe4, 0xbc, 0x71, 0xc4, 0x72, 0x32, 0x11, 0x84, 0xac, ++ 0x09, 0xd2, 0x18, 0x44, 0x35, 0xf1, 0xcd, 0xaf, 0xa8, 0x98, 0xe0, 0x8b, ++ 0xec, 0xa0, 0x83, 0x37, 0xc3, 0x35, 0x85, 0xd6, 0xd8, 0x1b, 0xe0, 0x75, ++ 0xdc, 0xfd, 0xde, 0xc9, 0xeb, 0xd5, 0x18, 0x0f, 0xd3, 0x4c, 0x2f, 0x71, ++ 0xdc, 0x48, 0xe3, 0x14, 0xeb, 0xda, 0x00, 0x24, 0x24, 0x9e, 0xa3, 0x8e, ++ 0x3e, 0x08, 0x6f, 0x22, 0x24, 0xd6, 0xc4, 0x85, 0x8f, 0x68, 0x00, 0x4a, ++ 0x82, 0x4c, 0x33, 0x6e, 0xa5, 0x35, 0x7b, 0xeb, 0x4b, 0xdc, 0xa0, 0xa6, ++ 0x65, 0x6f, 0x5a, 0x7a, 0xdf, 0x8a, 0x01, 0x52, 0xa1, 0x6c, 0xff, 0x59, ++ 0x22, 0x7f, 0xe1, 0x96, 0x1b, 0x19, 0xb8, 0xf9, 0x5d, 0x44, 0x9f, 0x91, ++ 0x03, 0x3c, 0x3d, 0xa1, 0x2a, 0xb6, 0x5a, 0x51, 0xa0, 0xce, 0x4a, 0x88, ++ 0x22, 0x72, 0x9c, 0xdc, 0xc0, 0x47, 0x76, 0x35, 0x84, 0x75, 0x9b, 0x87, ++ 0x5c, 0xd3, 0xcf, 0xe7, 0xdd, 0xa3, 0x57, 0x14, 0xdf, 0x00, 0xfd, 0x19, ++ 0x2a, 0x7d, 0x89, 0x27, 0x1c, 0x78, 0x97, 0x04, 0x58, 0x48 ++}; ++unsigned int certificate2_der_len = 1366; ++ ++unsigned char hi_signed_2nd[] = { ++ 0x68, 0x69, 0x0a, 0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, ++ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, ++ 0x02, 0x9e, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, ++ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, ++ 0x7b, 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x01, 0x30, 0x52, 0x30, 0x3a, ++ 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x47, ++ 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, 0x72, 0x74, ++ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, ++ 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, ++ 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, 0x14, ++ 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, 0x3a, 0x91, 0x07, ++ 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, 0x0b, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0d, 0x06, ++ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, ++ 0x04, 0x82, 0x02, 0x00, 0x0e, 0xc2, 0x30, 0x38, 0x81, 0x23, 0x68, 0x90, ++ 0xae, 0x5f, 0xce, 0xf7, 0x27, 0xb1, 0x8c, 0x2e, 0x12, 0x10, 0xc6, 0x99, ++ 0xdc, 0x4d, 0x4b, 0x79, 0xda, 0xe4, 0x32, 0x10, 0x46, 0x1c, 0x16, 0x07, ++ 0x87, 0x66, 0x55, 0xff, 0x64, 0x1c, 0x61, 0x25, 0xd5, 0xb9, 0xe1, 0xfe, ++ 0xea, 0x5a, 0xcd, 0x56, 0xa5, 0xc3, 0xbe, 0xb1, 0x61, 0xc7, 0x6f, 0x5f, ++ 0x69, 0x20, 0x64, 0x50, 0x6f, 0x12, 0x78, 0xb6, 0x0c, 0x72, 0x44, 0x4f, ++ 0x60, 0x0f, 0x9f, 0xa2, 0x83, 0x3b, 0xc2, 0x83, 0xd5, 0x14, 0x1f, 0x6f, ++ 0x3e, 0xb2, 0x47, 0xb5, 0x58, 0xc5, 0xa7, 0xb4, 0x82, 0x53, 0x2e, 0x53, ++ 0x95, 0x4e, 0x3d, 0xe4, 0x62, 0xe8, 0xa1, 0xaf, 0xae, 0xbf, 0xa9, 0xd2, ++ 0x22, 0x07, 0xbe, 0x71, 0x37, 0x2c, 0x5a, 0xa7, 0x6c, 0xaf, 0x14, 0xc0, ++ 0x6c, 0x2f, 0xbf, 0x4f, 0x15, 0xc2, 0x0f, 0x8b, 0xdc, 0x68, 0x45, 0xdf, ++ 0xf3, 0xa5, 0x7f, 0x11, 0x6a, 0x54, 0xcd, 0x67, 0xb9, 0x2e, 0x7d, 0x05, ++ 0xe3, 0x1c, 0x1d, 0xcc, 0x77, 0x8e, 0x97, 0xb1, 0xa0, 0x11, 0x09, 0x3d, ++ 0x90, 0x54, 0xfc, 0x7e, 0xbb, 0xbb, 0x21, 0x23, 0x03, 0x44, 0xbf, 0x7d, ++ 0x2c, 0xc9, 0x15, 0x42, 0xe5, 0xa0, 0x3b, 0xa2, 0xd1, 0x5b, 0x73, 0x81, ++ 0xff, 0xfa, 0x90, 0xfc, 0x27, 0x7b, 0x2f, 0x86, 0x9c, 0x1d, 0x14, 0x36, ++ 0x94, 0xa2, 0x6e, 0xe8, 0x9d, 0xa0, 0x5f, 0xfc, 0x5a, 0x0d, 0xa4, 0xd5, ++ 0x2f, 0x8d, 0xd6, 0x00, 0xfa, 0x93, 0x5b, 0x09, 0x7f, 0x42, 0x78, 0xcc, ++ 0x8c, 0x49, 0xda, 0xd9, 0xf6, 0x43, 0xe7, 0xe1, 0x3c, 0xa2, 0xe2, 0x70, ++ 0xe2, 0x6a, 0x99, 0xc5, 0xd6, 0xa2, 0xe3, 0x0b, 0xd4, 0x09, 0xac, 0x94, ++ 0xaf, 0xb7, 0xf0, 0xb3, 0x0c, 0x1e, 0xf5, 0x16, 0x4f, 0x53, 0x9a, 0xe3, ++ 0xcc, 0xe2, 0x0c, 0x4a, 0xb9, 0xe6, 0x06, 0xbb, 0xf7, 0x41, 0x43, 0x20, ++ 0x04, 0xee, 0x99, 0x2f, 0xd8, 0x9f, 0xda, 0x3f, 0xfd, 0x49, 0xb8, 0xc2, ++ 0xbd, 0xd9, 0xc5, 0x72, 0xfd, 0xe3, 0xce, 0x1c, 0xbc, 0xe4, 0x39, 0xac, ++ 0x2a, 0x99, 0xe9, 0xb4, 0x3e, 0x74, 0x10, 0xeb, 0xd5, 0x14, 0xcc, 0xdb, ++ 0xf1, 0x04, 0x63, 0x36, 0xfb, 0x1f, 0x2b, 0xe2, 0x73, 0xd4, 0xd8, 0x49, ++ 0x31, 0xa8, 0x55, 0xcc, 0xa7, 0x76, 0x36, 0x6e, 0x18, 0xdc, 0xb9, 0xb0, ++ 0x29, 0x99, 0xcf, 0x49, 0xbf, 0xf9, 0xdb, 0x7f, 0x24, 0x42, 0x02, 0xcb, ++ 0xc1, 0xaa, 0xcb, 0xba, 0x18, 0x85, 0x86, 0xc7, 0xf4, 0x1c, 0x62, 0x76, ++ 0xbc, 0x73, 0xfb, 0xe4, 0x15, 0xb8, 0xdd, 0x5d, 0xa6, 0x68, 0x39, 0xa5, ++ 0x3d, 0x33, 0xaf, 0xd5, 0x92, 0x4d, 0x48, 0xdb, 0x22, 0xc0, 0xdc, 0x49, ++ 0x5f, 0x7b, 0xa8, 0xd2, 0x62, 0x2d, 0xa7, 0x39, 0x93, 0x48, 0xe7, 0x6b, ++ 0x23, 0xba, 0xd4, 0xe0, 0xc1, 0x29, 0x55, 0xc4, 0x34, 0xe3, 0xac, 0x25, ++ 0xa7, 0x15, 0xad, 0xab, 0xb3, 0xb7, 0x25, 0xca, 0x37, 0x88, 0x40, 0x2e, ++ 0x47, 0x6e, 0x92, 0x20, 0x09, 0x2e, 0x5a, 0xec, 0xf2, 0xfb, 0xb3, 0xa0, ++ 0x16, 0xb6, 0x93, 0xf2, 0xf5, 0x8b, 0xfe, 0xaf, 0x25, 0xee, 0x2e, 0x98, ++ 0x6c, 0x0a, 0xfe, 0xae, 0x0b, 0x57, 0xf5, 0x9f, 0x3c, 0x80, 0xe9, 0x8b, ++ 0xaf, 0x92, 0x8a, 0xad, 0xe7, 0xa0, 0xe4, 0xe6, 0x0a, 0xa0, 0xc7, 0x83, ++ 0xb5, 0x48, 0x58, 0x5f, 0x55, 0x9e, 0x9b, 0x27, 0xcd, 0x31, 0x1f, 0x3e, ++ 0x50, 0x5a, 0x91, 0xad, 0x21, 0x1b, 0x97, 0x5b, 0xe8, 0xfa, 0x29, 0x8a, ++ 0xa4, 0x17, 0xe8, 0xab, 0x87, 0x02, 0xd6, 0x18, 0x8c, 0x9f, 0x65, 0xb7, ++ 0x2a, 0xfa, 0xde, 0x5f, 0x77, 0x30, 0x6c, 0x04, 0x22, 0xe6, 0x58, 0x26, ++ 0x14, 0x0d, 0x9c, 0x41, 0x0a, 0x82, 0x77, 0xdb, 0x40, 0xa1, 0x58, 0xac, ++ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb5, ++ 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, ++ 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, ++ 0x65, 0x64, 0x7e, 0x0a ++}; ++unsigned int hi_signed_2nd_len = 736; ++ ++unsigned char certificate_printable_der[] = { ++ 0x30, 0x82, 0x03, 0x39, 0x30, 0x82, 0x02, 0x21, 0xa0, 0x03, 0x02, 0x01, ++ 0x02, 0x02, 0x09, 0x00, 0xde, 0xf6, 0x22, 0xc4, 0xf2, 0xf1, 0x86, 0x02, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x0b, 0x05, 0x00, 0x30, 0x2a, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, ++ 0x04, 0x03, 0x13, 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, ++ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, ++ 0x43, 0x41, 0x20, 0x32, 0x20, 0x28, 0x62, 0x65, 0x74, 0x61, 0x29, 0x30, ++ 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x30, 0x33, 0x31, 0x31, 0x34, 0x31, ++ 0x39, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x37, 0x31, 0x30, 0x32, 0x35, ++ 0x31, 0x34, 0x31, 0x39, 0x32, 0x33, 0x5a, 0x30, 0x2f, 0x31, 0x2d, 0x30, ++ 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x52, 0x65, 0x64, 0x20, ++ 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, ++ 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, ++ 0x33, 0x20, 0x28, 0x62, 0x65, 0x74, 0x61, 0x29, 0x30, 0x82, 0x01, 0x22, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, ++ 0x02, 0x82, 0x01, 0x01, 0x00, 0xbd, 0xda, 0xa1, 0xed, 0x8d, 0x8e, 0x15, ++ 0x5c, 0xf8, 0x01, 0x77, 0x48, 0x4a, 0x60, 0x96, 0xf9, 0x27, 0xfa, 0xe2, ++ 0xb1, 0x69, 0x0f, 0x51, 0x19, 0x52, 0x7e, 0xc4, 0x34, 0x8e, 0xe1, 0x9b, ++ 0x9c, 0xa4, 0xb1, 0x5c, 0xd6, 0x81, 0x98, 0x78, 0xfe, 0xa9, 0xe5, 0x0b, ++ 0x00, 0xba, 0x9c, 0x64, 0x7e, 0xc7, 0xcc, 0x72, 0xb1, 0x73, 0x4b, 0x11, ++ 0x07, 0x52, 0xf0, 0x20, 0x96, 0x8b, 0x99, 0x39, 0xde, 0xdb, 0xfa, 0x3d, ++ 0x45, 0xe2, 0x98, 0x7b, 0x0c, 0x41, 0xe4, 0x0c, 0xb5, 0x5d, 0x92, 0x74, ++ 0x39, 0x96, 0xe1, 0x97, 0x97, 0xa1, 0xad, 0x2e, 0xcc, 0xd0, 0x1b, 0x4d, ++ 0x9d, 0xbd, 0x3e, 0xa9, 0x36, 0x8e, 0xcc, 0xc7, 0x5f, 0x6a, 0x7d, 0x39, ++ 0x5e, 0x0b, 0x8d, 0xca, 0xe4, 0x83, 0xe9, 0x3b, 0x5c, 0x86, 0x47, 0xd4, ++ 0xba, 0x7d, 0x98, 0x26, 0xa1, 0xf4, 0xe8, 0x90, 0x6b, 0x0f, 0xf1, 0x6b, ++ 0x8c, 0xe3, 0xa2, 0x80, 0x3c, 0x96, 0xf1, 0x0a, 0xb6, 0x66, 0xc0, 0x4b, ++ 0x61, 0xf7, 0x74, 0xcd, 0xd3, 0x7b, 0x8e, 0x5e, 0x39, 0xda, 0x99, 0x20, ++ 0x33, 0x93, 0xd3, 0xf0, 0x7f, 0xad, 0x35, 0xe9, 0x88, 0x8d, 0x9c, 0xbf, ++ 0x65, 0xf1, 0x47, 0x02, 0xf9, 0x7c, 0xed, 0x27, 0x5f, 0x4a, 0x65, 0x3c, ++ 0xcf, 0x5f, 0x0e, 0x88, 0x95, 0x74, 0xde, 0xfb, 0x9e, 0x2e, 0x91, 0x9b, ++ 0x45, 0x37, 0xc8, 0x85, 0xff, 0xe3, 0x41, 0x70, 0xfe, 0xd5, 0xef, 0x0e, ++ 0x82, 0x22, 0x08, 0xb7, 0x3b, 0x44, 0x3e, 0xdc, 0x5b, 0x7f, 0xba, 0xbf, ++ 0xe6, 0x58, 0x9d, 0x02, 0x6e, 0x75, 0xbf, 0x50, 0xec, 0xcf, 0x3f, 0xa5, ++ 0x91, 0x0a, 0xe2, 0x59, 0x2c, 0xc3, 0xe7, 0x05, 0x03, 0xe8, 0xf2, 0x6f, ++ 0x2a, 0x04, 0x68, 0x9a, 0x31, 0x32, 0x8f, 0x04, 0x35, 0xcd, 0x1f, 0x34, ++ 0xcc, 0x4f, 0x79, 0x5a, 0x99, 0x8d, 0x9d, 0x5c, 0xf5, 0x02, 0x03, 0x01, ++ 0x00, 0x01, 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, ++ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, ++ 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1d, 0x06, ++ 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x65, 0xc5, 0xbe, 0xca, ++ 0xe6, 0x59, 0x6a, 0xfd, 0x6c, 0x71, 0xc4, 0xa7, 0x98, 0xc6, 0x25, 0x8d, ++ 0x7b, 0x67, 0x05, 0xd0, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, ++ 0x18, 0x30, 0x16, 0x80, 0x14, 0x81, 0xf8, 0xee, 0x47, 0x5c, 0x3e, 0xed, ++ 0xfb, 0xce, 0xa5, 0x84, 0xbe, 0xd7, 0xae, 0xdb, 0xd3, 0x7d, 0x64, 0xb3, ++ 0x2a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, ++ 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x66, 0x1e, 0x3d, ++ 0x1d, 0x53, 0x33, 0xde, 0x4e, 0xc7, 0xc4, 0xf4, 0xdf, 0xda, 0x18, 0x19, ++ 0x8a, 0xa9, 0xff, 0xe2, 0x63, 0x2b, 0xbe, 0xf2, 0x61, 0x63, 0xe2, 0xf6, ++ 0xed, 0x47, 0x1a, 0x71, 0x02, 0xec, 0x2a, 0xef, 0x89, 0x77, 0xe3, 0xfd, ++ 0x86, 0x69, 0xf1, 0x3f, 0x0d, 0xf9, 0x6e, 0xf9, 0x3b, 0xad, 0x26, 0x47, ++ 0xb7, 0xf2, 0x0d, 0xad, 0x23, 0xa3, 0x67, 0x3b, 0xcb, 0x6d, 0x9e, 0x03, ++ 0x0f, 0xbc, 0x69, 0x73, 0x9f, 0xd4, 0xa5, 0x0f, 0x6f, 0xf8, 0xab, 0x4d, ++ 0x36, 0xd1, 0xe0, 0xe0, 0x5d, 0x20, 0x43, 0x90, 0xc4, 0x65, 0x61, 0x93, ++ 0xe2, 0x0f, 0x51, 0x59, 0x0a, 0xf7, 0x88, 0x70, 0x57, 0xb9, 0x04, 0xa9, ++ 0x32, 0x57, 0x9c, 0xb3, 0x57, 0x38, 0x8b, 0x8e, 0x46, 0xc8, 0x32, 0x6c, ++ 0xb4, 0xf3, 0x96, 0x7f, 0x4b, 0xf0, 0x88, 0xf9, 0x7f, 0xe2, 0x71, 0xe1, ++ 0x8b, 0xe2, 0x14, 0xf1, 0x4b, 0x25, 0x00, 0x48, 0x1c, 0x7e, 0xe5, 0x8d, ++ 0x65, 0x2d, 0xeb, 0x72, 0x4f, 0x92, 0x44, 0xf3, 0xe6, 0xe0, 0xd0, 0xdf, ++ 0x85, 0xa8, 0x13, 0x4a, 0xfb, 0x99, 0xca, 0x14, 0x2c, 0x97, 0x80, 0x93, ++ 0x27, 0xd3, 0x20, 0xf8, 0x6d, 0x29, 0x28, 0x2c, 0xb9, 0x77, 0xea, 0xb1, ++ 0x63, 0xbd, 0x7d, 0x53, 0xfd, 0x4a, 0x62, 0x64, 0x0b, 0x98, 0xa8, 0xae, ++ 0x11, 0xfc, 0x6e, 0x8d, 0x63, 0xd4, 0x15, 0x55, 0xc6, 0x4c, 0x74, 0xf5, ++ 0x5f, 0xa0, 0xb9, 0x2c, 0x2d, 0x9a, 0x7a, 0x87, 0x6e, 0xf0, 0x5e, 0x25, ++ 0xed, 0xfc, 0xd8, 0xc4, 0x34, 0x33, 0x32, 0xad, 0x01, 0xd4, 0x4b, 0x49, ++ 0x51, 0xc2, 0x07, 0x7f, 0x90, 0x6d, 0xea, 0xf5, 0x4c, 0x41, 0x71, 0x64, ++ 0xeb, 0x1f, 0x29, 0xa3, 0x1f, 0x64, 0xa2, 0x1e, 0x0e, 0x6f, 0xa1, 0x67, ++ 0x99, 0x8d, 0x98, 0x1c, 0xb8, 0x53, 0x9d, 0x30, 0x1d, 0xae, 0x32, 0x56, ++ 0xd2 ++}; ++unsigned int certificate_printable_der_len = 829; diff --git a/SOURCES/0172-Introduce-function-grub_debug_is_enabled-void-return.patch b/SOURCES/0172-Introduce-function-grub_debug_is_enabled-void-return.patch deleted file mode 100644 index 4e4718b..0000000 --- a/SOURCES/0172-Introduce-function-grub_debug_is_enabled-void-return.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Mon, 25 Nov 2019 09:29:53 +0100 -Subject: [PATCH] Introduce function grub_debug_is_enabled(void) returning 1 if - 'debug' is in the environment and not empty -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Renaud Métrich ---- - grub-core/kern/misc.c | 13 +++++++++++++ - include/grub/misc.h | 1 + - 2 files changed, 14 insertions(+) - -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index 9f54b6b7d2d..a186ad3dd41 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -163,6 +163,19 @@ int grub_err_printf (const char *fmt, ...) - __attribute__ ((alias("grub_printf"))); - #endif - -+/* Return 1 if 'debug' is set and not empty */ -+int -+grub_debug_is_enabled (void) -+{ -+ const char *debug; -+ -+ debug = grub_env_get ("debug"); -+ if (!debug || debug[0] == '\0') -+ return 0; -+ -+ return 1; -+} -+ - int - grub_debug_enabled (const char * condition) - { -diff --git a/include/grub/misc.h b/include/grub/misc.h -index 3adc4036e3b..6c4aa85ac50 100644 ---- a/include/grub/misc.h -+++ b/include/grub/misc.h -@@ -340,6 +340,7 @@ grub_puts (const char *s) - } - - int EXPORT_FUNC(grub_puts_) (const char *s); -+int EXPORT_FUNC(grub_debug_is_enabled) (void); - int EXPORT_FUNC(grub_debug_enabled) (const char *condition); - void EXPORT_FUNC(grub_real_dprintf) (const char *file, - const int line, diff --git a/SOURCES/0172-appended-signatures-documentation.patch b/SOURCES/0172-appended-signatures-documentation.patch new file mode 100644 index 0000000..eb58046 --- /dev/null +++ b/SOURCES/0172-appended-signatures-documentation.patch @@ -0,0 +1,341 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 1 Oct 2020 13:02:09 +1000 +Subject: [PATCH] appended signatures: documentation + +This explains how appended signatures can be used to form part of +a secure boot chain, and documents the commands and variables +introduced. + +Signed-off-by: Daniel Axtens +--- + docs/grub.texi | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 182 insertions(+), 17 deletions(-) + +diff --git a/docs/grub.texi b/docs/grub.texi +index afbde7c1f7..4816be8561 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -3214,6 +3214,7 @@ These variables have special meaning to GRUB. + + @menu + * biosnum:: ++* check_appended_signatures:: + * check_signatures:: + * chosen:: + * cmdpath:: +@@ -3273,11 +3274,18 @@ For an alternative approach which also changes BIOS drive mappings for the + chain-loaded system, @pxref{drivemap}. + + ++@node check_appended_signatures ++@subsection check_appended_signatures ++ ++This variable controls whether GRUB enforces appended signature validation on ++certain loaded files. @xref{Using appended signatures}. ++ ++ + @node check_signatures + @subsection check_signatures + +-This variable controls whether GRUB enforces digital signature +-validation on loaded files. @xref{Using digital signatures}. ++This variable controls whether GRUB enforces GPG-style digital signature ++validation on loaded files. @xref{Using GPG-style digital signatures}. + + @node chosen + @subsection chosen +@@ -3994,6 +4002,7 @@ you forget a command, you can run the command @command{help} + * date:: Display or set current date and time + * devicetree:: Load a device tree blob + * distrust:: Remove a pubkey from trusted keys ++* distrust_certificate:: Remove a certificate from the list of trusted certificates + * drivemap:: Map a drive to another + * echo:: Display a line of text + * eval:: Evaluate agruments as GRUB commands +@@ -4010,6 +4019,7 @@ you forget a command, you can run the command @command{help} + * keystatus:: Check key modifier status + * linux:: Load a Linux kernel + * linux16:: Load a Linux kernel (16-bit mode) ++* list_certificates:: List trusted certificates + * list_env:: List variables in environment block + * list_trusted:: List trusted public keys + * load_env:: Load variables from environment block +@@ -4047,8 +4057,10 @@ you forget a command, you can run the command @command{help} + * test:: Check file types and compare values + * true:: Do nothing, successfully + * trust:: Add public key to list of trusted keys ++* trust_certificate:: Add an x509 certificate to the list of trusted certificates + * unset:: Unset an environment variable + @comment * vbeinfo:: List available video modes ++* verify_appended:: Verify appended digital signature + * verify_detached:: Verify detached digital signature + * videoinfo:: List available video modes + @comment * xen_*:: Xen boot commands for AArch64 +@@ -4376,9 +4388,28 @@ These keys are used to validate signatures when environment variable + @code{check_signatures} is set to @code{enforce} + (@pxref{check_signatures}), and by some invocations of + @command{verify_detached} (@pxref{verify_detached}). @xref{Using +-digital signatures}, for more information. ++GPG-style digital signatures}, for more information. + @end deffn + ++ ++@node distrust_certificate ++@subsection distrust_certificate ++ ++@deffn Command distrust_certificate cert_number ++Remove the x509 certificate numbered @var{cert_number} from GRUB's keyring of ++trusted x509 certificates for verifying appended signatures. ++ ++@var{cert_number} is the certificate number as listed by ++@command{list_certificates} (@pxref{list_certificates}). ++ ++These certificates are used to validate appended signatures when environment ++variable @code{check_appended_signatures} is set to @code{enforce} or ++@code{forced} (@pxref{check_appended_signatures}), and by ++@command{verify_appended} (@pxref{verify_appended}). See ++@xref{Using appended signatures} for more information. ++@end deffn ++ ++ + @node drivemap + @subsection drivemap + +@@ -4636,6 +4667,21 @@ This command is only available on x86 systems. + @end deffn + + ++@node list_certificates ++@subsection list_certificates ++ ++@deffn Command list_certificates ++List all x509 certificates trusted by GRUB for validating appended signatures. ++The output is a numbered list of certificates, showing the certificate's serial ++number and Common Name. ++ ++The certificate number can be used as an argument to ++@command{distrust_certificate} (@pxref{distrust_certificate}). ++ ++See @xref{Using appended signatures} for more information. ++@end deffn ++ ++ + @node list_env + @subsection list_env + +@@ -4655,7 +4701,7 @@ The output is in GPG's v4 key fingerprint format (i.e., the output of + @code{gpg --fingerprint}). The least significant four bytes (last + eight hexadecimal digits) can be used as an argument to + @command{distrust} (@pxref{distrust}). +-@xref{Using digital signatures}, for more information about uses for ++@xref{Using GPG-style digital signatures}, for more information about uses for + these keys. + @end deffn + +@@ -4690,8 +4736,13 @@ When used with care, @option{--skip-sig} and the whitelist enable an + administrator to configure a system to boot only signed + configurations, but to allow the user to select from among multiple + configurations, and to enable ``one-shot'' boot attempts and +-``savedefault'' behavior. @xref{Using digital signatures}, for more ++``savedefault'' behavior. @xref{Using GPG-style digital signatures}, for more + information. ++ ++Extra care should be taken when combining this command with appended signatures ++(@pxref{Using appended signatures}), as this file is not validated by an ++appended signature and could set @code{check_appended_signatures=no} if GRUB is ++not in @pxref{Lockdown} mode. + @end deffn + + +@@ -4987,7 +5038,7 @@ read. It is possible to modify a digitally signed environment block + file from within GRUB using this command, such that its signature will + no longer be valid on subsequent boots. Care should be taken in such + advanced configurations to avoid rendering the system +-unbootable. @xref{Using digital signatures}, for more information. ++unbootable. @xref{Using GPG-style digital signatures}, for more information. + @end deffn + + +@@ -5387,11 +5438,32 @@ signatures when environment variable @code{check_signatures} is set to + must itself be properly signed. The @option{--skip-sig} option can be + used to disable signature-checking when reading @var{pubkey_file} + itself. It is expected that @option{--skip-sig} is useful for testing +-and manual booting. @xref{Using digital signatures}, for more ++and manual booting. @xref{Using GPG-style digital signatures}, for more + information. + @end deffn + + ++@node trust_certificate ++@subsection trust_certificate ++ ++@deffn Command trust_certificate x509_certificate ++Read an DER-formatted x509 certificate from the file @var{x509_certificate} ++and add it to GRUB's internal list of trusted x509 certificates. These ++certificates are used to validate appended signatures when the environment ++variable @code{check_appended_signatures} is set to @code{enforce} or ++@code{forced}. ++ ++Note that if @code{check_appended_signatures} is set to @code{enforce} or ++@code{forced} when @command{trust_certificate} is executed, then ++@var{x509_certificate} must itself bear an appended signature. (It is not ++sufficient that @var{x509_certificate} be signed by a trusted certificate ++according to the x509 rules: grub does not include support for validating ++signatures within x509 certificates themselves.) ++ ++See @xref{Using appended signatures} for more information. ++@end deffn ++ ++ + @node unset + @subsection unset + +@@ -5410,6 +5482,18 @@ only on PC BIOS platforms. + @end deffn + @end ignore + ++@node verify_appended ++@subsection verify_appended ++ ++@deffn Command verify_appended file ++Verifies an appended signature on @var{file} against the trusted certificates ++known to GRUB (See @pxref{list_certificates}, @pxref{trust_certificate}, and ++@pxref{distrust_certificate}). ++ ++Exit code @code{$?} is set to 0 if the signature validates ++successfully. If validation fails, it is set to a non-zero value. ++See @xref{Using appended signatures}, for more information. ++@end deffn + + @node verify_detached + @subsection verify_detached +@@ -5428,7 +5512,7 @@ tried. + + Exit code @code{$?} is set to 0 if the signature validates + successfully. If validation fails, it is set to a non-zero value. +-@xref{Using digital signatures}, for more information. ++@xref{Using GPG-style digital signatures}, for more information. + @end deffn + + @node videoinfo +@@ -5811,13 +5895,14 @@ environment variables and commands are listed in the same order. + @chapter Security + + @menu +-* Authentication and authorisation:: Users and access control +-* Using digital signatures:: Booting digitally signed code +-* UEFI secure boot and shim:: Booting digitally signed PE files +-* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation +-* Measured Boot:: Measuring boot components +-* Lockdown:: Lockdown when booting on a secure setup +-* Signing GRUB itself:: Ensuring the integrity of the GRUB core image ++* Authentication and authorisation:: Users and access control ++* Using GPG-style digital signatures:: Booting digitally signed code ++* Using appended signatures:: An alternative approach to booting digitally signed code ++* UEFI secure boot and shim:: Booting digitally signed PE files ++* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation ++* Measured Boot:: Measuring boot components ++* Lockdown:: Lockdown when booting on a secure setup ++* Signing GRUB itself:: Ensuring the integrity of the GRUB core image + @end menu + + @node Authentication and authorisation +@@ -5891,8 +5976,8 @@ generating configuration files with authentication. You can use + adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} + commands. + +-@node Using digital signatures +-@section Using digital signatures in GRUB ++@node Using GPG-style digital signatures ++@section Using GPG-style digital signatures in GRUB + + GRUB's @file{core.img} can optionally provide enforcement that all files + subsequently read from disk are covered by a valid digital signature. +@@ -5985,6 +6070,86 @@ or BIOS) configuration to cause the machine to boot from a different + (attacker-controlled) device. GRUB is at best only one link in a + secure boot chain. + ++@node Using appended signatures ++@section Using appended signatures in GRUB ++ ++GRUB supports verifying Linux-style 'appended signatures' for secure boot. ++Appended signatures are PKCS#7 messages containing a signature over the ++contents of a file, plus some metadata, appended to the end of a file. A file ++with an appended signature ends with the magic string: ++ ++@example ++~Module signature appended~\n ++@end example ++ ++where @code{\n} represents the line-feed character, @code{0x0a}. ++ ++Certificates can be managed at boot time using the @pxref{trust_certificate}, ++@pxref{distrust_certificate} and @pxref{list_certificates} commands. ++Certificates can also be built in to the core image using the @code{--x509} ++parameter to @command{grub-install} or @command{grub-mkimage}. ++ ++A file can be explictly verified using the @pxref{verify_appended} command. ++ ++Only signatures made with the SHA-256 or SHA-512 hash algorithm are supported, ++and only RSA signatures are supported. ++ ++A file can be signed with the @command{sign-file} utility supplied with the ++Linux kernel source. For example, if you have @code{signing.key} as the private ++key and @code{certificate.der} as the x509 certificate containing the public key: ++ ++@example ++sign-file SHA256 signing.key certificate.der vmlinux vmlinux.signed ++@end example ++ ++Enforcement of signature verification is controlled by the ++@code{check_appended_signatures} variable. ++ ++@itemize ++@item @samp{no}: no verification is performed. This is the default when GRUB ++ is not in @pxref{Lockdown} mode. ++@item @samp{enforce}: verification is performed. Verification can be disabled ++ by setting the variable back to @samp{no}. ++@item @samp{forced}: verification is performed and cannot be disabled. This is ++ set when GRUB is in Lockdown when the appendedsig module is loaded. ++@end itemize ++ ++Unlike GPG-style signatures, not all files loaded by GRUB are required to be ++signed. Once verification is turned on, the following file types will have ++appended signatures verified: ++ ++@itemize ++@item Linux kernels ++@item GRUB modules, except those built into the core image ++@item Any new certificate files to be trusted ++@end itemize ++ ++ACPI tables and Device Tree images will not be checked for appended signatures ++but must be verified by another mechanism such as GPG-style signatures before ++they will be loaded. ++ ++Unless lockdown mode is enabled, signature checking does @strong{not} ++stop an attacker with console access from dropping manually to the GRUB ++console and executing: ++ ++@example ++set check_appended_signatures=no ++@end example ++ ++Refer to the section on password-protecting GRUB (@pxref{Authentication ++and authorisation}) for more information on preventing this. ++ ++Additionally, unless lockdown mode is enabled: ++ ++@itemize ++@item Special care must be taken around the @command{loadenv} command, which ++ can be used to turn off @code{check_appended_signature}. ++ ++@item If the grub configuration file is loaded from the disk, anyone who can ++ modify the file on disk can turn off @code{check_appended_signature}. ++ Consider embedding the configuration into the core grub image. ++@end itemize ++ + @node UEFI secure boot and shim + @section UEFI secure boot and shim support + diff --git a/SOURCES/0173-Don-t-clear-screen-when-debugging-is-enabled.patch b/SOURCES/0173-Don-t-clear-screen-when-debugging-is-enabled.patch deleted file mode 100644 index d2a5988..0000000 --- a/SOURCES/0173-Don-t-clear-screen-when-debugging-is-enabled.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Sat, 23 Nov 2019 16:23:54 +0100 -Subject: [PATCH] Don't clear screen when debugging is enabled -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Renaud Métrich ---- - grub-core/normal/main.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index e349303c29b..155bf366da2 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -210,7 +210,8 @@ void - grub_normal_init_page (struct grub_term_output *term, - int y __attribute__((__unused__))) - { -- grub_term_cls (term); -+ if (! grub_debug_is_enabled ()) -+ grub_term_cls (term); - - #if 0 - grub_ssize_t msg_len; diff --git a/SOURCES/0173-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch b/SOURCES/0173-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch new file mode 100644 index 0000000..c90cc7e --- /dev/null +++ b/SOURCES/0173-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 28 Sep 2020 11:11:17 +1000 +Subject: [PATCH] ieee1275: enter lockdown based on /ibm,secure-boot + +If the 'ibm,secure-boot' property of the root node is 2 or greater, +enter lockdown. + +Signed-off-by: Daniel Axtens +--- + grub-core/Makefile.core.def | 1 + + grub-core/kern/ieee1275/init.c | 27 +++++++++++++++++++++++++++ + include/grub/lockdown.h | 3 ++- + docs/grub.texi | 4 ++-- + 4 files changed, 32 insertions(+), 3 deletions(-) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 9ea5fb38f1..4a57de975e 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -323,6 +323,7 @@ kernel = { + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; + powerpc_ieee1275 = kern/powerpc/compiler-rt.S; ++ powerpc_ieee1275 = kern/lockdown.c; + + sparc64_ieee1275 = kern/sparc64/cache.S; + sparc64_ieee1275 = kern/sparc64/dl.c; +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 937c1bc44c..fc7d971272 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -44,6 +44,7 @@ + #ifdef __sparc__ + #include + #endif ++#include + + /* The minimal heap size we can live with. */ + #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) +@@ -271,6 +272,30 @@ grub_parse_cmdline (void) + } + } + ++static void ++grub_get_ieee1275_secure_boot (void) ++{ ++ grub_ieee1275_phandle_t root; ++ int rc; ++ grub_uint32_t is_sb; ++ ++ grub_ieee1275_finddevice ("/", &root); ++ ++ rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &is_sb, ++ sizeof (is_sb), 0); ++ ++ /* ibm,secure-boot: ++ * 0 - disabled ++ * 1 - audit ++ * 2 - enforce ++ * 3 - enforce + OS-specific behaviour ++ * ++ * We only support enforce. ++ */ ++ if (rc >= 0 && is_sb >= 2) ++ grub_lockdown (); ++} ++ + grub_addr_t grub_modbase; + + void +@@ -296,6 +321,8 @@ grub_machine_init (void) + #else + grub_install_get_time_ms (grub_rtc_get_time_ms); + #endif ++ ++ grub_get_ieee1275_secure_boot (); + } + + void +diff --git a/include/grub/lockdown.h b/include/grub/lockdown.h +index 40531fa823..ebfee4bf06 100644 +--- a/include/grub/lockdown.h ++++ b/include/grub/lockdown.h +@@ -24,7 +24,8 @@ + #define GRUB_LOCKDOWN_DISABLED 0 + #define GRUB_LOCKDOWN_ENABLED 1 + +-#ifdef GRUB_MACHINE_EFI ++#if defined(GRUB_MACHINE_EFI) || \ ++ (defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)) + extern void + EXPORT_FUNC (grub_lockdown) (void); + extern int +diff --git a/docs/grub.texi b/docs/grub.texi +index 4816be8561..a4da9c2a1b 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -6227,8 +6227,8 @@ Measured boot is currently only supported on EFI platforms. + @section Lockdown when booting on a secure setup + + The GRUB can be locked down when booted on a secure boot environment, for example +-if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will +-be restricted and some operations/commands cannot be executed. ++if UEFI or Power secure boot is enabled. On a locked down configuration, the ++GRUB will be restricted and some operations/commands cannot be executed. + + The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down. + Otherwise it does not exit. diff --git a/SOURCES/0174-grub_file_-instrumentation-new-file-debug-tag.patch b/SOURCES/0174-grub_file_-instrumentation-new-file-debug-tag.patch deleted file mode 100644 index 0cc6b8c..0000000 --- a/SOURCES/0174-grub_file_-instrumentation-new-file-debug-tag.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Fri, 29 Nov 2019 11:02:00 +0100 -Subject: [PATCH] grub_file_* instrumentation (new 'file' debug tag) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Renaud Métrich ---- - grub-core/kern/file.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c -index 58454458c47..e19aea3e514 100644 ---- a/grub-core/kern/file.c -+++ b/grub-core/kern/file.c -@@ -66,6 +66,8 @@ grub_file_open (const char *name, enum grub_file_type type) - const char *file_name; - grub_file_filter_id_t filter; - -+ grub_dprintf ("file", "Opening `%s' ...\n", name); -+ - device_name = grub_file_get_device_name (name); - if (grub_errno) - goto fail; -@@ -128,6 +130,8 @@ grub_file_open (const char *name, enum grub_file_type type) - if (!file) - grub_file_close (last_file); - -+ grub_dprintf ("file", "Opening `%s' succeeded.\n", name); -+ - return file; - - fail: -@@ -138,6 +142,8 @@ grub_file_open (const char *name, enum grub_file_type type) - - grub_free (file); - -+ grub_dprintf ("file", "Opening `%s' failed.\n", name); -+ - return 0; - } - -@@ -169,6 +175,7 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) - - if (len == 0) - return 0; -+ - read_hook = file->read_hook; - read_hook_data = file->read_hook_data; - if (!file->read_hook) -@@ -189,11 +196,18 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) - grub_err_t - grub_file_close (grub_file_t file) - { -+ grub_dprintf ("file", "Closing `%s' ...\n", file->name); - if (file->fs->fs_close) - (file->fs->fs_close) (file); - - if (file->device) - grub_device_close (file->device); -+ -+ if (grub_errno == GRUB_ERR_NONE) -+ grub_dprintf ("file", "Closing `%s' succeeded.\n", file->name); -+ else -+ grub_dprintf ("file", "Closing `%s' failed with %d.\n", file->name, grub_errno); -+ - grub_free (file->name); - grub_free (file); - return grub_errno; diff --git a/SOURCES/0174-ieee1275-drop-HEAP_MAX_ADDR-HEAP_MIN_SIZE.patch b/SOURCES/0174-ieee1275-drop-HEAP_MAX_ADDR-HEAP_MIN_SIZE.patch new file mode 100644 index 0000000..a40caea --- /dev/null +++ b/SOURCES/0174-ieee1275-drop-HEAP_MAX_ADDR-HEAP_MIN_SIZE.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Wed, 14 Apr 2021 20:10:23 +1000 +Subject: [PATCH] ieee1275: drop HEAP_MAX_ADDR, HEAP_MIN_SIZE + +HEAP_MAX_ADDR is confusing. Currently it is set to 32MB, except +on ieee1275 on x86, where it is 64MB. + +There is a comment which purports to explain it: + +/* If possible, we will avoid claiming heap above this address, because it + seems to cause relocation problems with OSes that link at 4 MiB */ + +This doesn't make a lot of sense when the constants are well above 4MB +already. It was not always this way. Prior to +commit 7b5d0fe4440c ("Increase heap limit") in 2010, HEAP_MAX_SIZE and +HEAP_MAX_ADDR were indeed 4MB. However, when the constants were increased +the comment was left unchanged. + +It's been over a decade. It doesn't seem like we have problems with +claims over 4MB on powerpc or x86 ieee1275. (sparc does things completely +differently and never used the constant.) + +Drop the constant and the check. + +The only use of HEAP_MIN_SIZE was to potentially override the +HEAP_MAX_ADDR check. It is now unused. Remove it. + +Signed-off-by: Daniel Axtens +--- + grub-core/kern/ieee1275/init.c | 17 ----------------- + 1 file changed, 17 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index fc7d971272..0dcd114ce5 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -46,9 +46,6 @@ + #endif + #include + +-/* The minimal heap size we can live with. */ +-#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) +- + /* The maximum heap size we're going to claim */ + #ifdef __i386__ + #define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) +@@ -56,14 +53,6 @@ + #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) + #endif + +-/* If possible, we will avoid claiming heap above this address, because it +- seems to cause relocation problems with OSes that link at 4 MiB */ +-#ifdef __i386__ +-#define HEAP_MAX_ADDR (unsigned long) (64 * 1024 * 1024) +-#else +-#define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024) +-#endif +- + extern char _end[]; + + #ifdef __sparc__ +@@ -185,12 +174,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + if (*total + len > HEAP_MAX_SIZE) + len = HEAP_MAX_SIZE - *total; + +- /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */ +- if ((addr < HEAP_MAX_ADDR) && /* if it's too late, don't bother */ +- (addr + len > HEAP_MAX_ADDR) && /* if it wasn't available anyway, don't bother */ +- (*total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE)) /* only limit ourselves when we can afford to */ +- len = HEAP_MAX_ADDR - addr; +- + /* In theory, firmware should already prevent this from happening by not + listing our own image in /memory/available. The check below is intended + as a safeguard in case that doesn't happen. However, it doesn't protect diff --git a/SOURCES/0175-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch b/SOURCES/0175-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch new file mode 100644 index 0000000..5728f26 --- /dev/null +++ b/SOURCES/0175-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch @@ -0,0 +1,315 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Sat, 8 May 2021 02:27:58 +0200 +Subject: [PATCH] appendedsig/x509: Also handle the Extended Key Usage + extension + +Red Hat certificates have both Key Usage and Extended Key Usage extensions +present, but the appended signatures x509 parser doesn't handle the latter +and so buils due finding an unrecognised critical extension: + +Error loading initial key: +../../grub-core/commands/appendedsig/x509.c:780:Unhandled critical x509 extension with OID 2.5.29.37 + +Fix this by also parsing the Extended Key Usage extension and handle it by +verifying that the certificate has a single purpose, that is code signing. + +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Daniel Axtens +--- + grub-core/commands/appendedsig/x509.c | 94 ++++++++++++++++++++++++++++++- + grub-core/tests/appended_signature_test.c | 29 +++++++++- + grub-core/tests/appended_signatures.h | 81 ++++++++++++++++++++++++++ + 3 files changed, 201 insertions(+), 3 deletions(-) + +diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c +index 2b38b3670a..42ec65c54a 100644 +--- a/grub-core/commands/appendedsig/x509.c ++++ b/grub-core/commands/appendedsig/x509.c +@@ -47,6 +47,12 @@ const char *keyUsage_oid = "2.5.29.15"; + */ + const char *basicConstraints_oid = "2.5.29.19"; + ++/* ++ * RFC 5280 4.2.1.12 Extended Key Usage ++ */ ++const char *extendedKeyUsage_oid = "2.5.29.37"; ++const char *codeSigningUsage_oid = "1.3.6.1.5.5.7.3.3"; ++ + /* + * RFC 3279 2.3.1 + * +@@ -637,6 +643,77 @@ cleanup: + return err; + } + ++/* ++ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId ++ * ++ * KeyPurposeId ::= OBJECT IDENTIFIER ++ */ ++static grub_err_t ++verify_extended_key_usage (grub_uint8_t * value, int value_size) ++{ ++ asn1_node extendedasn; ++ int result, count; ++ grub_err_t err = GRUB_ERR_NONE; ++ char usage[MAX_OID_LEN]; ++ int usage_size = sizeof (usage); ++ ++ result = ++ asn1_create_element (_gnutls_pkix_asn, "PKIX1.ExtKeyUsageSyntax", ++ &extendedasn); ++ if (result != ASN1_SUCCESS) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Could not create ASN.1 structure for Extended Key Usage"); ++ } ++ ++ result = asn1_der_decoding2 (&extendedasn, value, &value_size, ++ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error parsing DER for Extended Key Usage: %s", ++ asn1_error); ++ goto cleanup; ++ } ++ ++ /* ++ * If EKUs are present, there must be exactly 1 and it must be a ++ * codeSigning usage. ++ */ ++ result = asn1_number_of_elements(extendedasn, "", &count); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error counting number of Extended Key Usages: %s", ++ asn1_strerror (result)); ++ goto cleanup; ++ } ++ ++ result = asn1_read_value (extendedasn, "?1", usage, &usage_size); ++ if (result != ASN1_SUCCESS) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Error reading Extended Key Usage: %s", ++ asn1_strerror (result)); ++ goto cleanup; ++ } ++ ++ if (grub_strncmp (codeSigningUsage_oid, usage, usage_size) != 0) ++ { ++ err = ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unexpected Extended Key Usage OID, got: %s", ++ usage); ++ goto cleanup; ++ } ++ ++cleanup: ++ asn1_delete_structure (&extendedasn); ++ return err; ++} + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension +@@ -660,7 +737,7 @@ verify_extensions (asn1_node cert) + { + int result; + int ext, num_extensions = 0; +- int usage_present = 0, constraints_present = 0; ++ int usage_present = 0, constraints_present = 0, extended_usage_present = 0; + char *oid_path, *critical_path, *value_path; + char extnID[MAX_OID_LEN]; + int extnID_size; +@@ -754,6 +831,15 @@ verify_extensions (asn1_node cert) + } + constraints_present++; + } ++ else if (grub_strncmp (extendedKeyUsage_oid, extnID, extnID_size) == 0) ++ { ++ err = verify_extended_key_usage (value, value_size); ++ if (err != GRUB_ERR_NONE) ++ { ++ goto cleanup_value; ++ } ++ extended_usage_present++; ++ } + else if (grub_strncmp ("TRUE", critical, critical_size) == 0) + { + /* +@@ -785,6 +871,12 @@ verify_extensions (asn1_node cert) + "Unexpected number of basic constraints extensions - expected 1, got %d", + constraints_present); + } ++ if (extended_usage_present > 1) ++ { ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "Unexpected number of Extended Key Usage extensions - expected 0 or 1, got %d", ++ extended_usage_present); ++ } + return GRUB_ERR_NONE; + + cleanup_value: +diff --git a/grub-core/tests/appended_signature_test.c b/grub-core/tests/appended_signature_test.c +index 88a485200d..dbba061662 100644 +--- a/grub-core/tests/appended_signature_test.c ++++ b/grub-core/tests/appended_signature_test.c +@@ -111,6 +111,22 @@ static struct grub_procfs_entry certificate_printable_der_entry = { + .get_contents = get_certificate_printable_der + }; + ++static char * ++get_certificate_eku_der (grub_size_t * sz) ++{ ++ char *ret; ++ *sz = certificate_eku_der_len; ++ ret = grub_malloc (*sz); ++ if (ret) ++ grub_memcpy (ret, certificate_eku_der, *sz); ++ return ret; ++} ++ ++static struct grub_procfs_entry certificate_eku_der_entry = { ++ .name = "certificate_eku.der", ++ .get_contents = get_certificate_eku_der ++}; ++ + + static void + do_verify (const char *f, int is_valid) +@@ -149,6 +165,7 @@ appended_signature_test (void) + char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL }; + char *trust_args_printable[] = { (char *) "(proc)/certificate_printable.der", + NULL }; ++ char *trust_args_eku[] = { (char *) "(proc)/certificate_eku.der", NULL }; + char *distrust_args[] = { (char *) "1", NULL }; + char *distrust2_args[] = { (char *) "2", NULL }; + grub_err_t err; +@@ -157,6 +174,7 @@ appended_signature_test (void) + grub_procfs_register ("certificate2.der", &certificate2_der_entry); + grub_procfs_register ("certificate_printable.der", + &certificate_printable_der_entry); ++ grub_procfs_register ("certificate_eku.der", &certificate_eku_der_entry); + + cmd_trust = grub_command_find ("trust_certificate"); + if (!cmd_trust) +@@ -266,16 +284,23 @@ appended_signature_test (void) + + /* + * Lastly, check a certificate that uses printableString rather than +- * utf8String loads properly. ++ * utf8String loads properly, and that a certificate with an appropriate ++ * extended key usage loads. + */ + err = (cmd_trust->func) (cmd_trust, 1, trust_args_printable); + grub_test_assert (err == GRUB_ERR_NONE, +- "distrusting printable certificate failed: %d: %s", ++ "trusting printable certificate failed: %d: %s", ++ grub_errno, grub_errmsg); ++ ++ err = (cmd_trust->func) (cmd_trust, 1, trust_args_eku); ++ grub_test_assert (err == GRUB_ERR_NONE, ++ "trusting certificate with extended key usage failed: %d: %s", + grub_errno, grub_errmsg); + + grub_procfs_unregister (&certificate_der_entry); + grub_procfs_unregister (&certificate2_der_entry); + grub_procfs_unregister (&certificate_printable_der_entry); ++ grub_procfs_unregister (&certificate_eku_der_entry); + } + + GRUB_FUNCTIONAL_TEST (appended_signature_test, appended_signature_test); +diff --git a/grub-core/tests/appended_signatures.h b/grub-core/tests/appended_signatures.h +index aa3dc6278e..2e5ebd7d8b 100644 +--- a/grub-core/tests/appended_signatures.h ++++ b/grub-core/tests/appended_signatures.h +@@ -555,3 +555,84 @@ unsigned char certificate_printable_der[] = { + 0xd2 + }; + unsigned int certificate_printable_der_len = 829; ++ ++unsigned char certificate_eku_der[] = { ++ 0x30, 0x82, 0x03, 0x90, 0x30, 0x82, 0x02, 0x78, 0xa0, 0x03, 0x02, 0x01, ++ 0x02, 0x02, 0x09, 0x00, 0xd3, 0x9c, 0x41, 0x33, 0xdd, 0x6b, 0x5f, 0x45, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x0b, 0x05, 0x00, 0x30, 0x47, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, ++ 0x04, 0x03, 0x0c, 0x18, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, ++ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, ++ 0x43, 0x41, 0x20, 0x36, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2a, 0x86, ++ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x13, 0x73, 0x65, 0x63, ++ 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, ++ 0x31, 0x35, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x33, ++ 0x38, 0x30, 0x31, 0x31, 0x37, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, ++ 0x30, 0x4e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, ++ 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, ++ 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, ++ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x36, 0x30, 0x32, 0x31, 0x22, 0x30, 0x20, ++ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, ++ 0x13, 0x73, 0x65, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, ++ 0x64, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, ++ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, ++ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, ++ 0x02, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x6f, 0xbb, 0x92, 0x77, 0xd7, 0x15, ++ 0xef, 0x88, 0x80, 0x88, 0xc0, 0xe7, 0x89, 0xeb, 0x35, 0x76, 0xf4, 0x85, ++ 0x05, 0x0f, 0x19, 0xe4, 0x5f, 0x25, 0xdd, 0xc1, 0xa2, 0xe5, 0x5c, 0x06, ++ 0xfb, 0xf1, 0x06, 0xb5, 0x65, 0x45, 0xcb, 0xbd, 0x19, 0x33, 0x54, 0xb5, ++ 0x1a, 0xcd, 0xe4, 0xa8, 0x35, 0x2a, 0xfe, 0x9c, 0x53, 0xf4, 0xc6, 0x76, ++ 0xdb, 0x1f, 0x8a, 0xd4, 0x7b, 0x18, 0x11, 0xaf, 0xa3, 0x90, 0xd4, 0xdd, ++ 0x4d, 0xd5, 0x42, 0xcc, 0x14, 0x9a, 0x64, 0x6b, 0xc0, 0x7f, 0xaa, 0x1c, ++ 0x94, 0x47, 0x4d, 0x79, 0xbd, 0x57, 0x9a, 0xbf, 0x99, 0x4e, 0x96, 0xa9, ++ 0x31, 0x2c, 0xa9, 0xe7, 0x14, 0x65, 0x86, 0xc8, 0xac, 0x79, 0x5e, 0x78, ++ 0xa4, 0x3c, 0x00, 0x24, 0xd3, 0xf7, 0xe1, 0xf5, 0x12, 0xad, 0xa0, 0x29, ++ 0xe5, 0xfe, 0x80, 0xae, 0xf8, 0xaa, 0x60, 0x36, 0xe7, 0xe8, 0x94, 0xcb, ++ 0xe9, 0xd1, 0xcc, 0x0b, 0x4d, 0xf7, 0xde, 0xeb, 0x52, 0xd2, 0x73, 0x09, ++ 0x28, 0xdf, 0x48, 0x99, 0x53, 0x9f, 0xc5, 0x9a, 0xd4, 0x36, 0xa3, 0xc6, ++ 0x5e, 0x8d, 0xbe, 0xd5, 0xdc, 0x76, 0xb4, 0x74, 0xb8, 0x26, 0x18, 0x27, ++ 0xfb, 0xf2, 0xfb, 0xd0, 0x9b, 0x3d, 0x7f, 0x10, 0xe2, 0xab, 0x44, 0xc7, ++ 0x88, 0x7f, 0xb4, 0x3d, 0x3e, 0xa3, 0xff, 0x6d, 0x06, 0x4b, 0x3e, 0x55, ++ 0xb2, 0x84, 0xf4, 0xad, 0x54, 0x88, 0x81, 0xc3, 0x9c, 0xf8, 0xb6, 0x68, ++ 0x96, 0x38, 0x8b, 0xcd, 0x90, 0x6d, 0x25, 0x4b, 0xbf, 0x0c, 0x44, 0x90, ++ 0xa5, 0x5b, 0x98, 0xd0, 0x40, 0x2f, 0xbb, 0x0d, 0xa8, 0x4b, 0x8a, 0x62, ++ 0x82, 0x46, 0x46, 0x18, 0x38, 0xae, 0x82, 0x07, 0xd0, 0xb4, 0x2f, 0x16, ++ 0x79, 0x55, 0x9f, 0x1b, 0xc5, 0x08, 0x6d, 0x85, 0xdf, 0x3f, 0xa9, 0x9b, ++ 0x4b, 0xc6, 0x28, 0xd3, 0x58, 0x72, 0x3d, 0x37, 0x11, 0x02, 0x03, 0x01, ++ 0x00, 0x01, 0xa3, 0x78, 0x30, 0x76, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, ++ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, ++ 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, ++ 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, ++ 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, ++ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6c, ++ 0xe4, 0x6c, 0x27, 0xaa, 0xcd, 0x0d, 0x4b, 0x74, 0x21, 0xa4, 0xf6, 0x5f, ++ 0x87, 0xb5, 0x31, 0xfe, 0x10, 0xbb, 0xa7, 0x30, 0x1f, 0x06, 0x03, 0x55, ++ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xe8, 0x6a, 0x1c, 0xab, ++ 0x2c, 0x48, 0xf9, 0x60, 0x36, 0xa2, 0xf0, 0x7b, 0x8e, 0xd2, 0x9d, 0xb4, ++ 0x2a, 0x28, 0x98, 0xc8, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, ++ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, ++ 0x55, 0x34, 0xe2, 0xfa, 0xf6, 0x89, 0x86, 0xad, 0x92, 0x21, 0xec, 0xb9, ++ 0x54, 0x0e, 0x18, 0x47, 0x0d, 0x1b, 0xa7, 0x58, 0xad, 0x69, 0xe4, 0xef, ++ 0x3b, 0xe6, 0x8d, 0xdd, 0xda, 0x0c, 0x45, 0xf6, 0xe8, 0x96, 0xa4, 0x29, ++ 0x0f, 0xbb, 0xcf, 0x16, 0xae, 0x93, 0xd0, 0xcb, 0x2a, 0x26, 0x1a, 0x7b, ++ 0xfc, 0x51, 0x22, 0x76, 0x98, 0x31, 0xa7, 0x0f, 0x29, 0x35, 0x79, 0xbf, ++ 0xe2, 0x4f, 0x0f, 0x14, 0xf5, 0x1f, 0xcb, 0xbf, 0x87, 0x65, 0x13, 0x32, ++ 0xa3, 0x19, 0x4a, 0xd1, 0x3f, 0x45, 0xd4, 0x4b, 0xe2, 0x00, 0x26, 0xa9, ++ 0x3e, 0xd7, 0xa5, 0x37, 0x9f, 0xf5, 0xad, 0x61, 0xe2, 0x40, 0xa9, 0x74, ++ 0x24, 0x53, 0xf2, 0x78, 0xeb, 0x10, 0x9b, 0x2c, 0x27, 0x88, 0x46, 0xcb, ++ 0xe4, 0x60, 0xca, 0xf5, 0x06, 0x24, 0x40, 0x2a, 0x97, 0x3a, 0xcc, 0xd0, ++ 0x81, 0xb1, 0x15, 0xa3, 0x4f, 0xd0, 0x2b, 0x4f, 0xca, 0x6e, 0xaa, 0x24, ++ 0x31, 0xb3, 0xac, 0xa6, 0x75, 0x05, 0xfe, 0x8a, 0xf4, 0x41, 0xc4, 0x06, ++ 0x8a, 0xc7, 0x0a, 0x83, 0x4e, 0x49, 0xd4, 0x3f, 0x83, 0x50, 0xec, 0x57, ++ 0x04, 0x97, 0x14, 0x49, 0xf5, 0xe1, 0xb1, 0x7a, 0x9c, 0x09, 0x4f, 0x61, ++ 0x87, 0xc3, 0x97, 0x22, 0x17, 0xc2, 0xeb, 0xcc, 0x32, 0x81, 0x31, 0x21, ++ 0x3f, 0x10, 0x57, 0x5b, 0x43, 0xbe, 0xcd, 0x68, 0x82, 0xbe, 0xe5, 0xc1, ++ 0x65, 0x94, 0x7e, 0xc2, 0x34, 0x76, 0x2b, 0xcf, 0x89, 0x3c, 0x2b, 0x81, ++ 0x23, 0x72, 0x95, 0xcf, 0xc9, 0x67, 0x19, 0x2a, 0xd5, 0x5c, 0xca, 0xa3, ++ 0x46, 0xbd, 0x48, 0x06, 0x0b, 0xa6, 0xa3, 0x96, 0x50, 0x28, 0xc7, 0x7e, ++ 0xcf, 0x62, 0xf2, 0xfa, 0xc4, 0xf2, 0x53, 0xe3, 0xc9, 0xe8, 0x2e, 0xdd, ++ 0x29, 0x37, 0x07, 0x47, 0xff, 0xff, 0x8a, 0x32, 0xbd, 0xa2, 0xb7, 0x21, ++ 0x89, 0xa0, 0x55, 0xf7 ++}; ++unsigned int certificate_eku_der_len = 916; diff --git a/SOURCES/0175-ieee1275-Avoiding-many-unecessary-open-close.patch b/SOURCES/0175-ieee1275-Avoiding-many-unecessary-open-close.patch deleted file mode 100644 index 6a0ad75..0000000 --- a/SOURCES/0175-ieee1275-Avoiding-many-unecessary-open-close.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Mon, 14 Dec 2020 17:42:45 +0100 -Subject: [PATCH] ieee1275: Avoiding many unecessary open/close - -Signed-off-by: Diego Domingos ---- - grub-core/disk/ieee1275/ofdisk.c | 64 ++++++++++++++++++++++------------------ - 1 file changed, 35 insertions(+), 29 deletions(-) - -diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c -index 03674cb477e..ea7f78ac7d8 100644 ---- a/grub-core/disk/ieee1275/ofdisk.c -+++ b/grub-core/disk/ieee1275/ofdisk.c -@@ -44,7 +44,7 @@ struct ofdisk_hash_ent - }; - - static grub_err_t --grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, -+grub_ofdisk_get_block_size (grub_uint32_t *block_size, - struct ofdisk_hash_ent *op); - - #define OFDISK_HASH_SZ 8 -@@ -461,6 +461,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) - grub_ssize_t actual; - grub_uint32_t block_size = 0; - grub_err_t err; -+ struct ofdisk_hash_ent *op; - - if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, -@@ -471,6 +472,35 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) - - grub_dprintf ("disk", "Opening `%s'.\n", devpath); - -+ op = ofdisk_hash_find (devpath); -+ if (!op) -+ op = ofdisk_hash_add (devpath, NULL); -+ if (!op) -+ { -+ grub_free (devpath); -+ return grub_errno; -+ } -+ -+ /* Check if the call to open is the same to the last disk already opened */ -+ if (last_devpath && !grub_strcmp(op->open_path,last_devpath)) -+ { -+ goto finish; -+ } -+ -+ /* If not, we need to close the previous disk and open the new one */ -+ else { -+ if (last_ihandle){ -+ grub_ieee1275_close (last_ihandle); -+ } -+ last_ihandle = 0; -+ last_devpath = NULL; -+ -+ grub_ieee1275_open (op->open_path, &last_ihandle); -+ if (! last_ihandle) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); -+ last_devpath = op->open_path; -+ } -+ - if (grub_ieee1275_finddevice (devpath, &dev)) - { - grub_free (devpath); -@@ -491,25 +521,18 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device"); - } - -+ -+ finish: - /* XXX: There is no property to read the number of blocks. There - should be a property `#blocks', but it is not there. Perhaps it - is possible to use seek for this. */ - disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; - - { -- struct ofdisk_hash_ent *op; -- op = ofdisk_hash_find (devpath); -- if (!op) -- op = ofdisk_hash_add (devpath, NULL); -- if (!op) -- { -- grub_free (devpath); -- return grub_errno; -- } - disk->id = (unsigned long) op; - disk->data = op->open_path; - -- err = grub_ofdisk_get_block_size (devpath, &block_size, op); -+ err = grub_ofdisk_get_block_size (&block_size, op); - if (err) - { - grub_free (devpath); -@@ -532,13 +555,6 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) - static void - grub_ofdisk_close (grub_disk_t disk) - { -- if (disk->data == last_devpath) -- { -- if (last_ihandle) -- grub_ieee1275_close (last_ihandle); -- last_ihandle = 0; -- last_devpath = NULL; -- } - disk->data = 0; - } - -@@ -685,7 +701,7 @@ grub_ofdisk_init (void) - } - - static grub_err_t --grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, -+grub_ofdisk_get_block_size (grub_uint32_t *block_size, - struct ofdisk_hash_ent *op) - { - struct size_args_ieee1275 -@@ -698,16 +714,6 @@ grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, - grub_ieee1275_cell_t size2; - } args_ieee1275; - -- if (last_ihandle) -- grub_ieee1275_close (last_ihandle); -- -- last_ihandle = 0; -- last_devpath = NULL; -- -- grub_ieee1275_open (device, &last_ihandle); -- if (! last_ihandle) -- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); -- - *block_size = 0; - - if (op->block_size_fails >= 2) diff --git a/SOURCES/0176-ieee1275-ofdisk-retry-on-open-failure.patch b/SOURCES/0176-ieee1275-ofdisk-retry-on-open-failure.patch new file mode 100644 index 0000000..9149773 --- /dev/null +++ b/SOURCES/0176-ieee1275-ofdisk-retry-on-open-failure.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Wed, 10 Mar 2021 14:17:52 -0500 +Subject: [PATCH] ieee1275/ofdisk: retry on open failure + +This patch aims to make grub more robust when booting from SAN/Multipath disks. + +If a path is failing intermittently so grub will retry the OPEN and READ the +disk (grub_ieee1275_open and grub_ieee1275_read) until the total amount of times +specified in MAX_RETRIES. + +Signed-off-by: Diego Domingos +--- + grub-core/disk/ieee1275/ofdisk.c | 25 ++++++++++++++++++++----- + include/grub/ieee1275/ofdisk.h | 8 ++++++++ + 2 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c +index ea7f78ac7d..55346849d3 100644 +--- a/grub-core/disk/ieee1275/ofdisk.c ++++ b/grub-core/disk/ieee1275/ofdisk.c +@@ -225,7 +225,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) + char *buf, *bufptr; + unsigned i; + +- if (grub_ieee1275_open (alias->path, &ihandle)) ++ ++ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle) ++ if (! ihandle) + return; + + /* This method doesn't need memory allocation for the table. Open +@@ -305,7 +307,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) + return; + } + +- if (grub_ieee1275_open (alias->path, &ihandle)) ++ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle); ++ ++ if (! ihandle) + { + grub_free (buf); + grub_free (table); +@@ -495,7 +499,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) + last_ihandle = 0; + last_devpath = NULL; + +- grub_ieee1275_open (op->open_path, &last_ihandle); ++ RETRY_IEEE1275_OFDISK_OPEN(op->open_path, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + last_devpath = op->open_path; +@@ -571,7 +575,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) + last_ihandle = 0; + last_devpath = NULL; + +- grub_ieee1275_open (disk->data, &last_ihandle); ++ RETRY_IEEE1275_OFDISK_OPEN(disk->data, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + last_devpath = disk->data; +@@ -598,12 +602,23 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + return err; + grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, + &actual); +- if (actual != (grub_ssize_t) (size << disk->log_sector_size)) ++ int i = 0; ++ while(actual != (grub_ssize_t) (size << disk->log_sector_size)){ ++ if (i>MAX_RETRIES){ + return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); ++ } ++ last_devpath = NULL; ++ err = grub_ofdisk_prepare (disk, sector); ++ if (err) ++ return err; + ++ grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, ++ &actual); ++ i++; ++ } + return 0; + } + +diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h +index 2f69e3f191..7d2d540930 100644 +--- a/include/grub/ieee1275/ofdisk.h ++++ b/include/grub/ieee1275/ofdisk.h +@@ -22,4 +22,12 @@ + extern void grub_ofdisk_init (void); + extern void grub_ofdisk_fini (void); + ++#define MAX_RETRIES 20 ++ ++ ++#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ ++ if(!grub_ieee1275_open(device, last_ihandle)) \ ++ break; \ ++ grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } ++ + #endif /* ! GRUB_INIT_HEADER */ diff --git a/SOURCES/0176-ieee1275-powerpc-implements-fibre-channel-discovery-.patch b/SOURCES/0176-ieee1275-powerpc-implements-fibre-channel-discovery-.patch deleted file mode 100644 index 9fa02bb..0000000 --- a/SOURCES/0176-ieee1275-powerpc-implements-fibre-channel-discovery-.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Mon, 14 Dec 2020 17:45:28 +0100 -Subject: [PATCH] ieee1275/powerpc: implements fibre channel discovery for - ofpathname - -grub-ofpathname doesn't work with fibre channel because there is no -function currently implemented for it. -This patch enables it by prividing a function that looks for the port -name, building the entire path for OF devices. - -Signed-off-by: Diego Domingos ---- - grub-core/osdep/linux/ofpath.c | 49 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 49 insertions(+) - -diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c -index a6153d35954..0f5d54e9f2d 100644 ---- a/grub-core/osdep/linux/ofpath.c -+++ b/grub-core/osdep/linux/ofpath.c -@@ -350,6 +350,38 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi - return ret; - } - -+ -+static void -+of_fc_port_name(const char *path, const char *subpath, char *port_name) -+{ -+ char *bname, *basepath, *p; -+ int fd; -+ -+ bname = xmalloc(sizeof(char)*150); -+ basepath = xmalloc(strlen(path)); -+ -+ /* Generate the path to get port name information from the drive */ -+ strncpy(basepath,path,subpath-path); -+ basepath[subpath-path-1] = '\0'; -+ p = get_basename(basepath); -+ snprintf(bname,sizeof(char)*150,"%s/fc_transport/%s/port_name",basepath,p); -+ -+ /* Read the information from the port name */ -+ fd = open (bname, O_RDONLY); -+ if (fd < 0) -+ grub_util_error (_("cannot open `%s': %s"), bname, strerror (errno)); -+ -+ if (read(fd,port_name,sizeof(char)*19) < 0) -+ grub_util_error (_("cannot read `%s': %s"), bname, strerror (errno)); -+ -+ sscanf(port_name,"0x%s",port_name); -+ -+ close(fd); -+ -+ free(bname); -+ free(basepath); -+} -+ - #ifdef __sparc__ - static char * - of_path_of_nvme(const char *sys_devname __attribute__((unused)), -@@ -577,6 +609,16 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev - digit_string = trailing_digits (device); - if (strncmp (of_path, "/vdevice/", sizeof ("/vdevice/") - 1) == 0) - { -+ if(strstr(of_path,"vfc-client")) -+ { -+ char * port_name = xmalloc(sizeof(char)*17); -+ of_fc_port_name(sysfs_path, p, port_name); -+ -+ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name); -+ free(port_name); -+ } -+ else -+ { - unsigned long id = 0x8000 | (tgt << 8) | (bus << 5) | lun; - if (*digit_string == '\0') - { -@@ -590,6 +632,13 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev - snprintf(disk, sizeof (disk), - "/%s@%04lx000000000000:%c", disk_name, id, 'a' + (part - 1)); - } -+ } -+ } else if (strstr(of_path,"fibre-channel")||(strstr(of_path,"vfc-client"))){ -+ char * port_name = xmalloc(sizeof(char)*17); -+ of_fc_port_name(sysfs_path, p, port_name); -+ -+ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name); -+ free(port_name); - } - else - { diff --git a/SOURCES/0177-Allow-chainloading-EFI-apps-from-loop-mounts.patch b/SOURCES/0177-Allow-chainloading-EFI-apps-from-loop-mounts.patch new file mode 100644 index 0000000..c3101e1 --- /dev/null +++ b/SOURCES/0177-Allow-chainloading-EFI-apps-from-loop-mounts.patch @@ -0,0 +1,138 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 11 Jun 2021 13:51:20 +0200 +Subject: [PATCH] Allow chainloading EFI apps from loop mounts. + +Signed-off-by: Dimitri John Ledkov +Signed-off-by: Robbie Harwood +--- + grub-core/disk/loopback.c | 9 +-------- + grub-core/loader/efi/chainloader.c | 23 +++++++++++++++++++++++ + include/grub/loopback.h | 30 ++++++++++++++++++++++++++++++ + 3 files changed, 54 insertions(+), 8 deletions(-) + create mode 100644 include/grub/loopback.h + +diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c +index 41bebd14fe..99f47924ec 100644 +--- a/grub-core/disk/loopback.c ++++ b/grub-core/disk/loopback.c +@@ -21,20 +21,13 @@ + #include + #include + #include ++#include + #include + #include + #include + + GRUB_MOD_LICENSE ("GPLv3+"); + +-struct grub_loopback +-{ +- char *devname; +- grub_file_t file; +- struct grub_loopback *next; +- unsigned long id; +-}; +- + static struct grub_loopback *loopback_list; + static unsigned long last_id = 0; + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index d41e8ea14a..3af6b12292 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -901,6 +902,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_status_t status; + grub_efi_boot_services_t *b; + grub_device_t dev = 0; ++ grub_device_t orig_dev = 0; + grub_efi_device_path_t *dp = 0; + char *filename; + void *boot_image = 0; +@@ -958,6 +960,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + if (! dev) + goto fail; + ++ /* if device is loopback, use underlying dev */ ++ if (dev->disk->dev->id == GRUB_DISK_DEVICE_LOOPBACK_ID) ++ { ++ struct grub_loopback *d; ++ orig_dev = dev; ++ d = dev->disk->data; ++ dev = d->file->device; ++ } ++ + if (dev->disk) + dev_handle = grub_efidisk_get_device_handle (dev->disk); + else if (dev->net && dev->net->server) +@@ -1065,6 +1076,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + #endif + ++ if (orig_dev) ++ { ++ dev = orig_dev; ++ orig_dev = 0; ++ } ++ + rc = grub_linuxefi_secure_validate((void *)(unsigned long)address, fsize); + grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); + if (rc > 0) +@@ -1087,6 +1104,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + // -1 fall-through to fail + + fail: ++ if (orig_dev) ++ { ++ dev = orig_dev; ++ orig_dev = 0; ++ } ++ + if (dev) + grub_device_close (dev); + +diff --git a/include/grub/loopback.h b/include/grub/loopback.h +new file mode 100644 +index 0000000000..3b9a9e32e8 +--- /dev/null ++++ b/include/grub/loopback.h +@@ -0,0 +1,30 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2019 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_LOOPBACK_HEADER ++#define GRUB_LOOPBACK_HEADER 1 ++ ++struct grub_loopback ++{ ++ char *devname; ++ grub_file_t file; ++ struct grub_loopback *next; ++ unsigned long id; ++}; ++ ++#endif /* ! GRUB_LOOPBACK_HEADER */ diff --git a/SOURCES/0177-ieee1275-powerpc-enables-device-mapper-discovery.patch b/SOURCES/0177-ieee1275-powerpc-enables-device-mapper-discovery.patch deleted file mode 100644 index 6f1c21b..0000000 --- a/SOURCES/0177-ieee1275-powerpc-enables-device-mapper-discovery.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Mon, 14 Dec 2020 17:47:16 +0100 -Subject: [PATCH] ieee1275/powerpc: enables device mapper discovery - -this patch enables the device mapper discovery on ofpath.c. Currently, -when we are dealing with a device like /dev/dm-* the ofpath returns null -since there is no function implemented to handle this case. - -This patch implements a function that will look into /sys/block/dm-* -devices and search recursively inside slaves directory to find the root -disk. - -Signed-off-by: Diego Domingos ---- - grub-core/osdep/linux/ofpath.c | 64 +++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 63 insertions(+), 1 deletion(-) - -diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c -index 0f5d54e9f2d..cc849d9c94c 100644 ---- a/grub-core/osdep/linux/ofpath.c -+++ b/grub-core/osdep/linux/ofpath.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #ifdef __sparc__ - typedef enum -@@ -755,13 +756,74 @@ strip_trailing_digits (const char *p) - return new; - } - -+static char * -+get_slave_from_dm(const char * device){ -+ char *curr_device, *tmp; -+ char *directory; -+ char *ret = NULL; -+ -+ directory = grub_strdup (device); -+ tmp = get_basename(directory); -+ curr_device = grub_strdup (tmp); -+ *tmp = '\0'; -+ -+ /* Recursively check for slaves devices so we can find the root device */ -+ while ((curr_device[0] == 'd') && (curr_device[1] == 'm') && (curr_device[2] == '-')){ -+ DIR *dp; -+ struct dirent *ep; -+ char* device_path; -+ -+ device_path = grub_xasprintf ("/sys/block/%s/slaves", curr_device); -+ dp = opendir(device_path); -+ free(device_path); -+ -+ if (dp != NULL) -+ { -+ ep = readdir (dp); -+ while (ep != NULL){ -+ -+ /* avoid some system directories */ -+ if (!strcmp(ep->d_name,".")) -+ goto next_dir; -+ if (!strcmp(ep->d_name,"..")) -+ goto next_dir; -+ -+ free (curr_device); -+ free (ret); -+ curr_device = grub_strdup (ep->d_name); -+ ret = grub_xasprintf ("%s%s", directory, curr_device); -+ break; -+ -+ next_dir: -+ ep = readdir (dp); -+ continue; -+ } -+ closedir (dp); -+ } -+ else -+ grub_util_warn (_("cannot open directory `%s'"), device_path); -+ } -+ -+ free (directory); -+ free (curr_device); -+ -+ return ret; -+} -+ - char * - grub_util_devname_to_ofpath (const char *sys_devname) - { -- char *name_buf, *device, *devnode, *devicenode, *ofpath; -+ char *name_buf, *device, *devnode, *devicenode, *ofpath, *realname; - - name_buf = xrealpath (sys_devname); - -+ realname = get_slave_from_dm (name_buf); -+ if (realname) -+ { -+ free (name_buf); -+ name_buf = realname; -+ } -+ - device = get_basename (name_buf); - devnode = strip_trailing_digits (name_buf); - devicenode = strip_trailing_digits (device); diff --git a/SOURCES/0178-Add-at_keyboard_fallback_set-var-to-force-the-set-ma.patch b/SOURCES/0178-Add-at_keyboard_fallback_set-var-to-force-the-set-ma.patch deleted file mode 100644 index 968a9c1..0000000 --- a/SOURCES/0178-Add-at_keyboard_fallback_set-var-to-force-the-set-ma.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Fri, 18 Dec 2020 15:39:26 +0100 -Subject: [PATCH] Add 'at_keyboard_fallback_set' var to force the set manually - -This seems required with HP DL380p Gen 8 systems. -Indeed, with this system, we can see the following sequence: - -1. controller is queried to get current configuration (returns 0x30 which is quite standard) -2. controller is queried to get the current keyboard set in used, using code 0xf0 (first part) -3. controller answers with 0xfa which means "ACK" (== ok) -4. then we send "0" to tell "we want to know which set your are supporting" -5. controller answers with 0xfa ("ACK") -6. controller should then give us 1, 2, 3 or 0x43, 0x41, 0x3f, but here it gives us 0xfe which means "NACK" - -Since there seems no way to determine the current set, and in fact the -controller expects set2 to be used, we need to rely on an environment -variable. -Everything has been tested on this system: using 0xFE (resend command), -making sure we wait for ACK in the 2 steps "write_mode", etc. - -Below is litterature I used to come up with "there is no other -solution": -- https://wiki.osdev.org/%228042%22_PS/2_Controller -- http://www-ug.eecg.toronto.edu/msl/nios_devices/datasheets/PS2%20Keyboard%20Protocol.htm -- http://www.s100computers.com/My%20System%20Pages/MSDOS%20Board/PC%20Keyboard.pdf ---- - grub-core/term/at_keyboard.c | 121 ++++++++++++++++++++++++++++++++++--------- - 1 file changed, 96 insertions(+), 25 deletions(-) - -diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c -index 26014382608..dac0f946fe6 100644 ---- a/grub-core/term/at_keyboard.c -+++ b/grub-core/term/at_keyboard.c -@@ -31,6 +31,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - static grub_uint8_t grub_keyboard_controller_orig; - static grub_uint8_t grub_keyboard_orig_set; - struct grub_ps2_state ps2_state; -+static int fallback_set; - - static int ping_sent; - -@@ -76,6 +77,8 @@ at_command (grub_uint8_t data) - break; - return 0; - } -+ if (i == GRUB_AT_TRIES) -+ grub_dprintf ("atkeyb", "at_command() timed out! (stopped after %d tries)\n", i); - return (i != GRUB_AT_TRIES); - } - -@@ -105,6 +108,21 @@ grub_keyboard_controller_read (void) - - #endif - -+static int -+resend_last_result (void) -+{ -+ grub_uint8_t ret; -+ keyboard_controller_wait_until_ready (); -+ grub_dprintf ("atkeyb", "resend_last_result: sending 0xfe\n"); -+ grub_outb (0xfe, KEYBOARD_REG_DATA); -+ ret = wait_ack (); -+ grub_dprintf ("atkeyb", "resend_last_result: wait_ack() returned 0x%x\n", ret); -+ keyboard_controller_wait_until_ready (); -+ ret = grub_inb (KEYBOARD_REG_DATA); -+ grub_dprintf ("atkeyb", "resend_last_result: read 0x%x from controller\n", ret); -+ return ret; -+} -+ - static int - write_mode (int mode) - { -@@ -113,11 +131,14 @@ write_mode (int mode) - { - grub_uint8_t ack; - keyboard_controller_wait_until_ready (); -+ grub_dprintf ("atkeyb", "write_mode: sending 0xf0\n"); - grub_outb (0xf0, KEYBOARD_REG_DATA); - keyboard_controller_wait_until_ready (); -+ grub_dprintf ("atkeyb", "write_mode: sending mode %d\n", mode); - grub_outb (mode, KEYBOARD_REG_DATA); - keyboard_controller_wait_until_ready (); - ack = wait_ack (); -+ grub_dprintf ("atkeyb", "write_mode: wait_ack() returned 0x%x\n", ack); - if (ack == GRUB_AT_NACK) - continue; - if (ack == GRUB_AT_ACK) -@@ -125,6 +146,9 @@ write_mode (int mode) - return 0; - } - -+ if (i == GRUB_AT_TRIES) -+ grub_dprintf ("atkeyb", "write_mode() timed out! (stopped after %d tries)\n", i); -+ - return (i != GRUB_AT_TRIES); - } - -@@ -132,31 +156,66 @@ static int - query_mode (void) - { - grub_uint8_t ret; -+ grub_uint64_t endtime; -+ unsigned i; - int e; -+ char *envvar; - -- e = write_mode (0); -- if (!e) { -- grub_dprintf("atkeyb", "query_mode: write_mode(0) failed\n"); -- return 0; -- } -+ for (i = 0; i < GRUB_AT_TRIES; i++) { -+ grub_dprintf ("atkeyb", "query_mode: sending command to controller\n"); -+ e = write_mode (0); -+ if (!e) { -+ grub_dprintf ("atkeyb", "query_mode: write_mode(0) failed\n"); -+ return 0; -+ } - -- do { -- keyboard_controller_wait_until_ready (); -- ret = grub_inb (KEYBOARD_REG_DATA); -- } while (ret == GRUB_AT_ACK); -- /* QEMU translates the set even in no-translate mode. */ -- if (ret == 0x43 || ret == 1) { -- grub_dprintf("atkeyb", "query_mode: returning 1 (ret=0x%x)\n", ret); -- return 1; -- } -- if (ret == 0x41 || ret == 2) { -- grub_dprintf("atkeyb", "query_mode: returning 2 (ret=0x%x)\n", ret); -- return 2; -+ endtime = grub_get_time_ms () + 20; -+ do { -+ keyboard_controller_wait_until_ready (); -+ ret = grub_inb (KEYBOARD_REG_DATA); -+ grub_dprintf ("atkeyb", "query_mode/loop: read 0x%x from controller\n", ret); -+ } while ((ret == GRUB_AT_ACK || ret == GRUB_AT_NACK) && grub_get_time_ms () < endtime); -+ if (ret == 0xfe) { -+ grub_dprintf ("atkeyb", "query_mode: asking controller to resend last result\n"); -+ ret = resend_last_result(); -+ grub_dprintf ("atkeyb", "query_mode: read 0x%x from controller\n", ret); -+ } -+ /* QEMU translates the set even in no-translate mode. */ -+ if (ret == 0x43 || ret == 1) { -+ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 1\n", ret); -+ return 1; -+ } -+ if (ret == 0x41 || ret == 2) { -+ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 2\n", ret); -+ return 2; -+ } -+ if (ret == 0x3f || ret == 3) { -+ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 3\n", ret); -+ return 3; -+ } -+ grub_dprintf ("atkeyb", "query_mode: controller returned unexpected value 0x%x, retrying\n", ret); - } -- if (ret == 0x3f || ret == 3) { -- grub_dprintf("atkeyb", "query_mode: returning 3 (ret=0x%x)\n", ret); -- return 3; -+ -+ /* -+ * Falling here means we tried querying and the controller returned something -+ * we don't understand, try to use 'at_keyboard_fallback_set' if it exists, -+ * otherwise return 0. -+ */ -+ envvar = grub_env_get ("at_keyboard_fallback_set"); -+ if (envvar) { -+ fallback_set = grub_strtoul (envvar, 0, 10); -+ if ((grub_errno) || (fallback_set < 1) || (fallback_set > 3)) { -+ grub_dprintf ("atkeyb", "WARNING: ignoring unexpected value '%s' for '%s' variable\n", -+ envvar, "at_keyboard_fallback_set"); -+ fallback_set = 0; -+ } else { -+ grub_dprintf ("atkeyb", "query_mode: '%s' specified in environment, returning %d\n", -+ "at_keyboard_fallback_set", fallback_set); -+ } -+ return fallback_set; - } -+ grub_dprintf ("atkeyb", "WARNING: no '%s' specified in environment, returning 0\n", -+ "at_keyboard_fallback_set"); - return 0; - } - -@@ -165,14 +224,25 @@ set_scancodes (void) - { - /* You must have visited computer museum. Keyboard without scancode set - knowledge. Assume XT. */ -- if (!grub_keyboard_orig_set) -- { -- grub_dprintf ("atkeyb", "No sets support assumed\n"); -- ps2_state.current_set = 1; -+ if (!grub_keyboard_orig_set) { -+ if (fallback_set) { -+ grub_dprintf ("atkeyb", "No sets support assumed but set forced to %d\n", fallback_set); -+ ps2_state.current_set = fallback_set; - return; - } -+ grub_dprintf ("atkeyb", "No sets support assumed, forcing to set 1\n"); -+ ps2_state.current_set = 1; -+ return; -+ } - - #if !USE_SCANCODE_SET -+ if (fallback_set) { -+ grub_dprintf ("atkeyb", "queried set is %d but set forced to %d\n", -+ grub_keyboard_orig_set, fallback_set); -+ ps2_state.current_set = fallback_set; -+ return; -+ } -+ - if ((grub_keyboard_controller_orig & KEYBOARD_AT_TRANSLATE) == KEYBOARD_AT_TRANSLATE) { - grub_dprintf ("atkeyb", "queried set is %d but keyboard in Translate mode, so actually in set 1\n", grub_keyboard_orig_set); - ps2_state.current_set = 1; -@@ -261,6 +331,7 @@ grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) - static void - grub_keyboard_controller_init (void) - { -+ grub_dprintf ("atkeyb", "initializing the controller\n"); - ps2_state.at_keyboard_status = 0; - /* Drain input buffer. */ - while (1) -@@ -282,6 +353,7 @@ grub_keyboard_controller_init (void) - grub_keyboard_controller_orig = grub_keyboard_controller_read (); - grub_dprintf ("atkeyb", "grub_keyboard_controller_orig = 0x%x\n", grub_keyboard_controller_orig); - grub_keyboard_orig_set = query_mode (); -+ grub_dprintf ("atkeyb", "grub_keyboard_orig_set = %d\n", grub_keyboard_orig_set); - #endif - set_scancodes (); - keyboard_controller_led (ps2_state.led_status); -@@ -329,7 +401,6 @@ grub_at_restore_hw (void) - return GRUB_ERR_NONE; - } - -- - static struct grub_term_input grub_at_keyboard_term = - { - .name = "at_keyboard", diff --git a/SOURCES/0178-efinet-Add-DHCP-proxy-support.patch b/SOURCES/0178-efinet-Add-DHCP-proxy-support.patch new file mode 100644 index 0000000..eed2dbb --- /dev/null +++ b/SOURCES/0178-efinet-Add-DHCP-proxy-support.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ian Page Hands +Date: Tue, 8 Jun 2021 13:48:56 -0400 +Subject: [PATCH] efinet: Add DHCP proxy support + +If a proxyDHCP configuration is used, the server name, server IP and boot +file values should be taken from the DHCP proxy offer instead of the DHCP +server ack packet. Currently that case is not handled, add support for it. + +Signed-off-by: Ian Page Hands +Signed-off-by: Robbie Harwood +--- + grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index e11d759f19..1a24f38a21 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -850,10 +850,31 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + else + { + grub_dprintf ("efinet", "using ipv4 and dhcp\n"); ++ ++ struct grub_net_bootp_packet *dhcp_ack = &pxe_mode->dhcp_ack; ++ ++ if (pxe_mode->proxy_offer_received) ++ { ++ grub_dprintf ("efinet", "proxy offer receive"); ++ struct grub_net_bootp_packet *proxy_offer = &pxe_mode->proxy_offer; ++ ++ if (proxy_offer && dhcp_ack->boot_file[0] == '\0') ++ { ++ grub_dprintf ("efinet", "setting values from proxy offer"); ++ /* Here we got a proxy offer and the dhcp_ack has a nil boot_file ++ * Copy the proxy DHCP offer details into the bootp_packet we are ++ * sending forward as they are the deatils we need. ++ */ ++ *dhcp_ack->server_name = *proxy_offer->server_name; ++ *dhcp_ack->boot_file = *proxy_offer->boot_file; ++ dhcp_ack->server_ip = proxy_offer->server_ip; ++ } ++ } ++ + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) +- packet_buf, +- packet_bufsz, ++ &pxe_mode->dhcp_ack, ++ sizeof (pxe_mode->dhcp_ack), + 1, device, path); + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } diff --git a/SOURCES/0179-Add-suport-for-signing-grub-with-an-appended-signatu.patch b/SOURCES/0179-Add-suport-for-signing-grub-with-an-appended-signatu.patch deleted file mode 100644 index caab8d5..0000000 --- a/SOURCES/0179-Add-suport-for-signing-grub-with-an-appended-signatu.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Rashmica Gupta -Date: Thu, 11 Jun 2020 11:26:23 +1000 -Subject: [PATCH] Add suport for signing grub with an appended signature - -Add infrastructure to allow firmware to verify the integrity of grub -by use of a Linux-kernel-module-style appended signature. We initially -target powerpc-ieee1275, but the code should be extensible to other -platforms. - -Usually these signatures are appended to a file without modifying the -ELF file itself. (This is what the 'sign-file' tool does, for example.) -The verifier loads the signed file from the file system and looks at the -end of the file for the appended signature. However, on powerpc-ieee1275 -platforms, the bootloader is often stored directly in the PReP partition -as raw bytes without a file-system. This makes determining the location -of an appended signature more difficult. - -To address this, we add a new ELF note. - -The name field of shall be the string "Appended-Signature", zero-padded -to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values -for the string "ASig"). It must be the final section in the ELF binary. - -The description shall contain the appended signature structure as defined -by the Linux kernel. The description will also be padded to be a multiple -of 4 bytes. The padding shall be added before the appended signature -structure (not at the end) so that the final bytes of a signed ELF file -are the appended signature magic. - -A subsequent patch documents how to create a grub core.img validly signed -under this scheme. - -Signed-off-by: Daniel Axtens -Signed-off-by: Rashmica Gupta - ---- - -You can experiment with this code with a patched version of SLOF -that verifies these signatures. You can find one at: - https://github.com/daxtens/SLOF - -I will be proposing this for inclusion in a future Power Architecture -Platform Reference (PAPR). ---- - util/grub-install-common.c | 18 ++++++++++++++++-- - util/grub-mkimage.c | 15 +++++++++++++-- - util/grub-mkimagexx.c | 39 ++++++++++++++++++++++++++++++++++++++- - util/mkimage.c | 13 +++++++------ - include/grub/util/install.h | 8 ++++++-- - include/grub/util/mkimage.h | 4 ++-- - 6 files changed, 82 insertions(+), 15 deletions(-) - -diff --git a/util/grub-install-common.c b/util/grub-install-common.c -index 4e212e690c5..aab2a941f85 100644 ---- a/util/grub-install-common.c -+++ b/util/grub-install-common.c -@@ -461,10 +461,12 @@ static size_t npubkeys; - static char *sbat; - static int disable_shim_lock; - static grub_compression_t compression; -+static size_t appsig_size; - - int - grub_install_parse (int key, char *arg) - { -+ const char *end; - switch (key) - { - case 'C': -@@ -562,6 +564,12 @@ grub_install_parse (int key, char *arg) - grub_util_error (_("Unrecognized compression `%s'"), arg); - case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE: - return 1; -+ case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE: -+ grub_errno = 0; -+ appsig_size = grub_strtol(arg, &end, 10); -+ if (grub_errno) -+ return 0; -+ return 1; - default: - return 0; - } -@@ -665,7 +673,13 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, - dir, prefix, - outname, dtb ? : "", sbat ? : "", mkimage_target, - compnames[compression], note ? "--note" : "", -- disable_shim_lock ? "--disable-shim-lock" : "", s); -+ disable_shim_lock ? "--disable-shim-lock" : "", -+ "--format '%s' --compression '%s' " -+ "--appended-signature-size %zu %s %s\n", -+ dir, prefix, -+ outname, dtb ? : "", mkimage_target, -+ compnames[compression], appsig_size, -+ note ? "--note" : "", s); - free (s); - - tgt = grub_install_get_image_target (mkimage_target); -@@ -675,7 +689,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, - grub_install_generate_image (dir, prefix, fp, outname, - modules.entries, memdisk_path, - pubkeys, npubkeys, config_path, tgt, -- note, compression, dtb, sbat, -+ note, appsig_size, compression, dtb, sbat, - disable_shim_lock); - while (dc--) - grub_install_pop_module (); -diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c -index c0d55993702..8a53310548b 100644 ---- a/util/grub-mkimage.c -+++ b/util/grub-mkimage.c -@@ -84,6 +84,7 @@ static struct argp_option options[] = { - {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0}, - {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0}, - {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, -+ {"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0}, - { 0, 0, 0, 0, 0, 0 } - }; - -@@ -128,6 +129,7 @@ struct arguments - char *sbat; - int note; - int disable_shim_lock; -+ size_t appsig_size; - const struct grub_install_image_target_desc *image_target; - grub_compression_t comp; - }; -@@ -138,6 +140,7 @@ argp_parser (int key, char *arg, struct argp_state *state) - /* Get the input argument from argp_parse, which we - know is a pointer to our arguments structure. */ - struct arguments *arguments = state->input; -+ const char* end; - - switch (key) - { -@@ -170,6 +173,13 @@ argp_parser (int key, char *arg, struct argp_state *state) - arguments->note = 1; - break; - -+ case 'S': -+ grub_errno = 0; -+ arguments->appsig_size = grub_strtol(arg, &end, 10); -+ if (grub_errno) -+ return 0; -+ break; -+ - case 'm': - if (arguments->memdisk) - free (arguments->memdisk); -@@ -324,8 +334,9 @@ main (int argc, char *argv[]) - arguments.memdisk, arguments.pubkeys, - arguments.npubkeys, arguments.config, - arguments.image_target, arguments.note, -- arguments.comp, arguments.dtb, -- arguments.sbat, arguments.disable_shim_lock); -+ arguments.appsig_size, arguments.comp, -+ arguments.dtb, arguments.sbat, -+ arguments.disable_shim_lock); - - if (grub_util_file_sync (fp) < 0) - grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout", -diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c -index d78fa3e5330..393119486d3 100644 ---- a/util/grub-mkimagexx.c -+++ b/util/grub-mkimagexx.c -@@ -84,6 +84,15 @@ struct grub_ieee1275_note - struct grub_ieee1275_note_desc descriptor; - }; - -+#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature" -+#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */ -+ -+struct grub_appended_signature_note -+{ -+ Elf32_Nhdr header; -+ char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)]; -+}; -+ - #define GRUB_XEN_NOTE_NAME "Xen" - - struct fixup_block_list -@@ -207,7 +216,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr) - - void - SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target, -- int note, char **core_img, size_t *core_size, -+ int note, size_t appsig_size, char **core_img, size_t *core_size, - Elf_Addr target_addr, - struct grub_mkimage_layout *layout) - { -@@ -221,6 +230,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc - int shnum = 4; - int string_size = sizeof (".text") + sizeof ("mods") + 1; - -+ if (appsig_size) -+ { -+ phnum++; -+ footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4); -+ } -+ - if (image_target->id != IMAGE_LOONGSON_ELF) - phnum += 2; - -@@ -484,6 +499,28 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc - phdr->p_offset = grub_host_to_target32 (header_size + program_size); - } - -+ if (appsig_size) { -+ int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4); -+ struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *) -+ (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0)); -+ -+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME)); -+ /* needs to sit at the end, so we round this up and sign some zero padding */ -+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4)); -+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE); -+ strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME); -+ -+ phdr++; -+ phdr->p_type = grub_host_to_target32 (PT_NOTE); -+ phdr->p_flags = grub_host_to_target32 (PF_R); -+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof); -+ phdr->p_vaddr = 0; -+ phdr->p_paddr = 0; -+ phdr->p_filesz = grub_host_to_target32 (note_size); -+ phdr->p_memsz = 0; -+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0)); -+ } -+ - { - char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr) - + shnum * sizeof (*shdr)); -diff --git a/util/mkimage.c b/util/mkimage.c -index a26cf76f72f..bab12276010 100644 ---- a/util/mkimage.c -+++ b/util/mkimage.c -@@ -869,8 +869,9 @@ grub_install_generate_image (const char *dir, const char *prefix, - char *memdisk_path, char **pubkey_paths, - size_t npubkeys, char *config_path, - const struct grub_install_image_target_desc *image_target, -- int note, grub_compression_t comp, const char *dtb_path, -- const char *sbat_path, int disable_shim_lock) -+ int note, size_t appsig_size, grub_compression_t comp, -+ const char *dtb_path, const char *sbat_path, -+ int disable_shim_lock) - { - char *kernel_img, *core_img; - size_t total_module_size, core_size; -@@ -1773,11 +1774,11 @@ grub_install_generate_image (const char *dir, const char *prefix, - else - target_addr = image_target->link_addr; - if (image_target->voidp_sizeof == 4) -- grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size, -- target_addr, &layout); -+ grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img, -+ &core_size, target_addr, &layout); - else -- grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size, -- target_addr, &layout); -+ grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img, -+ &core_size, target_addr, &layout); - } - break; - } -diff --git a/include/grub/util/install.h b/include/grub/util/install.h -index 7df3191f47e..cf4531e02b6 100644 ---- a/include/grub/util/install.h -+++ b/include/grub/util/install.h -@@ -67,6 +67,9 @@ - N_("SBAT metadata"), 0 }, \ - { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \ - N_("disable shim_lock verifier"), 0 }, \ -+ { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\ -+ "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \ -+ 1}, \ - { "verbose", 'v', 0, 0, \ - N_("print verbose messages."), 1 } - -@@ -128,7 +131,8 @@ enum grub_install_options { - GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS, - GRUB_INSTALL_OPTIONS_DTB, - GRUB_INSTALL_OPTIONS_SBAT, -- GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK -+ GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, -+ GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE - }; - - extern char *grub_install_source_directory; -@@ -188,7 +192,7 @@ grub_install_generate_image (const char *dir, const char *prefix, - size_t npubkeys, - char *config_path, - const struct grub_install_image_target_desc *image_target, -- int note, -+ int note, size_t appsig_size, - grub_compression_t comp, const char *dtb_file, - const char *sbat_path, const int disable_shim_lock); - -diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h -index 3819a67441c..6f1da89b9b6 100644 ---- a/include/grub/util/mkimage.h -+++ b/include/grub/util/mkimage.h -@@ -51,12 +51,12 @@ grub_mkimage_load_image64 (const char *kernel_path, - const struct grub_install_image_target_desc *image_target); - void - grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target, -- int note, char **core_img, size_t *core_size, -+ int note, size_t appsig_size, char **core_img, size_t *core_size, - Elf32_Addr target_addr, - struct grub_mkimage_layout *layout); - void - grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target, -- int note, char **core_img, size_t *core_size, -+ int note, size_t appsig_size, char **core_img, size_t *core_size, - Elf64_Addr target_addr, - struct grub_mkimage_layout *layout); - diff --git a/SOURCES/0179-fs-ext2-Ignore-checksum-seed-incompat-feature.patch b/SOURCES/0179-fs-ext2-Ignore-checksum-seed-incompat-feature.patch new file mode 100644 index 0000000..3d7c641 --- /dev/null +++ b/SOURCES/0179-fs-ext2-Ignore-checksum-seed-incompat-feature.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Fri, 11 Jun 2021 00:01:29 +0200 +Subject: [PATCH] fs/ext2: Ignore checksum seed incompat feature + +This incompat feature is used to denote that the filesystem stored its +metadata checksum seed in the superblock. This is used to allow tune2fs +to change the UUID on a mounted metadata_csum filesystem without having +to rewrite all the disk metadata. + +But GRUB doesn't use the metadata checksum in anyway, so can just ignore +this feature if is enabled. This is consistent with GRUB filesystem code +in general which just does a best effort to access the filesystem's data. + +It may be removed from the ignored list in the future if supports to do +metadata checksumming verification is added to the read-only FS driver. + +Suggested-by: Eric Sandeen +Suggested-by: Lukas Czerner +Signed-off-by: Javier Martinez Canillas +--- + grub-core/fs/ext2.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c +index e7dd78e663..731d346f88 100644 +--- a/grub-core/fs/ext2.c ++++ b/grub-core/fs/ext2.c +@@ -103,6 +103,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 + #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 + #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 ++#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000 + #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 + + /* The set of back-incompatible features this driver DOES support. Add (OR) +@@ -123,9 +124,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); + * mmp: Not really back-incompatible - was added as such to + * avoid multiple read-write mounts. Safe to ignore for this + * RO driver. ++ * checksum seed: Not really back-incompatible - was added to allow tools ++ * such as tune2fs to change the UUID on a mounted metadata ++ * checksummed filesystem. Safe to ignore for now since the ++ * driver doesn't support checksum verification. But it must ++ * be removed from this list if that support is added later. ++ * + */ + #define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \ +- | EXT4_FEATURE_INCOMPAT_MMP) ++ | EXT4_FEATURE_INCOMPAT_MMP \ ++ | EXT4_FEATURE_INCOMPAT_CSUM_SEED) + + + #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U diff --git a/SOURCES/0180-Don-t-update-the-cmdline-when-generating-legacy-menu.patch b/SOURCES/0180-Don-t-update-the-cmdline-when-generating-legacy-menu.patch new file mode 100644 index 0000000..b2783d1 --- /dev/null +++ b/SOURCES/0180-Don-t-update-the-cmdline-when-generating-legacy-menu.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Thu, 17 Jun 2021 14:31:42 +0200 +Subject: [PATCH] Don't update the cmdline when generating legacy menuentry + commands + +On OPAL ppc64le machines with an old petitboot version that doesn't have +support to parse BLS snippets, the grub2-mkconfig script is executed to +generate menuentry commands from the BLS snippets. + +In this case, the script is executed with the --no-grubenv-update option +that indicates that no side effects should happen when running the script. + +But the options field in the BLS snippets are updated regardless, only do +the update if --no-grubenv-update was not used. + +Signed-off-by: Javier Martinez Canillas +--- + util/grub.d/10_linux.in | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index e490e1a43a..865af3d6c4 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -256,7 +256,9 @@ if [ -z "\${kernelopts}" ]; then + fi + EOF + +- update_bls_cmdline ++ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then ++ update_bls_cmdline ++ fi + + if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then + populate_menu diff --git a/SOURCES/0180-docs-grub-Document-signing-grub-under-UEFI.patch b/SOURCES/0180-docs-grub-Document-signing-grub-under-UEFI.patch deleted file mode 100644 index 9b9b19a..0000000 --- a/SOURCES/0180-docs-grub-Document-signing-grub-under-UEFI.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Sat, 15 Aug 2020 02:00:57 +1000 -Subject: [PATCH] docs/grub: Document signing grub under UEFI - -Before adding information about how grub is signed with an appended -signature scheme, it's worth adding some information about how it -can currently be signed for UEFI. - -Signed-off-by: Daniel Axtens ---- - docs/grub.texi | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/docs/grub.texi b/docs/grub.texi -index 4870faaa00a..365d1d6931b 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -5817,6 +5817,7 @@ environment variables and commands are listed in the same order. - * Secure Boot Advanced Targeting:: Embedded information for generation number based revocation - * Measured Boot:: Measuring boot components - * Lockdown:: Lockdown when booting on a secure setup -+* Signing GRUB itself:: Ensuring the integrity of the GRUB core image - @end menu - - @node Authentication and authorisation -@@ -5895,7 +5896,7 @@ commands. - - GRUB's @file{core.img} can optionally provide enforcement that all files - subsequently read from disk are covered by a valid digital signature. --This document does @strong{not} cover how to ensure that your -+This section does @strong{not} cover how to ensure that your - platform's firmware (e.g., Coreboot) validates @file{core.img}. - - If environment variable @code{check_signatures} -@@ -6067,6 +6068,25 @@ be restricted and some operations/commands cannot be executed. - The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down. - Otherwise it does not exit. - -+@node Signing GRUB itself -+@section Signing GRUB itself -+ -+To ensure a complete secure-boot chain, there must be a way for the code that -+loads GRUB to verify the integrity of the core image. -+ -+This is ultimately platform-specific and individual platforms can define their -+own mechanisms. However, there are general-purpose mechanisms that can be used -+with GRUB. -+ -+@section Signing GRUB for UEFI secure boot -+ -+On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed -+with a tool such as @command{pesign} or @command{sbsign}. Refer to the -+suggestions in @pxref{UEFI secure boot and shim} to ensure that the final -+image works under UEFI secure boot and can maintain the secure-boot chain. It -+will also be necessary to enrol the public key used into a relevant firmware -+key database. -+ - @node Platform limitations - @chapter Platform limitations - diff --git a/SOURCES/0181-Suppress-gettext-error-message.patch b/SOURCES/0181-Suppress-gettext-error-message.patch new file mode 100644 index 0000000..64b219a --- /dev/null +++ b/SOURCES/0181-Suppress-gettext-error-message.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 29 Jun 2021 13:17:42 +0200 +Subject: [PATCH] Suppress gettext error message + +Colin Watson's patch from comment #11 on the upstream bug: +https://savannah.gnu.org/bugs/?35880#comment11 + +Resolves: rhbz#1592124 + +Signed-off-by: Paulo Flabiano Smorigo +--- + grub-core/gettext/gettext.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c +index 4d02e62c10..7ec81ca0b4 100644 +--- a/grub-core/gettext/gettext.c ++++ b/grub-core/gettext/gettext.c +@@ -424,6 +424,13 @@ grub_gettext_init_ext (struct grub_gettext_context *ctx, + grub_free (lang); + } + ++ /* If no translations are available, fall back to untranslated text. */ ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ + if (locale[0] == 'e' && locale[1] == 'n' + && (locale[2] == '\0' || locale[2] == '_')) + grub_errno = err = GRUB_ERR_NONE; diff --git a/SOURCES/0181-docs-grub-Document-signing-grub-with-an-appended-sig.patch b/SOURCES/0181-docs-grub-Document-signing-grub-with-an-appended-sig.patch deleted file mode 100644 index 4d85d93..0000000 --- a/SOURCES/0181-docs-grub-Document-signing-grub-with-an-appended-sig.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Sat, 15 Aug 2020 02:19:36 +1000 -Subject: [PATCH] docs/grub: Document signing grub with an appended signature - -Signing grub for firmware that verifies an appended signature is a -bit fiddly. I don't want people to have to figure it out from scratch -so document it here. - -Signed-off-by: Daniel Axtens ---- - docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 42 insertions(+) - -diff --git a/docs/grub.texi b/docs/grub.texi -index 365d1d6931b..afbde7c1f7b 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -6087,6 +6087,48 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It - will also be necessary to enrol the public key used into a relevant firmware - key database. - -+@section Signing GRUB with an appended signature -+ -+The @file{core.elf} itself can be signed with a Linux kernel module-style -+appended signature. -+ -+To support IEEE1275 platforms where the boot image is often loaded directly -+from a disk partition rather than from a file system, the @file{core.elf} -+can specify the size and location of the appended signature with an ELF -+note added by @command{grub-install}. -+ -+An image can be signed this way using the @command{sign-file} command from -+the Linux kernel: -+ -+@example -+@group -+# grub.key is your private key and certificate.der is your public key -+ -+# Determine the size of the appended signature. It depends on the signing -+# certificate and the hash algorithm -+touch empty -+sign-file SHA256 grub.key certificate.der empty empty.sig -+SIG_SIZE=`stat -c '%s' empty.sig` -+rm empty empty.sig -+ -+# Build a grub image with $SIG_SIZE reserved for the signature -+grub-install --appended-signature-size $SIG_SIZE --modules="..." ... -+ -+# Replace the reserved size with a signature: -+# cut off the last $SIG_SIZE bytes with truncate's minus modifier -+truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned -+# sign the trimmed file with an appended signature, restoring the correct size -+sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed -+ -+# Don't forget to install the signed image as required -+# (e.g. on powerpc-ieee1275, to the PReP partition) -+@end group -+@end example -+ -+As with UEFI secure boot, it is necessary to build in the required modules, -+or sign them separately. -+ -+ - @node Platform limitations - @chapter Platform limitations - diff --git a/SOURCES/0182-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch b/SOURCES/0182-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch deleted file mode 100644 index 6e46db0..0000000 --- a/SOURCES/0182-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 30 Jul 2020 00:13:21 +1000 -Subject: [PATCH] dl: provide a fake grub_dl_set_persistent for the emu target - -Trying to start grub-emu with a module that calls grub_dl_set_persistent -will crash because grub-emu fakes modules and passes NULL to the module -init function. - -Provide an empty function for the emu case. - -Fixes: ee7808e2197c (dl: Add support for persistent modules) -Signed-off-by: Daniel Axtens ---- - include/grub/dl.h | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 2f76e6b0437..20d870f2a47 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -245,11 +245,22 @@ grub_dl_get (const char *name) - return 0; - } - -+#ifdef GRUB_MACHINE_EMU -+/* -+ * Under grub-emu, modules are faked and NULL is passed to GRUB_MOD_INIT. -+ * So we fake this out to avoid a NULL deref. -+ */ -+static inline void -+grub_dl_set_persistent (grub_dl_t mod __attribute__((unused))) -+{ -+} -+#else - static inline void - grub_dl_set_persistent (grub_dl_t mod) - { - mod->persistent = 1; - } -+#endif - - static inline int - grub_dl_is_persistent (grub_dl_t mod) diff --git a/SOURCES/0182-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch b/SOURCES/0182-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch new file mode 100644 index 0000000..b5d5e5c --- /dev/null +++ b/SOURCES/0182-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 5 Jul 2021 18:24:22 +0200 +Subject: [PATCH] grub-set-password: Always use /boot/grub2/user.cfg as + password default + +The GRUB configuration file is always placed in /boot/grub2/ now, even for +EFI. But the tool is still creating the user.cfg in the ESP and not there. + +Resolves: rhbz#1955294 + +Signed-off-by: Javier Martinez Canillas +--- + util/grub-set-password.in | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/util/grub-set-password.in b/util/grub-set-password.in +index c0b5ebbfdc..d8005e5a14 100644 +--- a/util/grub-set-password.in ++++ b/util/grub-set-password.in +@@ -1,11 +1,6 @@ + #!/bin/sh -e + +-EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') +-if [ -d /sys/firmware/efi/efivars/ ]; then +- grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` +-else +- grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` +-fi ++grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` + + PACKAGE_VERSION="@PACKAGE_VERSION@" + PACKAGE_NAME="@PACKAGE_NAME@" +@@ -116,8 +111,6 @@ if [ -z "${MYPASS}" ]; then + exit 1 + fi + +-# on the ESP, these will fail to set the permissions, but it's okay because +-# the directory is protected. + install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : + chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : + echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" diff --git a/SOURCES/0183-pgp-factor-out-rsa_pad.patch b/SOURCES/0183-pgp-factor-out-rsa_pad.patch deleted file mode 100644 index a8154e7..0000000 --- a/SOURCES/0183-pgp-factor-out-rsa_pad.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 1 Oct 2020 20:23:48 +1000 -Subject: [PATCH] pgp: factor out rsa_pad - -rsa_pad does the PKCS#1 v1.5 padding for the RSA signature scheme. -We want to use it in other RSA signature verification applications. - -I considered and rejected putting it in lib/crypto.c. That file doesn't -currently require any MPI functions, but rsa_pad does. That's not so -much of a problem for the grub kernel and modules, but crypto.c also -gets built into all the grub utilities. So - despite the utils not -using any asymmetric ciphers - we would need to built the entire MPI -infrastructure in to them. - -A better and simpler solution is just to spin rsa_pad out into its own -PKCS#1 v1.5 module. - -Signed-off-by: Daniel Axtens ---- - grub-core/Makefile.core.def | 8 ++++++ - grub-core/commands/pgp.c | 28 ++------------------- - grub-core/lib/pkcs1_v15.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ - include/grub/pkcs1_v15.h | 27 +++++++++++++++++++++ - 4 files changed, 96 insertions(+), 26 deletions(-) - create mode 100644 grub-core/lib/pkcs1_v15.c - create mode 100644 include/grub/pkcs1_v15.h - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 81fc274148e..97347ae76f9 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2510,6 +2510,14 @@ module = { - cppflags = '$(CPPFLAGS_GCRY)'; - }; - -+module = { -+ name = pkcs1_v15; -+ common = lib/pkcs1_v15.c; -+ -+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; -+ cppflags = '$(CPPFLAGS_GCRY)'; -+}; -+ - module = { - name = all_video; - common = lib/fake_module.c; -diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c -index 5daa1e9d00c..2408db4994f 100644 ---- a/grub-core/commands/pgp.c -+++ b/grub-core/commands/pgp.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -411,32 +412,7 @@ static int - rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, - const gcry_md_spec_t *hash, struct grub_public_subkey *sk) - { -- grub_size_t tlen, emlen, fflen; -- grub_uint8_t *em, *emptr; -- unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]); -- int ret; -- tlen = hash->mdlen + hash->asnlen; -- emlen = (nbits + 7) / 8; -- if (emlen < tlen + 11) -- return 1; -- -- em = grub_malloc (emlen); -- if (!em) -- return 1; -- -- em[0] = 0x00; -- em[1] = 0x01; -- fflen = emlen - tlen - 3; -- for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) -- *emptr = 0xff; -- *emptr++ = 0x00; -- grub_memcpy (emptr, hash->asnoid, hash->asnlen); -- emptr += hash->asnlen; -- grub_memcpy (emptr, hval, hash->mdlen); -- -- ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); -- grub_free (em); -- return ret; -+ return grub_crypto_rsa_pad(hmpi, hval, hash, sk->mpis[0]); - } - - struct grub_pubkey_context -diff --git a/grub-core/lib/pkcs1_v15.c b/grub-core/lib/pkcs1_v15.c -new file mode 100644 -index 00000000000..dbacd563d01 ---- /dev/null -+++ b/grub-core/lib/pkcs1_v15.c -@@ -0,0 +1,59 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2013 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+/* -+ * Given a hash value 'hval', of hash specification 'hash', perform -+ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod' -+ * (see RFC 8017 s 9.2) and place the result in 'hmpi'. -+ */ -+gcry_err_code_t -+grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval, -+ const gcry_md_spec_t * hash, gcry_mpi_t mod) -+{ -+ grub_size_t tlen, emlen, fflen; -+ grub_uint8_t *em, *emptr; -+ unsigned nbits = gcry_mpi_get_nbits (mod); -+ int ret; -+ tlen = hash->mdlen + hash->asnlen; -+ emlen = (nbits + 7) / 8; -+ if (emlen < tlen + 11) -+ return GPG_ERR_TOO_SHORT; -+ -+ em = grub_malloc (emlen); -+ if (!em) -+ return 1; -+ -+ em[0] = 0x00; -+ em[1] = 0x01; -+ fflen = emlen - tlen - 3; -+ for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) -+ *emptr = 0xff; -+ *emptr++ = 0x00; -+ grub_memcpy (emptr, hash->asnoid, hash->asnlen); -+ emptr += hash->asnlen; -+ grub_memcpy (emptr, hval, hash->mdlen); -+ -+ ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); -+ grub_free (em); -+ return ret; -+} -diff --git a/include/grub/pkcs1_v15.h b/include/grub/pkcs1_v15.h -new file mode 100644 -index 00000000000..5c338c84a15 ---- /dev/null -+++ b/include/grub/pkcs1_v15.h -@@ -0,0 +1,27 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2013 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+/* -+ * Given a hash value 'hval', of hash specification 'hash', perform -+ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod' -+ * (See RFC 8017 s 9.2) -+ */ -+gcry_err_code_t -+grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval, -+ const gcry_md_spec_t * hash, gcry_mpi_t mod); -+ diff --git a/SOURCES/0183-templates-Check-for-EFI-at-runtime-instead-of-config.patch b/SOURCES/0183-templates-Check-for-EFI-at-runtime-instead-of-config.patch new file mode 100644 index 0000000..265b967 --- /dev/null +++ b/SOURCES/0183-templates-Check-for-EFI-at-runtime-instead-of-config.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 6 Jul 2021 00:38:40 +0200 +Subject: [PATCH] templates: Check for EFI at runtime instead of config + generation time + +The 30_uefi-firmware template checks if an OsIndicationsSupported UEFI var +exists and EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, to decide whether +a "fwsetup" menu entry would be added or not to the GRUB menu. + +But this has the problem that it will only work if the configuration file +was created on an UEFI machine that supports booting to a firmware UI. + +This for example doesn't support creating GRUB config files when executing +on systems that support both UEFI and legacy BIOS booting. Since creating +the config file from legacy BIOS wouldn't allow to access the firmware UI. + +To prevent this, make the template to unconditionally create the grub.cfg +snippet but check at runtime if was booted through UEFI to decide if this +entry should be added. That way it won't be added when booting with BIOS. + +There's no need to check if EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, +since that's already done by the "fwsetup" command when is executed. + +Resolves: rhbz#1823864 + +Signed-off-by: Javier Martinez Canillas +--- + util/grub.d/30_uefi-firmware.in | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/util/grub.d/30_uefi-firmware.in b/util/grub.d/30_uefi-firmware.in +index d344d3883d..b6041b55e2 100644 +--- a/util/grub.d/30_uefi-firmware.in ++++ b/util/grub.d/30_uefi-firmware.in +@@ -26,19 +26,14 @@ export TEXTDOMAINDIR="@localedir@" + + . "$pkgdatadir/grub-mkconfig_lib" + +-EFI_VARS_DIR=/sys/firmware/efi/efivars +-EFI_GLOBAL_VARIABLE=8be4df61-93ca-11d2-aa0d-00e098032b8c +-OS_INDICATIONS="$EFI_VARS_DIR/OsIndicationsSupported-$EFI_GLOBAL_VARIABLE" ++LABEL="UEFI Firmware Settings" + +-if [ -e "$OS_INDICATIONS" ] && \ +- [ "$(( $(printf 0x%x \'"$(cat $OS_INDICATIONS | cut -b5)"\') & 1 ))" = 1 ]; then +- LABEL="UEFI Firmware Settings" ++gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 + +- gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 +- +- cat << EOF +-menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { +- fwsetup +-} +-EOF ++cat << EOF ++if [ "\$grub_platform" = "efi" ]; then ++ menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { ++ fwsetup ++ } + fi ++EOF diff --git a/SOURCES/0184-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch b/SOURCES/0184-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch deleted file mode 100644 index 763cdc6..0000000 --- a/SOURCES/0184-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 2 Oct 2020 10:49:26 +1000 -Subject: [PATCH] crypto: move storage for grub_crypto_pk_* to crypto.c - -The way gcry_rsa and friends (the asymmetric ciphers) are loaded for the -pgp module is a bit quirky. - -include/grub/crypto.h contains: - extern struct gcry_pk_spec *grub_crypto_pk_rsa; - -commands/pgp.c contains the actual storage: - struct gcry_pk_spec *grub_crypto_pk_rsa; - -And the module itself saves to the storage in pgp.c: - GRUB_MOD_INIT(gcry_rsa) - { - grub_crypto_pk_rsa = &_gcry_pubkey_spec_rsa; - } - -This is annoying: gcry_rsa now has a dependency on pgp! - -We want to be able to bring in gcry_rsa without bringing in PGP, -so move the storage to crypto.c. - -Previously, gcry_rsa depended on pgp and mpi. Now it depends on -crypto and mpi. As pgp depends on crypto, this doesn't add any new -module dependencies using the PGP verfier. - -[FWIW, the story is different for the symmetric ciphers. cryptodisk -and friends (zfs encryption etc) use grub_crypto_lookup_cipher_by_name() -to get a cipher handle. That depends on grub_ciphers being populated -by people calling grub_cipher_register. import_gcry.py ensures that the -symmetric ciphers call it.] - -Signed-off-by: Daniel Axtens ---- - grub-core/commands/pgp.c | 4 ---- - grub-core/lib/crypto.c | 4 ++++ - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c -index 2408db4994f..355a43844ac 100644 ---- a/grub-core/commands/pgp.c -+++ b/grub-core/commands/pgp.c -@@ -147,10 +147,6 @@ const char *hashes[] = { - [0x0b] = "sha224" - }; - --struct gcry_pk_spec *grub_crypto_pk_dsa; --struct gcry_pk_spec *grub_crypto_pk_ecdsa; --struct gcry_pk_spec *grub_crypto_pk_rsa; -- - static int - dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, - const gcry_md_spec_t *hash, struct grub_public_subkey *sk); -diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c -index ca334d5a40e..c578128a59d 100644 ---- a/grub-core/lib/crypto.c -+++ b/grub-core/lib/crypto.c -@@ -121,6 +121,10 @@ grub_md_unregister (gcry_md_spec_t *cipher) - } - } - -+struct gcry_pk_spec *grub_crypto_pk_dsa; -+struct gcry_pk_spec *grub_crypto_pk_ecdsa; -+struct gcry_pk_spec *grub_crypto_pk_rsa; -+ - void - grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, - grub_size_t inlen) diff --git a/SOURCES/0184-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch b/SOURCES/0184-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch new file mode 100644 index 0000000..3b1a219 --- /dev/null +++ b/SOURCES/0184-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 6 Jul 2021 01:10:18 +0200 +Subject: [PATCH] efi: Print an error if boot to firmware setup is not + supported + +The "fwsetup" command is only registered if the firmware supports booting +to the firmware setup UI. But it could be possible that the GRUB config +already contains a "fwsetup" entry, because it was generated in a machine +that has support for this feature. + +To prevent users getting a "can't find command `fwsetup`" error if it is +not supported by the firmware, let's just always register the command but +print a more accurate message if the firmware doesn't support this option. + +Resolves: rhbz#1823864 + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/commands/efi/efifwsetup.c | 43 ++++++++++++++++++++----------------- + 1 file changed, 23 insertions(+), 20 deletions(-) + +diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c +index eaca032838..328c45e82e 100644 +--- a/grub-core/commands/efi/efifwsetup.c ++++ b/grub-core/commands/efi/efifwsetup.c +@@ -27,6 +27,25 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + ++static grub_efi_boolean_t ++efifwsetup_is_supported (void) ++{ ++ grub_efi_uint64_t *os_indications_supported = NULL; ++ grub_size_t oi_size = 0; ++ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; ++ ++ grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, ++ (void **) &os_indications_supported); ++ ++ if (!os_indications_supported) ++ return 0; ++ ++ if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) ++ return 1; ++ ++ return 0; ++} ++ + static grub_err_t + grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), +@@ -38,6 +57,10 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + grub_size_t oi_size; + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + ++ if (!efifwsetup_is_supported ()) ++ return grub_error (GRUB_ERR_INVALID_COMMAND, ++ N_("Reboot to firmware setup is not supported")); ++ + grub_efi_get_variable ("OsIndications", &global, &oi_size, + (void **) &old_os_indications); + +@@ -56,28 +79,8 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + + static grub_command_t cmd = NULL; + +-static grub_efi_boolean_t +-efifwsetup_is_supported (void) +-{ +- grub_efi_uint64_t *os_indications_supported = NULL; +- grub_size_t oi_size = 0; +- grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; +- +- grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, +- (void **) &os_indications_supported); +- +- if (!os_indications_supported) +- return 0; +- +- if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) +- return 1; +- +- return 0; +-} +- + GRUB_MOD_INIT (efifwsetup) + { +- if (efifwsetup_is_supported ()) + cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, + N_("Reboot into firmware setup menu.")); + diff --git a/SOURCES/0185-arm64-Fix-EFI-loader-kernel-image-allocation.patch b/SOURCES/0185-arm64-Fix-EFI-loader-kernel-image-allocation.patch new file mode 100644 index 0000000..cc5458c --- /dev/null +++ b/SOURCES/0185-arm64-Fix-EFI-loader-kernel-image-allocation.patch @@ -0,0 +1,218 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Mon, 2 Aug 2021 23:10:01 +1000 +Subject: [PATCH] arm64: Fix EFI loader kernel image allocation + +We are currently allocating just enough memory for the file size, +which means that the kernel BSS is in limbo (and not even zeroed). + +We are also not honoring the alignment specified in the image +PE header. + +This makes us use the PE optional header in which the kernel puts the +actual size it needs, including BSS, and make sure we clear it, and +honors the specified alignment for the image. + +Signed-off-by: Benjamin Herrenschmidt +[pjones: arm: check for the PE magic for the compiled arch] +Signed-off-by: Peter Jones +Signed-off-by: Robbie Harwood +--- + grub-core/loader/arm64/linux.c | 100 +++++++++++++++++++++++++++-------------- + include/grub/arm/linux.h | 1 + + include/grub/arm64/linux.h | 1 + + 3 files changed, 68 insertions(+), 34 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 47f8cf0d84..f18d90bd74 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -41,6 +41,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; + static int loaded; + ++static void *kernel_alloc_addr; ++static grub_uint32_t kernel_alloc_pages; + static void *kernel_addr; + static grub_uint64_t kernel_size; + static grub_uint32_t handover_offset; +@@ -204,9 +206,8 @@ grub_linux_unload (void) + GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start)); + initrd_start = initrd_end = 0; + grub_free (linux_args); +- if (kernel_addr) +- grub_efi_free_pages ((grub_addr_t) kernel_addr, +- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); ++ if (kernel_alloc_addr) ++ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); + grub_fdt_unload (); + return GRUB_ERR_NONE; + } +@@ -311,14 +312,35 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + return grub_errno; + } + ++static grub_err_t ++parse_pe_header (void *kernel, grub_uint64_t *total_size, ++ grub_uint32_t *entry_offset, ++ grub_uint32_t *alignment) ++{ ++ struct linux_arch_kernel_header *lh = kernel; ++ struct grub_armxx_linux_pe_header *pe; ++ ++ pe = (void *)((unsigned long)kernel + lh->hdr_offset); ++ ++ if (pe->opt.magic != GRUB_PE32_PEXX_MAGIC) ++ return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic"); ++ ++ *total_size = pe->opt.image_size; ++ *entry_offset = pe->opt.entry_addr; ++ *alignment = pe->opt.section_alignment; ++ ++ return GRUB_ERR_NONE; ++} ++ + static grub_err_t + grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- struct linux_arch_kernel_header lh; +- struct grub_armxx_linux_pe_header *pe; + grub_err_t err; ++ grub_off_t filelen; ++ grub_uint32_t align; ++ void *kernel = NULL; + int rc; + + grub_dl_ref (my_mod); +@@ -333,40 +355,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (!file) + goto fail; + +- kernel_size = grub_file_size (file); +- +- if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) +- return grub_errno; +- +- if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) +- goto fail; +- +- grub_loader_unset(); +- +- grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size); +- kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size)); +- grub_dprintf ("linux", "kernel numpages: %lld\n", +- (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size)); +- if (!kernel_addr) ++ filelen = grub_file_size (file); ++ kernel = grub_malloc(filelen); ++ if (!kernel) + { +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel load buffer")); + goto fail; + } + +- grub_file_seek (file, 0); +- if (grub_file_read (file, kernel_addr, kernel_size) +- < (grub_int64_t) kernel_size) ++ if (grub_file_read (file, kernel, filelen) < (grub_ssize_t)filelen) + { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), ++ argv[0]); + goto fail; + } + +- grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); +- + if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { +- rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); ++ rc = grub_linuxefi_secure_validate (kernel, filelen); + if (rc <= 0) + { + grub_error (GRUB_ERR_INVALID_COMMAND, +@@ -375,8 +381,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + } + +- pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); +- handover_offset = pe->opt.entry_addr; ++ if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) ++ goto fail; ++ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) ++ goto fail; ++ grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); ++ grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); ++ grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); ++ ++ grub_loader_unset(); ++ ++ kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); ++ kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages); ++ grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages); ++ if (!kernel_alloc_addr) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); ++ ++ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); ++ grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); ++ if (kernel_size > filelen) ++ grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); ++ grub_free(kernel); ++ kernel = NULL; + + cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); + linux_args = grub_malloc (cmdline_size); +@@ -400,6 +430,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + + fail: ++ if (kernel) ++ grub_free (kernel); ++ + if (file) + grub_file_close (file); + +@@ -412,9 +445,8 @@ fail: + if (linux_args && !loaded) + grub_free (linux_args); + +- if (kernel_addr && !loaded) +- grub_efi_free_pages ((grub_addr_t) kernel_addr, +- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); ++ if (kernel_alloc_addr && !loaded) ++ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); + + return grub_errno; + } +diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h +index b582f67f66..966a5074f5 100644 +--- a/include/grub/arm/linux.h ++++ b/include/grub/arm/linux.h +@@ -44,6 +44,7 @@ struct grub_arm_linux_pe_header + + #if defined(__arm__) + # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE ++# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE32_MAGIC + # define linux_arch_kernel_header linux_arm_kernel_header + # define grub_armxx_linux_pe_header grub_arm_linux_pe_header + #endif +diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h +index ea030312df..422bf2bf24 100644 +--- a/include/grub/arm64/linux.h ++++ b/include/grub/arm64/linux.h +@@ -48,6 +48,7 @@ struct grub_arm64_linux_pe_header + + #if defined(__aarch64__) + # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE ++# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE64_MAGIC + # define linux_arch_kernel_header linux_arm64_kernel_header + # define grub_armxx_linux_pe_header grub_arm64_linux_pe_header + #endif diff --git a/SOURCES/0185-posix_wrap-tweaks-in-preparation-for-libtasn1.patch b/SOURCES/0185-posix_wrap-tweaks-in-preparation-for-libtasn1.patch deleted file mode 100644 index a09cab1..0000000 --- a/SOURCES/0185-posix_wrap-tweaks-in-preparation-for-libtasn1.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Sat, 2 May 2020 00:27:57 +1000 -Subject: [PATCH] posix_wrap: tweaks in preparation for libtasn1 - - - Define SIZEOF_UNSIGNED_LONG_INT, it's the same as - SIZEOF_UNSIGNED_LONG. - - - Define WORD_BIT, the size in bits of an int. This is a defined - in the Single Unix Specification and in gnulib's limits.h. gnulib - assumes it's 32 bits on all our platforms, including 64 bit - platforms, so we also use that value. - - - Provide strto[u]l[l] preprocessor macros that resolve to - grub_strto[u]l[l]. To avoid gcrypt redefining strtoul, we - also define HAVE_STRTOUL here. - -Signed-off-by: Daniel Axtens ---- - grub-core/lib/posix_wrap/limits.h | 1 + - grub-core/lib/posix_wrap/stdlib.h | 8 ++++++++ - grub-core/lib/posix_wrap/sys/types.h | 1 + - 3 files changed, 10 insertions(+) - -diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h -index 7217138ffd6..591dbf3289d 100644 ---- a/grub-core/lib/posix_wrap/limits.h -+++ b/grub-core/lib/posix_wrap/limits.h -@@ -37,5 +37,6 @@ - #define LONG_MAX GRUB_LONG_MAX - - #define CHAR_BIT 8 -+#define WORD_BIT 32 - - #endif -diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h -index 7a8d385e973..4634db09f29 100644 ---- a/grub-core/lib/posix_wrap/stdlib.h -+++ b/grub-core/lib/posix_wrap/stdlib.h -@@ -58,4 +58,12 @@ abs (int c) - return (c >= 0) ? c : -c; - } - -+#define strtol grub_strtol -+ -+/* for libgcrypt */ -+#define HAVE_STRTOUL -+#define strtoul grub_strtoul -+ -+#define strtoull grub_strtoull -+ - #endif -diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h -index 854eb0122ef..f63412c8da0 100644 ---- a/grub-core/lib/posix_wrap/sys/types.h -+++ b/grub-core/lib/posix_wrap/sys/types.h -@@ -51,6 +51,7 @@ typedef grub_uint8_t byte; - typedef grub_addr_t uintptr_t; - - #define SIZEOF_UNSIGNED_LONG GRUB_CPU_SIZEOF_LONG -+#define SIZEOF_UNSIGNED_LONG_INT GRUB_CPU_SIZEOF_LONG - #define SIZEOF_UNSIGNED_INT 4 - #define SIZEOF_UNSIGNED_LONG_LONG 8 - #define SIZEOF_UNSIGNED_SHORT 2 diff --git a/SOURCES/0186-libtasn1-import-libtasn1-4.16.0.patch b/SOURCES/0186-libtasn1-import-libtasn1-4.16.0.patch deleted file mode 100644 index 89552c8..0000000 --- a/SOURCES/0186-libtasn1-import-libtasn1-4.16.0.patch +++ /dev/null @@ -1,8934 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Wed, 10 Jun 2020 16:31:22 +1000 -Subject: [PATCH] libtasn1: import libtasn1-4.16.0 - -Import a very trimmed-down set of libtasn1 files: - -pushd /tmp -wget https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.16.0.tar.gz -popd -pushd grub-core/lib -mkdir libtasn1 -cp /tmp/libtasn1-4.16.0/{README.md,LICENSE} libtasn1/ -mkdir libtasn1/lib -cp /tmp/libtasn1-4.16.0/lib/{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h} libtasn1/lib -cp /tmp/libtasn1-4.16.0/lib/includes/libtasn1.h ../../include/grub/ -git add libtasn1/ ../../include/grub/libtasn1.h -popd - -Signed-off-by: Daniel Axtens ---- - grub-core/lib/libtasn1/lib/coding.c | 1415 ++++++++++++++++++ - grub-core/lib/libtasn1/lib/decoding.c | 2478 +++++++++++++++++++++++++++++++ - grub-core/lib/libtasn1/lib/element.c | 1111 ++++++++++++++ - grub-core/lib/libtasn1/lib/errors.c | 100 ++ - grub-core/lib/libtasn1/lib/gstr.c | 74 + - grub-core/lib/libtasn1/lib/parser_aux.c | 1173 +++++++++++++++ - grub-core/lib/libtasn1/lib/structure.c | 1220 +++++++++++++++ - grub-core/lib/libtasn1/lib/element.h | 40 + - grub-core/lib/libtasn1/lib/gstr.h | 47 + - grub-core/lib/libtasn1/lib/int.h | 221 +++ - grub-core/lib/libtasn1/lib/parser_aux.h | 172 +++ - grub-core/lib/libtasn1/lib/structure.h | 45 + - include/grub/libtasn1.h | 588 ++++++++ - grub-core/lib/libtasn1/LICENSE | 16 + - grub-core/lib/libtasn1/README.md | 91 ++ - 15 files changed, 8791 insertions(+) - create mode 100644 grub-core/lib/libtasn1/lib/coding.c - create mode 100644 grub-core/lib/libtasn1/lib/decoding.c - create mode 100644 grub-core/lib/libtasn1/lib/element.c - create mode 100644 grub-core/lib/libtasn1/lib/errors.c - create mode 100644 grub-core/lib/libtasn1/lib/gstr.c - create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.c - create mode 100644 grub-core/lib/libtasn1/lib/structure.c - create mode 100644 grub-core/lib/libtasn1/lib/element.h - create mode 100644 grub-core/lib/libtasn1/lib/gstr.h - create mode 100644 grub-core/lib/libtasn1/lib/int.h - create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.h - create mode 100644 grub-core/lib/libtasn1/lib/structure.h - create mode 100644 include/grub/libtasn1.h - create mode 100644 grub-core/lib/libtasn1/LICENSE - create mode 100644 grub-core/lib/libtasn1/README.md - -diff --git a/grub-core/lib/libtasn1/lib/coding.c b/grub-core/lib/libtasn1/lib/coding.c -new file mode 100644 -index 00000000000..245ea64cf0a ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/coding.c -@@ -0,0 +1,1415 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+ -+/*****************************************************/ -+/* File: coding.c */ -+/* Description: Functions to create a DER coding of */ -+/* an ASN1 type. */ -+/*****************************************************/ -+ -+#include -+#include "parser_aux.h" -+#include -+#include "element.h" -+#include "minmax.h" -+#include -+ -+#define MAX_TAG_LEN 16 -+ -+/******************************************************/ -+/* Function : _asn1_error_description_value_not_found */ -+/* Description: creates the ErrorDescription string */ -+/* for the ASN1_VALUE_NOT_FOUND error. */ -+/* Parameters: */ -+/* node: node of the tree where the value is NULL. */ -+/* ErrorDescription: string returned. */ -+/* Return: */ -+/******************************************************/ -+static void -+_asn1_error_description_value_not_found (asn1_node node, -+ char *ErrorDescription) -+{ -+ -+ if (ErrorDescription == NULL) -+ return; -+ -+ Estrcpy (ErrorDescription, ":: value of element '"); -+ _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), -+ ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); -+ Estrcat (ErrorDescription, "' not found"); -+ -+} -+ -+/** -+ * asn1_length_der: -+ * @len: value to convert. -+ * @der: buffer to hold the returned encoding (may be %NULL). -+ * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]). -+ * -+ * Creates the DER encoding of the provided length value. -+ * The @der buffer must have enough room for the output. The maximum -+ * length this function will encode is %ASN1_MAX_LENGTH_SIZE. -+ * -+ * To know the size of the DER encoding use a %NULL value for @der. -+ **/ -+void -+asn1_length_der (unsigned long int len, unsigned char *der, int *der_len) -+{ -+ int k; -+ unsigned char temp[ASN1_MAX_LENGTH_SIZE]; -+#if SIZEOF_UNSIGNED_LONG_INT > 8 -+ len &= 0xFFFFFFFFFFFFFFFF; -+#endif -+ -+ if (len < 128) -+ { -+ /* short form */ -+ if (der != NULL) -+ der[0] = (unsigned char) len; -+ *der_len = 1; -+ } -+ else -+ { -+ /* Long form */ -+ k = 0; -+ while (len) -+ { -+ temp[k++] = len & 0xFF; -+ len = len >> 8; -+ } -+ *der_len = k + 1; -+ if (der != NULL) -+ { -+ der[0] = ((unsigned char) k & 0x7F) + 128; -+ while (k--) -+ der[*der_len - 1 - k] = temp[k]; -+ } -+ } -+} -+ -+/******************************************************/ -+/* Function : _asn1_tag_der */ -+/* Description: creates the DER coding for the CLASS */ -+/* and TAG parameters. */ -+/* It is limited by the ASN1_MAX_TAG_SIZE variable */ -+/* Parameters: */ -+/* class: value to convert. */ -+/* tag_value: value to convert. */ -+/* ans: string returned. */ -+/* ans_len: number of meaningful bytes of ANS */ -+/* (ans[0]..ans[ans_len-1]). */ -+/* Return: */ -+/******************************************************/ -+static void -+_asn1_tag_der (unsigned char class, unsigned int tag_value, -+ unsigned char ans[ASN1_MAX_TAG_SIZE], int *ans_len) -+{ -+ int k; -+ unsigned char temp[ASN1_MAX_TAG_SIZE]; -+ -+ if (tag_value < 31) -+ { -+ /* short form */ -+ ans[0] = (class & 0xE0) + ((unsigned char) (tag_value & 0x1F)); -+ *ans_len = 1; -+ } -+ else -+ { -+ /* Long form */ -+ ans[0] = (class & 0xE0) + 31; -+ k = 0; -+ while (tag_value != 0) -+ { -+ temp[k++] = tag_value & 0x7F; -+ tag_value >>= 7; -+ -+ if (k > ASN1_MAX_TAG_SIZE - 1) -+ break; /* will not encode larger tags */ -+ } -+ *ans_len = k + 1; -+ while (k--) -+ ans[*ans_len - 1 - k] = temp[k] + 128; -+ ans[*ans_len - 1] -= 128; -+ } -+} -+ -+/** -+ * asn1_octet_der: -+ * @str: the input data. -+ * @str_len: STR length (str[0]..str[*str_len-1]). -+ * @der: encoded string returned. -+ * @der_len: number of meaningful bytes of DER (der[0]..der[der_len-1]). -+ * -+ * Creates a length-value DER encoding for the input data. -+ * The DER encoding of the input data will be placed in the @der variable. -+ * -+ * Note that the OCTET STRING tag is not included in the output. -+ * -+ * This function does not return any value because it is expected -+ * that @der_len will contain enough bytes to store the string -+ * plus the DER encoding. The DER encoding size can be obtained using -+ * asn1_length_der(). -+ **/ -+void -+asn1_octet_der (const unsigned char *str, int str_len, -+ unsigned char *der, int *der_len) -+{ -+ int len_len; -+ -+ if (der == NULL || str_len < 0) -+ return; -+ -+ asn1_length_der (str_len, der, &len_len); -+ memcpy (der + len_len, str, str_len); -+ *der_len = str_len + len_len; -+} -+ -+ -+/** -+ * asn1_encode_simple_der: -+ * @etype: The type of the string to be encoded (ASN1_ETYPE_) -+ * @str: the string data. -+ * @str_len: the string length -+ * @tl: the encoded tag and length -+ * @tl_len: the bytes of the @tl field -+ * -+ * Creates the DER encoding for various simple ASN.1 types like strings etc. -+ * It stores the tag and length in @tl, which should have space for at least -+ * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl. -+ * -+ * The complete DER encoding should consist of the value in @tl appended -+ * with the provided @str. -+ * -+ * Returns: %ASN1_SUCCESS if successful or an error value. -+ **/ -+int -+asn1_encode_simple_der (unsigned int etype, const unsigned char *str, -+ unsigned int str_len, unsigned char *tl, -+ unsigned int *tl_len) -+{ -+ int tag_len, len_len; -+ unsigned tlen; -+ unsigned char der_tag[ASN1_MAX_TAG_SIZE]; -+ unsigned char der_length[ASN1_MAX_LENGTH_SIZE]; -+ unsigned char *p; -+ -+ if (str == NULL) -+ return ASN1_VALUE_NOT_VALID; -+ -+ if (ETYPE_OK (etype) == 0) -+ return ASN1_VALUE_NOT_VALID; -+ -+ /* doesn't handle constructed classes */ -+ if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL) -+ return ASN1_VALUE_NOT_VALID; -+ -+ _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len); -+ -+ asn1_length_der (str_len, der_length, &len_len); -+ -+ if (tag_len <= 0 || len_len <= 0) -+ return ASN1_VALUE_NOT_VALID; -+ -+ tlen = tag_len + len_len; -+ -+ if (*tl_len < tlen) -+ return ASN1_MEM_ERROR; -+ -+ p = tl; -+ memcpy (p, der_tag, tag_len); -+ p += tag_len; -+ memcpy (p, der_length, len_len); -+ -+ *tl_len = tlen; -+ -+ return ASN1_SUCCESS; -+} -+ -+/******************************************************/ -+/* Function : _asn1_time_der */ -+/* Description: creates the DER coding for a TIME */ -+/* type (length included). */ -+/* Parameters: */ -+/* str: TIME null-terminated string. */ -+/* der: string returned. */ -+/* der_len: number of meaningful bytes of DER */ -+/* (der[0]..der[ans_len-1]). Initially it */ -+/* if must store the lenght of DER. */ -+/* Return: */ -+/* ASN1_MEM_ERROR when DER isn't big enough */ -+/* ASN1_SUCCESS otherwise */ -+/******************************************************/ -+static int -+_asn1_time_der (unsigned char *str, int str_len, unsigned char *der, -+ int *der_len) -+{ -+ int len_len; -+ int max_len; -+ -+ if (der == NULL) -+ return ASN1_VALUE_NOT_VALID; -+ -+ max_len = *der_len; -+ -+ asn1_length_der (str_len, (max_len > 0) ? der : NULL, &len_len); -+ -+ if ((len_len + str_len) <= max_len) -+ memcpy (der + len_len, str, str_len); -+ *der_len = len_len + str_len; -+ -+ if ((*der_len) > max_len) -+ return ASN1_MEM_ERROR; -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/* -+void -+_asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str) -+{ -+ int len_len,str_len; -+ char temp[20]; -+ -+ if(str==NULL) return; -+ str_len=asn1_get_length_der(der,*der_len,&len_len); -+ if (str_len<0) return; -+ memcpy(temp,der+len_len,str_len); -+ *der_len=str_len+len_len; -+ switch(str_len) -+ { -+ case 11: -+ temp[10]=0; -+ strcat(temp,"00+0000"); -+ break; -+ case 13: -+ temp[12]=0; -+ strcat(temp,"+0000"); -+ break; -+ case 15: -+ temp[15]=0; -+ memmove(temp+12,temp+10,6); -+ temp[10]=temp[11]='0'; -+ break; -+ case 17: -+ temp[17]=0; -+ break; -+ default: -+ return; -+ } -+ strcpy(str,temp); -+} -+*/ -+ -+static -+void encode_val(uint64_t val, unsigned char *der, int max_len, int *der_len) -+{ -+ int first, k; -+ unsigned char bit7; -+ -+ first = 0; -+ for (k = sizeof(val); k >= 0; k--) -+ { -+ bit7 = (val >> (k * 7)) & 0x7F; -+ if (bit7 || first || !k) -+ { -+ if (k) -+ bit7 |= 0x80; -+ if (max_len > (*der_len)) -+ der[*der_len] = bit7; -+ (*der_len)++; -+ first = 1; -+ } -+ } -+} -+ -+/******************************************************/ -+/* Function : _asn1_object_id_der */ -+/* Description: creates the DER coding for an */ -+/* OBJECT IDENTIFIER type (length included). */ -+/* Parameters: */ -+/* str: OBJECT IDENTIFIER null-terminated string. */ -+/* der: string returned. */ -+/* der_len: number of meaningful bytes of DER */ -+/* (der[0]..der[ans_len-1]). Initially it */ -+/* must store the length of DER. */ -+/* Return: */ -+/* ASN1_MEM_ERROR when DER isn't big enough */ -+/* ASN1_SUCCESS if succesful */ -+/* or an error value. */ -+/******************************************************/ -+static int -+_asn1_object_id_der (const char *str, unsigned char *der, int *der_len) -+{ -+ int len_len, counter, max_len; -+ char *temp, *n_end, *n_start; -+ uint64_t val, val1 = 0; -+ int str_len = _asn1_strlen (str); -+ -+ max_len = *der_len; -+ *der_len = 0; -+ -+ if (der == NULL && max_len > 0) -+ return ASN1_VALUE_NOT_VALID; -+ -+ temp = malloc (str_len + 2); -+ if (temp == NULL) -+ return ASN1_MEM_ALLOC_ERROR; -+ -+ memcpy (temp, str, str_len); -+ temp[str_len] = '.'; -+ temp[str_len + 1] = 0; -+ -+ counter = 0; -+ n_start = temp; -+ while ((n_end = strchr (n_start, '.'))) -+ { -+ *n_end = 0; -+ val = _asn1_strtou64 (n_start, NULL, 10); -+ counter++; -+ -+ if (counter == 1) -+ { -+ val1 = val; -+ } -+ else if (counter == 2) -+ { -+ uint64_t val0; -+ -+ if (val1 > 2) -+ { -+ free(temp); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ else if ((val1 == 0 || val1 == 1) && val > 39) -+ { -+ free(temp); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ -+ val0 = 40 * val1 + val; -+ encode_val(val0, der, max_len, der_len); -+ } -+ else -+ { -+ encode_val(val, der, max_len, der_len); -+ } -+ n_start = n_end + 1; -+ } -+ -+ asn1_length_der (*der_len, NULL, &len_len); -+ if (max_len >= (*der_len + len_len)) -+ { -+ memmove (der + len_len, der, *der_len); -+ asn1_length_der (*der_len, der, &len_len); -+ } -+ *der_len += len_len; -+ -+ free (temp); -+ -+ if (max_len < (*der_len)) -+ return ASN1_MEM_ERROR; -+ -+ return ASN1_SUCCESS; -+} -+ -+/** -+ * asn1_object_id_der: -+ * @str: An object identifier in numeric, dot format. -+ * @der: buffer to hold the returned encoding (may be %NULL). -+ * @der_len: initially the size of @der; will hold the final size. -+ * @flags: must be zero -+ * -+ * Creates the DER encoding of the provided object identifier. -+ * -+ * Returns: %ASN1_SUCCESS if DER encoding was OK, %ASN1_VALUE_NOT_VALID -+ * if @str is not a valid OID, %ASN1_MEM_ERROR if the @der -+ * vector isn't big enough and in this case @der_len will contain the -+ * length needed. -+ **/ -+int asn1_object_id_der(const char *str, unsigned char *der, int *der_len, unsigned flags) -+{ -+ unsigned char tag_der[MAX_TAG_LEN]; -+ int tag_len = 0, r; -+ int max_len = *der_len; -+ -+ *der_len = 0; -+ -+ _asn1_tag_der (ETYPE_CLASS (ASN1_ETYPE_OBJECT_ID), ETYPE_TAG (ASN1_ETYPE_OBJECT_ID), -+ tag_der, &tag_len); -+ -+ if (max_len > tag_len) -+ { -+ memcpy(der, tag_der, tag_len); -+ } -+ max_len -= tag_len; -+ der += tag_len; -+ -+ r = _asn1_object_id_der (str, der, &max_len); -+ if (r == ASN1_MEM_ERROR || r == ASN1_SUCCESS) -+ { -+ *der_len = max_len + tag_len; -+ } -+ -+ return r; -+} -+ -+static const unsigned char bit_mask[] = -+ { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 }; -+ -+/** -+ * asn1_bit_der: -+ * @str: BIT string. -+ * @bit_len: number of meaningful bits in STR. -+ * @der: string returned. -+ * @der_len: number of meaningful bytes of DER -+ * (der[0]..der[ans_len-1]). -+ * -+ * Creates a length-value DER encoding for the input data -+ * as it would have been for a BIT STRING. -+ * The DER encoded data will be copied in @der. -+ * -+ * Note that the BIT STRING tag is not included in the output. -+ * -+ * This function does not return any value because it is expected -+ * that @der_len will contain enough bytes to store the string -+ * plus the DER encoding. The DER encoding size can be obtained using -+ * asn1_length_der(). -+ **/ -+void -+asn1_bit_der (const unsigned char *str, int bit_len, -+ unsigned char *der, int *der_len) -+{ -+ int len_len, len_byte, len_pad; -+ -+ if (der == NULL) -+ return; -+ -+ len_byte = bit_len >> 3; -+ len_pad = 8 - (bit_len & 7); -+ if (len_pad == 8) -+ len_pad = 0; -+ else -+ len_byte++; -+ asn1_length_der (len_byte + 1, der, &len_len); -+ der[len_len] = len_pad; -+ -+ if (str) -+ memcpy (der + len_len + 1, str, len_byte); -+ der[len_len + len_byte] &= bit_mask[len_pad]; -+ *der_len = len_byte + len_len + 1; -+} -+ -+ -+/******************************************************/ -+/* Function : _asn1_complete_explicit_tag */ -+/* Description: add the length coding to the EXPLICIT */ -+/* tags. */ -+/* Parameters: */ -+/* node: pointer to the tree element. */ -+/* der: string with the DER coding of the whole tree*/ -+/* counter: number of meaningful bytes of DER */ -+/* (der[0]..der[*counter-1]). */ -+/* max_len: size of der vector */ -+/* Return: */ -+/* ASN1_MEM_ERROR if der vector isn't big enough, */ -+/* otherwise ASN1_SUCCESS. */ -+/******************************************************/ -+static int -+_asn1_complete_explicit_tag (asn1_node node, unsigned char *der, -+ int *counter, int *max_len) -+{ -+ asn1_node p; -+ int is_tag_implicit, len2, len3; -+ unsigned char temp[SIZEOF_UNSIGNED_INT]; -+ -+ if (der == NULL && *max_len > 0) -+ return ASN1_VALUE_NOT_VALID; -+ -+ is_tag_implicit = 0; -+ -+ if (node->type & CONST_TAG) -+ { -+ p = node->down; -+ if (p == NULL) -+ return ASN1_DER_ERROR; -+ /* When there are nested tags we must complete them reverse to -+ the order they were created. This is because completing a tag -+ modifies all data within it, including the incomplete tags -+ which store buffer positions -- simon@josefsson.org 2002-09-06 -+ */ -+ while (p->right) -+ p = p->right; -+ while (p && p != node->down->left) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_TAG) -+ { -+ if (p->type & CONST_EXPLICIT) -+ { -+ len2 = strtol (p->name, NULL, 10); -+ _asn1_set_name (p, NULL); -+ -+ asn1_length_der (*counter - len2, temp, &len3); -+ if (len3 <= (*max_len)) -+ { -+ memmove (der + len2 + len3, der + len2, -+ *counter - len2); -+ memcpy (der + len2, temp, len3); -+ } -+ *max_len -= len3; -+ *counter += len3; -+ is_tag_implicit = 0; -+ } -+ else -+ { /* CONST_IMPLICIT */ -+ if (!is_tag_implicit) -+ { -+ is_tag_implicit = 1; -+ } -+ } -+ } -+ p = p->left; -+ } -+ } -+ -+ if (*max_len < 0) -+ return ASN1_MEM_ERROR; -+ -+ return ASN1_SUCCESS; -+} -+ -+const tag_and_class_st _asn1_tags[] = { -+ [ASN1_ETYPE_GENERALSTRING] = -+ {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"}, -+ [ASN1_ETYPE_NUMERIC_STRING] = -+ {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"}, -+ [ASN1_ETYPE_IA5_STRING] = -+ {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"}, -+ [ASN1_ETYPE_TELETEX_STRING] = -+ {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"}, -+ [ASN1_ETYPE_PRINTABLE_STRING] = -+ {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"}, -+ [ASN1_ETYPE_UNIVERSAL_STRING] = -+ {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"}, -+ [ASN1_ETYPE_BMP_STRING] = -+ {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, -+ [ASN1_ETYPE_UTF8_STRING] = -+ {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, -+ [ASN1_ETYPE_VISIBLE_STRING] = -+ {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, -+ [ASN1_ETYPE_OCTET_STRING] = -+ {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, -+ [ASN1_ETYPE_BIT_STRING] = -+ {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"}, -+ [ASN1_ETYPE_OBJECT_ID] = -+ {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"}, -+ [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"}, -+ [ASN1_ETYPE_BOOLEAN] = -+ {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"}, -+ [ASN1_ETYPE_INTEGER] = -+ {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"}, -+ [ASN1_ETYPE_ENUMERATED] = -+ {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"}, -+ [ASN1_ETYPE_SEQUENCE] = -+ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, -+ "type:SEQUENCE"}, -+ [ASN1_ETYPE_SEQUENCE_OF] = -+ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, -+ "type:SEQ_OF"}, -+ [ASN1_ETYPE_SET] = -+ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"}, -+ [ASN1_ETYPE_SET_OF] = -+ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, -+ "type:SET_OF"}, -+ [ASN1_ETYPE_GENERALIZED_TIME] = -+ {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"}, -+ [ASN1_ETYPE_UTC_TIME] = -+ {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"}, -+}; -+ -+unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]); -+ -+/******************************************************/ -+/* Function : _asn1_insert_tag_der */ -+/* Description: creates the DER coding of tags of one */ -+/* NODE. */ -+/* Parameters: */ -+/* node: pointer to the tree element. */ -+/* der: string returned */ -+/* counter: number of meaningful bytes of DER */ -+/* (counter[0]..der[*counter-1]). */ -+/* max_len: size of der vector */ -+/* Return: */ -+/* ASN1_GENERIC_ERROR if the type is unknown, */ -+/* ASN1_MEM_ERROR if der vector isn't big enough, */ -+/* otherwise ASN1_SUCCESS. */ -+/******************************************************/ -+static int -+_asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, -+ int *max_len) -+{ -+ asn1_node p; -+ int tag_len, is_tag_implicit; -+ unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)]; -+ unsigned long tag_implicit = 0; -+ unsigned char tag_der[MAX_TAG_LEN]; -+ -+ is_tag_implicit = 0; -+ -+ if (node->type & CONST_TAG) -+ { -+ p = node->down; -+ while (p) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_TAG) -+ { -+ if (p->type & CONST_APPLICATION) -+ class = ASN1_CLASS_APPLICATION; -+ else if (p->type & CONST_UNIVERSAL) -+ class = ASN1_CLASS_UNIVERSAL; -+ else if (p->type & CONST_PRIVATE) -+ class = ASN1_CLASS_PRIVATE; -+ else -+ class = ASN1_CLASS_CONTEXT_SPECIFIC; -+ -+ if (p->type & CONST_EXPLICIT) -+ { -+ if (is_tag_implicit) -+ _asn1_tag_der (class_implicit, tag_implicit, tag_der, -+ &tag_len); -+ else -+ _asn1_tag_der (class | ASN1_CLASS_STRUCTURED, -+ _asn1_strtoul (p->value, NULL, 10), -+ tag_der, &tag_len); -+ -+ *max_len -= tag_len; -+ if (der && *max_len >= 0) -+ memcpy (der + *counter, tag_der, tag_len); -+ *counter += tag_len; -+ -+ _asn1_ltostr (*counter, (char *) temp); -+ _asn1_set_name (p, (const char *) temp); -+ -+ is_tag_implicit = 0; -+ } -+ else -+ { /* CONST_IMPLICIT */ -+ if (!is_tag_implicit) -+ { -+ if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || -+ (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) -+ || (type_field (node->type) == ASN1_ETYPE_SET) -+ || (type_field (node->type) == ASN1_ETYPE_SET_OF)) -+ class |= ASN1_CLASS_STRUCTURED; -+ class_implicit = class; -+ tag_implicit = _asn1_strtoul (p->value, NULL, 10); -+ is_tag_implicit = 1; -+ } -+ } -+ } -+ p = p->right; -+ } -+ } -+ -+ if (is_tag_implicit) -+ { -+ _asn1_tag_der (class_implicit, tag_implicit, tag_der, &tag_len); -+ } -+ else -+ { -+ unsigned type = type_field (node->type); -+ switch (type) -+ { -+ CASE_HANDLED_ETYPES: -+ _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag, -+ tag_der, &tag_len); -+ break; -+ case ASN1_ETYPE_TAG: -+ case ASN1_ETYPE_CHOICE: -+ case ASN1_ETYPE_ANY: -+ tag_len = 0; -+ break; -+ default: -+ return ASN1_GENERIC_ERROR; -+ } -+ } -+ -+ *max_len -= tag_len; -+ if (der && *max_len >= 0) -+ memcpy (der + *counter, tag_der, tag_len); -+ *counter += tag_len; -+ -+ if (*max_len < 0) -+ return ASN1_MEM_ERROR; -+ -+ return ASN1_SUCCESS; -+} -+ -+/******************************************************/ -+/* Function : _asn1_ordering_set */ -+/* Description: puts the elements of a SET type in */ -+/* the correct order according to DER rules. */ -+/* Parameters: */ -+/* der: string with the DER coding. */ -+/* node: pointer to the SET element. */ -+/* Return: */ -+/* ASN1_SUCCESS if successful */ -+/* or an error value. */ -+/******************************************************/ -+static int -+_asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) -+{ -+ struct vet -+ { -+ int end; -+ unsigned long value; -+ struct vet *next, *prev; -+ }; -+ -+ int counter, len, len2; -+ struct vet *first, *last, *p_vet, *p2_vet; -+ asn1_node p; -+ unsigned char class, *temp; -+ unsigned long tag, t; -+ int err; -+ -+ counter = 0; -+ -+ if (type_field (node->type) != ASN1_ETYPE_SET) -+ return ASN1_VALUE_NOT_VALID; -+ -+ p = node->down; -+ while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || -+ (type_field (p->type) == ASN1_ETYPE_SIZE))) -+ p = p->right; -+ -+ if ((p == NULL) || (p->right == NULL)) -+ return ASN1_SUCCESS; -+ -+ first = last = NULL; -+ while (p) -+ { -+ p_vet = malloc (sizeof (struct vet)); -+ if (p_vet == NULL) -+ { -+ err = ASN1_MEM_ALLOC_ERROR; -+ goto error; -+ } -+ -+ p_vet->next = NULL; -+ p_vet->prev = last; -+ if (first == NULL) -+ first = p_vet; -+ else -+ last->next = p_vet; -+ last = p_vet; -+ -+ /* tag value calculation */ -+ err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2, -+ &tag); -+ if (err != ASN1_SUCCESS) -+ goto error; -+ -+ t = ((unsigned int)class) << 24; -+ p_vet->value = t | tag; -+ counter += len2; -+ -+ /* extraction and length */ -+ len2 = asn1_get_length_der (der + counter, der_len - counter, &len); -+ if (len2 < 0) -+ { -+ err = ASN1_DER_ERROR; -+ goto error; -+ } -+ counter += len + len2; -+ -+ p_vet->end = counter; -+ p = p->right; -+ } -+ -+ p_vet = first; -+ -+ while (p_vet) -+ { -+ p2_vet = p_vet->next; -+ counter = 0; -+ while (p2_vet) -+ { -+ if (p_vet->value > p2_vet->value) -+ { -+ /* change position */ -+ temp = malloc (p_vet->end - counter); -+ if (temp == NULL) -+ { -+ err = ASN1_MEM_ALLOC_ERROR; -+ goto error; -+ } -+ -+ memcpy (temp, der + counter, p_vet->end - counter); -+ memcpy (der + counter, der + p_vet->end, -+ p2_vet->end - p_vet->end); -+ memcpy (der + counter + p2_vet->end - p_vet->end, temp, -+ p_vet->end - counter); -+ free (temp); -+ -+ tag = p_vet->value; -+ p_vet->value = p2_vet->value; -+ p2_vet->value = tag; -+ -+ p_vet->end = counter + (p2_vet->end - p_vet->end); -+ } -+ counter = p_vet->end; -+ -+ p2_vet = p2_vet->next; -+ p_vet = p_vet->next; -+ } -+ -+ if (p_vet != first) -+ p_vet->prev->next = NULL; -+ else -+ first = NULL; -+ free (p_vet); -+ p_vet = first; -+ } -+ return ASN1_SUCCESS; -+ -+error: -+ while (first != NULL) -+ { -+ p_vet = first; -+ first = first->next; -+ free(p_vet); -+ } -+ return err; -+} -+ -+struct vet -+{ -+ unsigned char *ptr; -+ int size; -+}; -+ -+static int setof_compar(const void *_e1, const void *_e2) -+{ -+ unsigned length; -+ const struct vet *e1 = _e1, *e2 = _e2; -+ int rval; -+ -+ /* The encodings of the component values of a set-of value shall -+ * appear in ascending order, the encodings being compared -+ * as octet strings with the shorter components being -+ * padded at their trailing end with 0-octets. -+ * The padding octets are for comparison purposes and -+ * do not appear in the encodings. -+ */ -+ length = MIN(e1->size, e2->size); -+ -+ rval = memcmp(e1->ptr, e2->ptr, length); -+ if (rval == 0 && e1->size != e2->size) -+ { -+ if (e1->size > e2->size) -+ rval = 1; -+ else if (e2->size > e1->size) -+ rval = -1; -+ } -+ -+ return rval; -+} -+ -+/******************************************************/ -+/* Function : _asn1_ordering_set_of */ -+/* Description: puts the elements of a SET OF type in */ -+/* the correct order according to DER rules. */ -+/* Parameters: */ -+/* der: string with the DER coding. */ -+/* node: pointer to the SET OF element. */ -+/* Return: */ -+/* ASN1_SUCCESS if successful */ -+/* or an error value. */ -+/******************************************************/ -+static int -+_asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) -+{ -+ int counter, len, len2; -+ struct vet *list = NULL, *tlist; -+ unsigned list_size = 0; -+ struct vet *p_vet; -+ asn1_node p; -+ unsigned char class; -+ unsigned i; -+ unsigned char *out = NULL; -+ int err; -+ -+ if (der == NULL) -+ return ASN1_VALUE_NOT_VALID; -+ -+ counter = 0; -+ -+ if (type_field (node->type) != ASN1_ETYPE_SET_OF) -+ return ASN1_VALUE_NOT_VALID; -+ -+ p = node->down; -+ while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || -+ (type_field (p->type) == ASN1_ETYPE_SIZE))) -+ p = p->right; -+ if (p == NULL) -+ return ASN1_VALUE_NOT_VALID; -+ p = p->right; -+ -+ if ((p == NULL) || (p->right == NULL)) -+ return ASN1_SUCCESS; -+ -+ while (p) -+ { -+ list_size++; -+ tlist = realloc (list, list_size*sizeof(struct vet)); -+ if (tlist == NULL) -+ { -+ err = ASN1_MEM_ALLOC_ERROR; -+ goto error; -+ } -+ list = tlist; -+ p_vet = &list[list_size-1]; -+ -+ p_vet->ptr = der+counter; -+ p_vet->size = 0; -+ -+ /* extraction of tag and length */ -+ if (der_len - counter > 0) -+ { -+ err = asn1_get_tag_der (der + counter, der_len - counter, &class, -+ &len, NULL); -+ if (err != ASN1_SUCCESS) -+ goto error; -+ counter += len; -+ p_vet->size += len; -+ -+ len2 = asn1_get_length_der (der + counter, der_len - counter, &len); -+ if (len2 < 0) -+ { -+ err = ASN1_DER_ERROR; -+ goto error; -+ } -+ counter += len + len2; -+ p_vet->size += len + len2; -+ -+ } -+ else -+ { -+ err = ASN1_DER_ERROR; -+ goto error; -+ } -+ p = p->right; -+ } -+ -+ if (counter > der_len) -+ { -+ err = ASN1_DER_ERROR; -+ goto error; -+ } -+ -+ qsort(list, list_size, sizeof(struct vet), setof_compar); -+ -+ out = malloc(der_len); -+ if (out == NULL) -+ { -+ err = ASN1_MEM_ERROR; -+ goto error; -+ } -+ -+ /* the sum of p_vet->size == der_len */ -+ counter = 0; -+ for (i = 0; i < list_size; i++) -+ { -+ p_vet = &list[i]; -+ memcpy(out+counter, p_vet->ptr, p_vet->size); -+ counter += p_vet->size; -+ } -+ memcpy(der, out, der_len); -+ free(out); -+ -+ err = ASN1_SUCCESS; -+ -+error: -+ free(list); -+ return err; -+} -+ -+/** -+ * asn1_der_coding: -+ * @element: pointer to an ASN1 element -+ * @name: the name of the structure you want to encode (it must be -+ * inside *POINTER). -+ * @ider: vector that will contain the DER encoding. DER must be a -+ * pointer to memory cells already allocated. -+ * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy -+ * holds the sizeof of der vector. -+ * @ErrorDescription: return the error description or an empty -+ * string if success. -+ * -+ * Creates the DER encoding for the NAME structure (inside *POINTER -+ * structure). -+ * -+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND -+ * if @name is not a valid element, %ASN1_VALUE_NOT_FOUND if there -+ * is an element without a value, %ASN1_MEM_ERROR if the @ider -+ * vector isn't big enough and in this case @len will contain the -+ * length needed. -+ **/ -+int -+asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len, -+ char *ErrorDescription) -+{ -+ asn1_node node, p, p2; -+ unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)]; -+ int counter, counter_old, len2, len3, move, max_len, max_len_old; -+ int err; -+ unsigned char *der = ider; -+ -+ if (ErrorDescription) -+ ErrorDescription[0] = 0; -+ -+ node = asn1_find_node (element, name); -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ /* Node is now a locally allocated variable. -+ * That is because in some point we modify the -+ * structure, and I don't know why! --nmav -+ */ -+ node = _asn1_copy_structure3 (node); -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ max_len = *len; -+ -+ if (der == NULL && max_len > 0) -+ return ASN1_VALUE_NOT_VALID; -+ -+ counter = 0; -+ move = DOWN; -+ p = node; -+ -+ while (1) -+ { -+ -+ counter_old = counter; -+ max_len_old = max_len; -+ if (move != UP) -+ { -+ p->start = counter; -+ err = _asn1_insert_tag_der (p, der, &counter, &max_len); -+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) -+ goto error; -+ } -+ switch (type_field (p->type)) -+ { -+ case ASN1_ETYPE_NULL: -+ max_len--; -+ if (der != NULL && max_len >= 0) -+ der[counter] = 0; -+ counter++; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_BOOLEAN: -+ if ((p->type & CONST_DEFAULT) && (p->value == NULL)) -+ { -+ counter = counter_old; -+ max_len = max_len_old; -+ } -+ else -+ { -+ if (p->value == NULL) -+ { -+ _asn1_error_description_value_not_found (p, -+ ErrorDescription); -+ err = ASN1_VALUE_NOT_FOUND; -+ goto error; -+ } -+ max_len -= 2; -+ if (der != NULL && max_len >= 0) -+ { -+ der[counter++] = 1; -+ if (p->value[0] == 'F') -+ der[counter++] = 0; -+ else -+ der[counter++] = 0xFF; -+ } -+ else -+ counter += 2; -+ } -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_INTEGER: -+ case ASN1_ETYPE_ENUMERATED: -+ if ((p->type & CONST_DEFAULT) && (p->value == NULL)) -+ { -+ counter = counter_old; -+ max_len = max_len_old; -+ } -+ else -+ { -+ if (p->value == NULL) -+ { -+ _asn1_error_description_value_not_found (p, -+ ErrorDescription); -+ err = ASN1_VALUE_NOT_FOUND; -+ goto error; -+ } -+ len2 = asn1_get_length_der (p->value, p->value_len, &len3); -+ if (len2 < 0) -+ { -+ err = ASN1_DER_ERROR; -+ goto error; -+ } -+ max_len -= len2 + len3; -+ if (der != NULL && max_len >= 0) -+ memcpy (der + counter, p->value, len3 + len2); -+ counter += len3 + len2; -+ } -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_OBJECT_ID: -+ if ((p->type & CONST_DEFAULT) && (p->value == NULL)) -+ { -+ counter = counter_old; -+ max_len = max_len_old; -+ } -+ else -+ { -+ if (p->value == NULL) -+ { -+ _asn1_error_description_value_not_found (p, -+ ErrorDescription); -+ err = ASN1_VALUE_NOT_FOUND; -+ goto error; -+ } -+ len2 = max_len; -+ err = _asn1_object_id_der ((char*)p->value, der + counter, &len2); -+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) -+ goto error; -+ -+ max_len -= len2; -+ counter += len2; -+ } -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_GENERALIZED_TIME: -+ case ASN1_ETYPE_UTC_TIME: -+ if (p->value == NULL) -+ { -+ _asn1_error_description_value_not_found (p, ErrorDescription); -+ err = ASN1_VALUE_NOT_FOUND; -+ goto error; -+ } -+ len2 = max_len; -+ err = _asn1_time_der (p->value, p->value_len, der + counter, &len2); -+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) -+ goto error; -+ -+ max_len -= len2; -+ counter += len2; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_OCTET_STRING: -+ case ASN1_ETYPE_GENERALSTRING: -+ case ASN1_ETYPE_NUMERIC_STRING: -+ case ASN1_ETYPE_IA5_STRING: -+ case ASN1_ETYPE_TELETEX_STRING: -+ case ASN1_ETYPE_PRINTABLE_STRING: -+ case ASN1_ETYPE_UNIVERSAL_STRING: -+ case ASN1_ETYPE_BMP_STRING: -+ case ASN1_ETYPE_UTF8_STRING: -+ case ASN1_ETYPE_VISIBLE_STRING: -+ case ASN1_ETYPE_BIT_STRING: -+ if (p->value == NULL) -+ { -+ _asn1_error_description_value_not_found (p, ErrorDescription); -+ err = ASN1_VALUE_NOT_FOUND; -+ goto error; -+ } -+ len2 = asn1_get_length_der (p->value, p->value_len, &len3); -+ if (len2 < 0) -+ { -+ err = ASN1_DER_ERROR; -+ goto error; -+ } -+ max_len -= len2 + len3; -+ if (der != NULL && max_len >= 0) -+ memcpy (der + counter, p->value, len3 + len2); -+ counter += len3 + len2; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_SEQUENCE: -+ case ASN1_ETYPE_SET: -+ if (move != UP) -+ { -+ p->tmp_ival = counter; -+ if (p->down == NULL) -+ { -+ move = UP; -+ continue; -+ } -+ else -+ { -+ p2 = p->down; -+ while (p2 && (type_field (p2->type) == ASN1_ETYPE_TAG)) -+ p2 = p2->right; -+ if (p2) -+ { -+ p = p2; -+ move = RIGHT; -+ continue; -+ } -+ move = UP; -+ continue; -+ } -+ } -+ else -+ { /* move==UP */ -+ len2 = p->tmp_ival; -+ p->tmp_ival = 0; -+ if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0)) -+ { -+ err = _asn1_ordering_set (der + len2, counter - len2, p); -+ if (err != ASN1_SUCCESS) -+ goto error; -+ } -+ asn1_length_der (counter - len2, temp, &len3); -+ max_len -= len3; -+ if (der != NULL && max_len >= 0) -+ { -+ memmove (der + len2 + len3, der + len2, counter - len2); -+ memcpy (der + len2, temp, len3); -+ } -+ counter += len3; -+ move = RIGHT; -+ } -+ break; -+ case ASN1_ETYPE_SEQUENCE_OF: -+ case ASN1_ETYPE_SET_OF: -+ if (move != UP) -+ { -+ p->tmp_ival = counter; -+ p = p->down; -+ while ((type_field (p->type) == ASN1_ETYPE_TAG) -+ || (type_field (p->type) == ASN1_ETYPE_SIZE)) -+ p = p->right; -+ if (p->right) -+ { -+ p = p->right; -+ move = RIGHT; -+ continue; -+ } -+ else -+ p = _asn1_find_up (p); -+ move = UP; -+ } -+ if (move == UP) -+ { -+ len2 = p->tmp_ival; -+ p->tmp_ival = 0; -+ if ((type_field (p->type) == ASN1_ETYPE_SET_OF) -+ && (counter - len2 > 0) && (max_len >= 0)) -+ { -+ err = _asn1_ordering_set_of (der + len2, counter - len2, p); -+ if (err != ASN1_SUCCESS) -+ goto error; -+ } -+ asn1_length_der (counter - len2, temp, &len3); -+ max_len -= len3; -+ if (der != NULL && max_len >= 0) -+ { -+ memmove (der + len2 + len3, der + len2, counter - len2); -+ memcpy (der + len2, temp, len3); -+ } -+ counter += len3; -+ move = RIGHT; -+ } -+ break; -+ case ASN1_ETYPE_ANY: -+ if (p->value == NULL) -+ { -+ _asn1_error_description_value_not_found (p, ErrorDescription); -+ err = ASN1_VALUE_NOT_FOUND; -+ goto error; -+ } -+ len2 = asn1_get_length_der (p->value, p->value_len, &len3); -+ if (len2 < 0) -+ { -+ err = ASN1_DER_ERROR; -+ goto error; -+ } -+ max_len -= len2; -+ if (der != NULL && max_len >= 0) -+ memcpy (der + counter, p->value + len3, len2); -+ counter += len2; -+ move = RIGHT; -+ break; -+ default: -+ move = (move == UP) ? RIGHT : DOWN; -+ break; -+ } -+ -+ if ((move != DOWN) && (counter != counter_old)) -+ { -+ p->end = counter - 1; -+ err = _asn1_complete_explicit_tag (p, der, &counter, &max_len); -+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) -+ goto error; -+ } -+ -+ if (p == node && move != DOWN) -+ break; -+ -+ if (move == DOWN) -+ { -+ if (p->down) -+ p = p->down; -+ else -+ move = RIGHT; -+ } -+ if (move == RIGHT) -+ { -+ if (p->right) -+ p = p->right; -+ else -+ move = UP; -+ } -+ if (move == UP) -+ p = _asn1_find_up (p); -+ } -+ -+ *len = counter; -+ -+ if (max_len < 0) -+ { -+ err = ASN1_MEM_ERROR; -+ goto error; -+ } -+ -+ err = ASN1_SUCCESS; -+ -+error: -+ asn1_delete_structure (&node); -+ return err; -+} -diff --git a/grub-core/lib/libtasn1/lib/decoding.c b/grub-core/lib/libtasn1/lib/decoding.c -new file mode 100644 -index 00000000000..ff04eb778cb ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/decoding.c -@@ -0,0 +1,2478 @@ -+/* -+ * Copyright (C) 2002-2016 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+ -+/*****************************************************/ -+/* File: decoding.c */ -+/* Description: Functions to manage DER decoding */ -+/*****************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef DEBUG -+# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) -+#else -+# define warn() -+#endif -+ -+#define IS_ERR(len, flags) (len < -1 || ((flags & ASN1_DECODE_FLAG_STRICT_DER) && len < 0)) -+ -+#define HAVE_TWO(x) (x>=2?1:0) -+ -+/* Decoding flags (dflags) used in several decoding functions. -+ * DECODE_FLAG_HAVE_TAG: The provided buffer includes a tag -+ * DECODE_FLAG_CONSTRUCTED: The provided buffer is of indefinite encoding (useful -+ * when no tags are present). -+ * DECODE_FLAG_LEVEL1: Internal flag to indicate a level of recursion for BER strings. -+ * DECODE_FLAG_LEVEL2: Internal flag to indicate two levels of recursion for BER strings. -+ * DECODE_FLAG_LEVEL3: Internal flag to indicate three levels of recursion for BER strings. -+ * This is the maximum levels of recursion possible to prevent stack -+ * exhaustion. -+ */ -+ -+#define DECODE_FLAG_HAVE_TAG 1 -+#define DECODE_FLAG_CONSTRUCTED (1<<1) -+#define DECODE_FLAG_LEVEL1 (1<<2) -+#define DECODE_FLAG_LEVEL2 (1<<3) -+#define DECODE_FLAG_LEVEL3 (1<<4) -+ -+#define DECR_LEN(l, s) do { \ -+ l -= s; \ -+ if (l < 0) { \ -+ warn(); \ -+ result = ASN1_DER_ERROR; \ -+ goto cleanup; \ -+ } \ -+ } while (0) -+ -+static int -+_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len); -+ -+static int -+_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, unsigned char **str, -+ unsigned int *str_len, unsigned int *ber_len, -+ unsigned dflags); -+ -+static int -+_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, const unsigned char **str, -+ unsigned int *str_len, unsigned dflags); -+ -+static void -+_asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) -+{ -+ -+ Estrcpy (ErrorDescription, ":: tag error near element '"); -+ _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), -+ ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); -+ Estrcat (ErrorDescription, "'"); -+ -+} -+ -+/** -+ * asn1_get_length_der: -+ * @der: DER data to decode. -+ * @der_len: Length of DER data to decode. -+ * @len: Output variable containing the length of the DER length field. -+ * -+ * Extract a length field from DER data. -+ * -+ * Returns: Return the decoded length value, or -1 on indefinite -+ * length, or -2 when the value was too big to fit in a int, or -4 -+ * when the decoded length value plus @len would exceed @der_len. -+ **/ -+long -+asn1_get_length_der (const unsigned char *der, int der_len, int *len) -+{ -+ unsigned int ans; -+ int k, punt, sum; -+ -+ *len = 0; -+ if (der_len <= 0) -+ return 0; -+ -+ if (!(der[0] & 128)) -+ { -+ /* short form */ -+ *len = 1; -+ ans = der[0]; -+ } -+ else -+ { -+ /* Long form */ -+ k = der[0] & 0x7F; -+ punt = 1; -+ if (k) -+ { /* definite length method */ -+ ans = 0; -+ while (punt <= k && punt < der_len) -+ { -+ if (INT_MULTIPLY_OVERFLOW (ans, 256)) -+ return -2; -+ ans *= 256; -+ -+ if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt]))) -+ return -2; -+ ans += der[punt]; -+ punt++; -+ } -+ } -+ else -+ { /* indefinite length method */ -+ *len = punt; -+ return -1; -+ } -+ -+ *len = punt; -+ } -+ -+ sum = ans; -+ if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len))) -+ return -2; -+ sum += *len; -+ -+ if (sum > der_len) -+ return -4; -+ -+ return ans; -+} -+ -+/** -+ * asn1_get_tag_der: -+ * @der: DER data to decode. -+ * @der_len: Length of DER data to decode. -+ * @cls: Output variable containing decoded class. -+ * @len: Output variable containing the length of the DER TAG data. -+ * @tag: Output variable containing the decoded tag (may be %NULL). -+ * -+ * Decode the class and TAG from DER code. -+ * -+ * Returns: Returns %ASN1_SUCCESS on success, or an error. -+ **/ -+int -+asn1_get_tag_der (const unsigned char *der, int der_len, -+ unsigned char *cls, int *len, unsigned long *tag) -+{ -+ unsigned int ris; -+ int punt; -+ -+ if (der == NULL || der_len < 2 || len == NULL) -+ return ASN1_DER_ERROR; -+ -+ *cls = der[0] & 0xE0; -+ if ((der[0] & 0x1F) != 0x1F) -+ { -+ /* short form */ -+ *len = 1; -+ ris = der[0] & 0x1F; -+ } -+ else -+ { -+ /* Long form */ -+ punt = 1; -+ ris = 0; -+ while (punt < der_len && der[punt] & 128) -+ { -+ -+ if (INT_MULTIPLY_OVERFLOW (ris, 128)) -+ return ASN1_DER_ERROR; -+ ris *= 128; -+ -+ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) -+ return ASN1_DER_ERROR; -+ ris += (der[punt] & 0x7F); -+ punt++; -+ } -+ -+ if (punt >= der_len) -+ return ASN1_DER_ERROR; -+ -+ if (INT_MULTIPLY_OVERFLOW (ris, 128)) -+ return ASN1_DER_ERROR; -+ ris *= 128; -+ -+ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) -+ return ASN1_DER_ERROR; -+ ris += (der[punt] & 0x7F); -+ punt++; -+ -+ *len = punt; -+ } -+ -+ if (tag) -+ *tag = ris; -+ return ASN1_SUCCESS; -+} -+ -+/** -+ * asn1_get_length_ber: -+ * @ber: BER data to decode. -+ * @ber_len: Length of BER data to decode. -+ * @len: Output variable containing the length of the BER length field. -+ * -+ * Extract a length field from BER data. The difference to -+ * asn1_get_length_der() is that this function will return a length -+ * even if the value has indefinite encoding. -+ * -+ * Returns: Return the decoded length value, or negative value when -+ * the value was too big. -+ * -+ * Since: 2.0 -+ **/ -+long -+asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) -+{ -+ int ret; -+ long err; -+ -+ ret = asn1_get_length_der (ber, ber_len, len); -+ -+ if (ret == -1 && ber_len > 1) -+ { /* indefinite length method */ -+ err = _asn1_get_indefinite_length_string (ber + 1, ber_len-1, &ret); -+ if (err != ASN1_SUCCESS) -+ return -3; -+ } -+ -+ return ret; -+} -+ -+/** -+ * asn1_get_octet_der: -+ * @der: DER data to decode containing the OCTET SEQUENCE. -+ * @der_len: The length of the @der data to decode. -+ * @ret_len: Output variable containing the encoded length of the DER data. -+ * @str: Pre-allocated output buffer to put decoded OCTET SEQUENCE in. -+ * @str_size: Length of pre-allocated output buffer. -+ * @str_len: Output variable containing the length of the contents of the OCTET SEQUENCE. -+ * -+ * Extract an OCTET SEQUENCE from DER data. Note that this function -+ * expects the DER data past the tag field, i.e., the length and -+ * content octets. -+ * -+ * Returns: Returns %ASN1_SUCCESS on success, or an error. -+ **/ -+int -+asn1_get_octet_der (const unsigned char *der, int der_len, -+ int *ret_len, unsigned char *str, int str_size, -+ int *str_len) -+{ -+ int len_len = 0; -+ -+ if (der_len <= 0) -+ return ASN1_GENERIC_ERROR; -+ -+ *str_len = asn1_get_length_der (der, der_len, &len_len); -+ -+ if (*str_len < 0) -+ return ASN1_DER_ERROR; -+ -+ *ret_len = *str_len + len_len; -+ if (str_size >= *str_len) -+ { -+ if (*str_len > 0 && str != NULL) -+ memcpy (str, der + len_len, *str_len); -+ } -+ else -+ { -+ return ASN1_MEM_ERROR; -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/*- -+ * _asn1_get_time_der: -+ * @type: %ASN1_ETYPE_GENERALIZED_TIME or %ASN1_ETYPE_UTC_TIME -+ * @der: DER data to decode containing the time -+ * @der_len: Length of DER data to decode. -+ * @ret_len: Output variable containing the length of the DER data. -+ * @str: Pre-allocated output buffer to put the textual time in. -+ * @str_size: Length of pre-allocated output buffer. -+ * @flags: Zero or %ASN1_DECODE_FLAG_STRICT_DER -+ * -+ * Performs basic checks in the DER encoded time object and returns its textual form. -+ * The textual form will be in the YYYYMMDD000000Z format for GeneralizedTime -+ * and YYMMDD000000Z for UTCTime. -+ * -+ * Returns: %ASN1_SUCCESS on success, or an error. -+ -*/ -+static int -+_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *ret_len, -+ char *str, int str_size, unsigned flags) -+{ -+ int len_len, str_len; -+ unsigned i; -+ unsigned sign_count = 0; -+ unsigned dot_count = 0; -+ const unsigned char *p; -+ -+ if (der_len <= 0 || str == NULL) -+ return ASN1_DER_ERROR; -+ -+ str_len = asn1_get_length_der (der, der_len, &len_len); -+ if (str_len <= 0 || str_size < str_len) -+ return ASN1_DER_ERROR; -+ -+ /* perform some sanity checks on the data */ -+ if (str_len < 8) -+ { -+ warn(); -+ return ASN1_TIME_ENCODING_ERROR; -+ } -+ -+ if ((flags & ASN1_DECODE_FLAG_STRICT_DER) && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME)) -+ { -+ p = &der[len_len]; -+ for (i=0;i<(unsigned)(str_len-1);i++) -+ { -+ if (c_isdigit(p[i]) == 0) -+ { -+ if (type == ASN1_ETYPE_GENERALIZED_TIME) -+ { -+ /* tolerate lax encodings */ -+ if (p[i] == '.' && dot_count == 0) -+ { -+ dot_count++; -+ continue; -+ } -+ -+ /* This is not really valid DER, but there are -+ * structures using that */ -+ if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && -+ (p[i] == '+' || p[i] == '-') && sign_count == 0) -+ { -+ sign_count++; -+ continue; -+ } -+ } -+ -+ warn(); -+ return ASN1_TIME_ENCODING_ERROR; -+ } -+ } -+ -+ if (sign_count == 0 && p[str_len-1] != 'Z') -+ { -+ warn(); -+ return ASN1_TIME_ENCODING_ERROR; -+ } -+ } -+ memcpy (str, der + len_len, str_len); -+ str[str_len] = 0; -+ *ret_len = str_len + len_len; -+ -+ return ASN1_SUCCESS; -+} -+ -+/** -+ * asn1_get_object_id_der: -+ * @der: DER data to decode containing the OBJECT IDENTIFIER -+ * @der_len: Length of DER data to decode. -+ * @ret_len: Output variable containing the length of the DER data. -+ * @str: Pre-allocated output buffer to put the textual object id in. -+ * @str_size: Length of pre-allocated output buffer. -+ * -+ * Converts a DER encoded object identifier to its textual form. This -+ * function expects the DER object identifier without the tag. -+ * -+ * Returns: %ASN1_SUCCESS on success, or an error. -+ **/ -+int -+asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len, -+ char *str, int str_size) -+{ -+ int len_len, len, k; -+ int leading, parsed; -+ char temp[LTOSTR_MAX_SIZE]; -+ uint64_t val, val1, val0; -+ -+ *ret_len = 0; -+ if (str && str_size > 0) -+ str[0] = 0; /* no oid */ -+ -+ if (str == NULL || der_len <= 0) -+ return ASN1_GENERIC_ERROR; -+ -+ len = asn1_get_length_der (der, der_len, &len_len); -+ -+ if (len <= 0 || len + len_len > der_len) -+ return ASN1_DER_ERROR; -+ -+ /* leading octet can never be 0x80 */ -+ if (der[len_len] == 0x80) -+ return ASN1_DER_ERROR; -+ -+ val0 = 0; -+ -+ for (k = 0; k < len; k++) -+ { -+ if (INT_LEFT_SHIFT_OVERFLOW (val0, 7)) -+ return ASN1_DER_ERROR; -+ -+ val0 <<= 7; -+ val0 |= der[len_len + k] & 0x7F; -+ if (!(der[len_len + k] & 0x80)) -+ break; -+ } -+ parsed = ++k; -+ -+ /* val0 = (X*40) + Y, X={0,1,2}, Y<=39 when X={0,1} */ -+ /* X = val, Y = val1 */ -+ -+ /* check if X == 0 */ -+ val = 0; -+ val1 = val0; -+ if (val1 > 39) -+ { -+ val = 1; -+ val1 = val0 - 40; -+ if (val1 > 39) -+ { -+ val = 2; -+ val1 = val0 - 80; -+ } -+ } -+ -+ _asn1_str_cpy (str, str_size, _asn1_ltostr (val, temp)); -+ _asn1_str_cat (str, str_size, "."); -+ _asn1_str_cat (str, str_size, _asn1_ltostr (val1, temp)); -+ -+ val = 0; -+ leading = 1; -+ for (k = parsed; k < len; k++) -+ { -+ /* X.690 mandates that the leading byte must never be 0x80 -+ */ -+ if (leading != 0 && der[len_len + k] == 0x80) -+ return ASN1_DER_ERROR; -+ leading = 0; -+ -+ /* check for wrap around */ -+ if (INT_LEFT_SHIFT_OVERFLOW (val, 7)) -+ return ASN1_DER_ERROR; -+ -+ val = val << 7; -+ val |= der[len_len + k] & 0x7F; -+ -+ if (!(der[len_len + k] & 0x80)) -+ { -+ _asn1_str_cat (str, str_size, "."); -+ _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp)); -+ val = 0; -+ leading = 1; -+ } -+ } -+ -+ if (INT_ADD_OVERFLOW (len, len_len)) -+ return ASN1_DER_ERROR; -+ -+ *ret_len = len + len_len; -+ -+ return ASN1_SUCCESS; -+} -+ -+/** -+ * asn1_get_bit_der: -+ * @der: DER data to decode containing the BIT SEQUENCE. -+ * @der_len: Length of DER data to decode. -+ * @ret_len: Output variable containing the length of the DER data. -+ * @str: Pre-allocated output buffer to put decoded BIT SEQUENCE in. -+ * @str_size: Length of pre-allocated output buffer. -+ * @bit_len: Output variable containing the size of the BIT SEQUENCE. -+ * -+ * Extract a BIT SEQUENCE from DER data. -+ * -+ * Returns: %ASN1_SUCCESS on success, or an error. -+ **/ -+int -+asn1_get_bit_der (const unsigned char *der, int der_len, -+ int *ret_len, unsigned char *str, int str_size, -+ int *bit_len) -+{ -+ int len_len = 0, len_byte; -+ -+ if (der_len <= 0) -+ return ASN1_GENERIC_ERROR; -+ -+ len_byte = asn1_get_length_der (der, der_len, &len_len) - 1; -+ if (len_byte < 0) -+ return ASN1_DER_ERROR; -+ -+ *ret_len = len_byte + len_len + 1; -+ *bit_len = len_byte * 8 - der[len_len]; -+ -+ if (*bit_len < 0) -+ return ASN1_DER_ERROR; -+ -+ if (str_size >= len_byte) -+ { -+ if (len_byte > 0 && str) -+ memcpy (str, der + len_len + 1, len_byte); -+ } -+ else -+ { -+ return ASN1_MEM_ERROR; -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+/* tag_len: the total tag length (explicit+inner) -+ * inner_tag_len: the inner_tag length -+ */ -+static int -+_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, -+ int *tag_len, int *inner_tag_len, unsigned flags) -+{ -+ asn1_node p; -+ int counter, len2, len3, is_tag_implicit; -+ int result; -+ unsigned long tag, tag_implicit = 0; -+ unsigned char class, class2, class_implicit = 0; -+ -+ if (der_len <= 0) -+ return ASN1_GENERIC_ERROR; -+ -+ counter = is_tag_implicit = 0; -+ -+ if (node->type & CONST_TAG) -+ { -+ p = node->down; -+ while (p) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_TAG) -+ { -+ if (p->type & CONST_APPLICATION) -+ class2 = ASN1_CLASS_APPLICATION; -+ else if (p->type & CONST_UNIVERSAL) -+ class2 = ASN1_CLASS_UNIVERSAL; -+ else if (p->type & CONST_PRIVATE) -+ class2 = ASN1_CLASS_PRIVATE; -+ else -+ class2 = ASN1_CLASS_CONTEXT_SPECIFIC; -+ -+ if (p->type & CONST_EXPLICIT) -+ { -+ if (asn1_get_tag_der -+ (der + counter, der_len, &class, &len2, -+ &tag) != ASN1_SUCCESS) -+ return ASN1_DER_ERROR; -+ -+ DECR_LEN(der_len, len2); -+ counter += len2; -+ -+ if (flags & ASN1_DECODE_FLAG_STRICT_DER) -+ len3 = -+ asn1_get_length_der (der + counter, der_len, -+ &len2); -+ else -+ len3 = -+ asn1_get_length_ber (der + counter, der_len, -+ &len2); -+ if (len3 < 0) -+ return ASN1_DER_ERROR; -+ -+ DECR_LEN(der_len, len2); -+ counter += len2; -+ -+ if (!is_tag_implicit) -+ { -+ if ((class != (class2 | ASN1_CLASS_STRUCTURED)) || -+ (tag != strtoul ((char *) p->value, NULL, 10))) -+ return ASN1_TAG_ERROR; -+ } -+ else -+ { /* ASN1_TAG_IMPLICIT */ -+ if ((class != class_implicit) || (tag != tag_implicit)) -+ return ASN1_TAG_ERROR; -+ } -+ is_tag_implicit = 0; -+ } -+ else -+ { /* ASN1_TAG_IMPLICIT */ -+ if (!is_tag_implicit) -+ { -+ if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || -+ (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) -+ || (type_field (node->type) == ASN1_ETYPE_SET) -+ || (type_field (node->type) == ASN1_ETYPE_SET_OF)) -+ class2 |= ASN1_CLASS_STRUCTURED; -+ class_implicit = class2; -+ tag_implicit = strtoul ((char *) p->value, NULL, 10); -+ is_tag_implicit = 1; -+ } -+ } -+ } -+ p = p->right; -+ } -+ } -+ -+ if (is_tag_implicit) -+ { -+ if (asn1_get_tag_der -+ (der + counter, der_len, &class, &len2, -+ &tag) != ASN1_SUCCESS) -+ return ASN1_DER_ERROR; -+ -+ DECR_LEN(der_len, len2); -+ -+ if ((class != class_implicit) || (tag != tag_implicit)) -+ { -+ if (type_field (node->type) == ASN1_ETYPE_OCTET_STRING) -+ { -+ class_implicit |= ASN1_CLASS_STRUCTURED; -+ if ((class != class_implicit) || (tag != tag_implicit)) -+ return ASN1_TAG_ERROR; -+ } -+ else -+ return ASN1_TAG_ERROR; -+ } -+ } -+ else -+ { -+ unsigned type = type_field (node->type); -+ if (type == ASN1_ETYPE_TAG) -+ { -+ *tag_len = 0; -+ if (inner_tag_len) -+ *inner_tag_len = 0; -+ return ASN1_SUCCESS; -+ } -+ -+ if (asn1_get_tag_der -+ (der + counter, der_len, &class, &len2, -+ &tag) != ASN1_SUCCESS) -+ return ASN1_DER_ERROR; -+ -+ DECR_LEN(der_len, len2); -+ -+ switch (type) -+ { -+ case ASN1_ETYPE_NULL: -+ case ASN1_ETYPE_BOOLEAN: -+ case ASN1_ETYPE_INTEGER: -+ case ASN1_ETYPE_ENUMERATED: -+ case ASN1_ETYPE_OBJECT_ID: -+ case ASN1_ETYPE_GENERALSTRING: -+ case ASN1_ETYPE_NUMERIC_STRING: -+ case ASN1_ETYPE_IA5_STRING: -+ case ASN1_ETYPE_TELETEX_STRING: -+ case ASN1_ETYPE_PRINTABLE_STRING: -+ case ASN1_ETYPE_UNIVERSAL_STRING: -+ case ASN1_ETYPE_BMP_STRING: -+ case ASN1_ETYPE_UTF8_STRING: -+ case ASN1_ETYPE_VISIBLE_STRING: -+ case ASN1_ETYPE_BIT_STRING: -+ case ASN1_ETYPE_SEQUENCE: -+ case ASN1_ETYPE_SEQUENCE_OF: -+ case ASN1_ETYPE_SET: -+ case ASN1_ETYPE_SET_OF: -+ case ASN1_ETYPE_GENERALIZED_TIME: -+ case ASN1_ETYPE_UTC_TIME: -+ if ((class != _asn1_tags[type].class) -+ || (tag != _asn1_tags[type].tag)) -+ return ASN1_DER_ERROR; -+ break; -+ -+ case ASN1_ETYPE_OCTET_STRING: -+ /* OCTET STRING is handled differently to allow -+ * BER encodings (structured class). */ -+ if (((class != ASN1_CLASS_UNIVERSAL) -+ && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))) -+ || (tag != ASN1_TAG_OCTET_STRING)) -+ return ASN1_DER_ERROR; -+ break; -+ case ASN1_ETYPE_ANY: -+ counter -= len2; -+ break; -+ case ASN1_ETYPE_CHOICE: -+ counter -= len2; -+ break; -+ default: -+ return ASN1_DER_ERROR; -+ break; -+ } -+ } -+ -+ counter += len2; -+ *tag_len = counter; -+ if (inner_tag_len) -+ *inner_tag_len = len2; -+ return ASN1_SUCCESS; -+ -+cleanup: -+ return result; -+} -+ -+static int -+extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len, -+ int *ret_len, int *inner_len, unsigned flags) -+{ -+asn1_node p; -+int ris = ASN1_DER_ERROR; -+ -+ if (type_field (node->type) == ASN1_ETYPE_CHOICE) -+ { -+ p = node->down; -+ while (p) -+ { -+ ris = _asn1_extract_tag_der (p, der, der_len, ret_len, inner_len, flags); -+ if (ris == ASN1_SUCCESS) -+ break; -+ p = p->right; -+ } -+ -+ *ret_len = 0; -+ return ris; -+ } -+ else -+ return _asn1_extract_tag_der (node, der, der_len, ret_len, inner_len, flags); -+} -+ -+static int -+_asn1_delete_not_used (asn1_node node) -+{ -+ asn1_node p, p2; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node; -+ while (p) -+ { -+ if (p->type & CONST_NOT_USED) -+ { -+ p2 = NULL; -+ if (p != node) -+ { -+ p2 = _asn1_find_left (p); -+ if (!p2) -+ p2 = _asn1_find_up (p); -+ } -+ asn1_delete_structure (&p); -+ p = p2; -+ } -+ -+ if (!p) -+ break; /* reach node */ -+ -+ if (p->down) -+ { -+ p = p->down; -+ } -+ else -+ { -+ if (p == node) -+ p = NULL; -+ else if (p->right) -+ p = p->right; -+ else -+ { -+ while (1) -+ { -+ p = _asn1_find_up (p); -+ if (p == node) -+ { -+ p = NULL; -+ break; -+ } -+ if (p->right) -+ { -+ p = p->right; -+ break; -+ } -+ } -+ } -+ } -+ } -+ return ASN1_SUCCESS; -+} -+ -+static int -+_asn1_get_indefinite_length_string (const unsigned char *der, -+ int der_len, int *len) -+{ -+ int len2, len3, counter, indefinite; -+ int result; -+ unsigned long tag; -+ unsigned char class; -+ -+ counter = indefinite = 0; -+ -+ while (1) -+ { -+ if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0)) -+ { -+ counter += 2; -+ DECR_LEN(der_len, 2); -+ -+ indefinite--; -+ if (indefinite <= 0) -+ break; -+ else -+ continue; -+ } -+ -+ if (asn1_get_tag_der -+ (der + counter, der_len, &class, &len2, -+ &tag) != ASN1_SUCCESS) -+ return ASN1_DER_ERROR; -+ -+ DECR_LEN(der_len, len2); -+ counter += len2; -+ -+ len2 = asn1_get_length_der (der + counter, der_len, &len3); -+ if (len2 < -1) -+ return ASN1_DER_ERROR; -+ -+ if (len2 == -1) -+ { -+ indefinite++; -+ counter += 1; -+ DECR_LEN(der_len, 1); -+ } -+ else -+ { -+ counter += len2 + len3; -+ DECR_LEN(der_len, len2+len3); -+ } -+ } -+ -+ *len = counter; -+ return ASN1_SUCCESS; -+ -+cleanup: -+ return result; -+} -+ -+static void delete_unneeded_choice_fields(asn1_node p) -+{ -+ asn1_node p2; -+ -+ while (p->right) -+ { -+ p2 = p->right; -+ asn1_delete_structure (&p2); -+ } -+} -+ -+ -+/** -+ * asn1_der_decoding2 -+ * @element: pointer to an ASN1 structure. -+ * @ider: vector that contains the DER encoding. -+ * @max_ider_len: pointer to an integer giving the information about the -+ * maximal number of bytes occupied by *@ider. The real size of the DER -+ * encoding is returned through this pointer. -+ * @flags: flags controlling the behaviour of the function. -+ * @errorDescription: null-terminated string contains details when an -+ * error occurred. -+ * -+ * Fill the structure *@element with values of a DER encoding string. The -+ * structure must just be created with function asn1_create_element(). -+ * -+ * If %ASN1_DECODE_FLAG_ALLOW_PADDING flag is set then the function will ignore -+ * padding after the decoded DER data. Upon a successful return the value of -+ * *@max_ider_len will be set to the number of bytes decoded. -+ * -+ * If %ASN1_DECODE_FLAG_STRICT_DER flag is set then the function will -+ * not decode any BER-encoded elements. -+ * -+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND -+ * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or -+ * %ASN1_DER_ERROR if the der encoding doesn't match the structure -+ * name (*@ELEMENT deleted). -+ **/ -+int -+asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, -+ unsigned int flags, char *errorDescription) -+{ -+ asn1_node node, p, p2, p3; -+ char temp[128]; -+ int counter, len2, len3, len4, move, ris, tlen; -+ struct node_tail_cache_st tcache = {NULL, NULL}; -+ unsigned char class; -+ unsigned long tag; -+ int tag_len; -+ int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len; -+ int inner_tag_len; -+ unsigned char *ptmp; -+ const unsigned char *ptag; -+ const unsigned char *der = ider; -+ -+ node = *element; -+ -+ if (errorDescription != NULL) -+ errorDescription[0] = 0; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ if (node->type & CONST_OPTION) -+ { -+ result = ASN1_GENERIC_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ counter = 0; -+ move = DOWN; -+ p = node; -+ while (1) -+ { -+ tag_len = 0; -+ inner_tag_len = 0; -+ ris = ASN1_SUCCESS; -+ if (move != UP) -+ { -+ if (p->type & CONST_SET) -+ { -+ p2 = _asn1_find_up (p); -+ len2 = p2->tmp_ival; -+ if (len2 == -1) -+ { -+ if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) -+ { -+ p = p2; -+ move = UP; -+ counter += 2; -+ DECR_LEN(ider_len, 2); -+ continue; -+ } -+ } -+ else if (counter == len2) -+ { -+ p = p2; -+ move = UP; -+ continue; -+ } -+ else if (counter > len2) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ p2 = p2->down; -+ while (p2) -+ { -+ if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) -+ { -+ ris = -+ extract_tag_der_recursive (p2, der + counter, -+ ider_len, &len2, NULL, flags); -+ if (ris == ASN1_SUCCESS) -+ { -+ p2->type &= ~CONST_NOT_USED; -+ p = p2; -+ break; -+ } -+ } -+ p2 = p2->right; -+ } -+ if (p2 == NULL) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ } -+ -+ /* the position in the DER structure this starts */ -+ p->start = counter; -+ p->end = total_len - 1; -+ -+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) -+ { -+ p2 = _asn1_find_up (p); -+ len2 = p2->tmp_ival; -+ if (counter == len2) -+ { -+ if (p->right) -+ { -+ p2 = p->right; -+ move = RIGHT; -+ } -+ else -+ move = UP; -+ -+ if (p->type & CONST_OPTION) -+ asn1_delete_structure (&p); -+ -+ p = p2; -+ continue; -+ } -+ } -+ -+ if (type_field (p->type) == ASN1_ETYPE_CHOICE) -+ { -+ while (p->down) -+ { -+ ris = -+ extract_tag_der_recursive (p->down, der + counter, -+ ider_len, &len2, NULL, flags); -+ -+ if (ris == ASN1_SUCCESS) -+ { -+ delete_unneeded_choice_fields(p->down); -+ break; -+ } -+ else if (ris == ASN1_ERROR_TYPE_ANY) -+ { -+ result = ASN1_ERROR_TYPE_ANY; -+ warn(); -+ goto cleanup; -+ } -+ else -+ { -+ p2 = p->down; -+ asn1_delete_structure (&p2); -+ } -+ } -+ -+ if (p->down == NULL) -+ { -+ if (!(p->type & CONST_OPTION)) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ } -+ else if (type_field (p->type) != ASN1_ETYPE_CHOICE) -+ p = p->down; -+ -+ p->start = counter; -+ } -+ -+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) -+ { -+ p2 = _asn1_find_up (p); -+ len2 = p2->tmp_ival; -+ -+ if ((len2 != -1) && (counter > len2)) -+ ris = ASN1_TAG_ERROR; -+ } -+ -+ if (ris == ASN1_SUCCESS) -+ ris = -+ extract_tag_der_recursive (p, der + counter, ider_len, -+ &tag_len, &inner_tag_len, flags); -+ -+ if (ris != ASN1_SUCCESS) -+ { -+ if (p->type & CONST_OPTION) -+ { -+ p->type |= CONST_NOT_USED; -+ move = RIGHT; -+ } -+ else if (p->type & CONST_DEFAULT) -+ { -+ _asn1_set_value (p, NULL, 0); -+ move = RIGHT; -+ } -+ else -+ { -+ if (errorDescription != NULL) -+ _asn1_error_description_tag_error (p, errorDescription); -+ -+ result = ASN1_TAG_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ } -+ else -+ { -+ DECR_LEN(ider_len, tag_len); -+ counter += tag_len; -+ } -+ } -+ -+ if (ris == ASN1_SUCCESS) -+ { -+ switch (type_field (p->type)) -+ { -+ case ASN1_ETYPE_NULL: -+ DECR_LEN(ider_len, 1); -+ if (der[counter]) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ counter++; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_BOOLEAN: -+ DECR_LEN(ider_len, 2); -+ -+ if (der[counter++] != 1) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ if (der[counter++] == 0) -+ _asn1_set_value (p, "F", 1); -+ else -+ _asn1_set_value (p, "T", 1); -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_INTEGER: -+ case ASN1_ETYPE_ENUMERATED: -+ len2 = -+ asn1_get_length_der (der + counter, ider_len, &len3); -+ if (len2 < 0) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len3+len2); -+ -+ _asn1_set_value (p, der + counter, len3 + len2); -+ counter += len3 + len2; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_OBJECT_ID: -+ result = -+ asn1_get_object_id_der (der + counter, ider_len, &len2, -+ temp, sizeof (temp)); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len2); -+ -+ tlen = strlen (temp); -+ if (tlen > 0) -+ _asn1_set_value (p, temp, tlen + 1); -+ -+ counter += len2; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_GENERALIZED_TIME: -+ case ASN1_ETYPE_UTC_TIME: -+ result = -+ _asn1_get_time_der (type_field (p->type), der + counter, ider_len, &len2, temp, -+ sizeof (temp) - 1, flags); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len2); -+ -+ tlen = strlen (temp); -+ if (tlen > 0) -+ _asn1_set_value (p, temp, tlen); -+ -+ counter += len2; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_OCTET_STRING: -+ if (counter < inner_tag_len) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ ptag = der + counter - inner_tag_len; -+ if ((flags & ASN1_DECODE_FLAG_STRICT_DER) || !(ptag[0] & ASN1_CLASS_STRUCTURED)) -+ { -+ if (ptag[0] & ASN1_CLASS_STRUCTURED) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ len2 = -+ asn1_get_length_der (der + counter, ider_len, &len3); -+ if (len2 < 0) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len3+len2); -+ -+ _asn1_set_value (p, der + counter, len3 + len2); -+ counter += len3 + len2; -+ } -+ else -+ { -+ unsigned dflags = 0, vlen, ber_len; -+ -+ if (ptag[0] & ASN1_CLASS_STRUCTURED) -+ dflags |= DECODE_FLAG_CONSTRUCTED; -+ -+ result = _asn1_decode_simple_ber(type_field (p->type), der+counter, ider_len, &ptmp, &vlen, &ber_len, dflags); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, ber_len); -+ -+ _asn1_set_value_lv (p, ptmp, vlen); -+ -+ counter += ber_len; -+ free(ptmp); -+ } -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_GENERALSTRING: -+ case ASN1_ETYPE_NUMERIC_STRING: -+ case ASN1_ETYPE_IA5_STRING: -+ case ASN1_ETYPE_TELETEX_STRING: -+ case ASN1_ETYPE_PRINTABLE_STRING: -+ case ASN1_ETYPE_UNIVERSAL_STRING: -+ case ASN1_ETYPE_BMP_STRING: -+ case ASN1_ETYPE_UTF8_STRING: -+ case ASN1_ETYPE_VISIBLE_STRING: -+ case ASN1_ETYPE_BIT_STRING: -+ len2 = -+ asn1_get_length_der (der + counter, ider_len, &len3); -+ if (len2 < 0) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len3+len2); -+ -+ _asn1_set_value (p, der + counter, len3 + len2); -+ counter += len3 + len2; -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_SEQUENCE: -+ case ASN1_ETYPE_SET: -+ if (move == UP) -+ { -+ len2 = p->tmp_ival; -+ p->tmp_ival = 0; -+ if (len2 == -1) -+ { /* indefinite length method */ -+ DECR_LEN(ider_len, 2); -+ if ((der[counter]) || der[counter + 1]) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ counter += 2; -+ } -+ else -+ { /* definite length method */ -+ if (len2 != counter) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ } -+ move = RIGHT; -+ } -+ else -+ { /* move==DOWN || move==RIGHT */ -+ len3 = -+ asn1_get_length_der (der + counter, ider_len, &len2); -+ if (IS_ERR(len3, flags)) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len2); -+ counter += len2; -+ -+ if (len3 > 0) -+ { -+ p->tmp_ival = counter + len3; -+ move = DOWN; -+ } -+ else if (len3 == 0) -+ { -+ p2 = p->down; -+ while (p2) -+ { -+ if (type_field (p2->type) != ASN1_ETYPE_TAG) -+ { -+ p3 = p2->right; -+ asn1_delete_structure (&p2); -+ p2 = p3; -+ } -+ else -+ p2 = p2->right; -+ } -+ move = RIGHT; -+ } -+ else -+ { /* indefinite length method */ -+ p->tmp_ival = -1; -+ move = DOWN; -+ } -+ } -+ break; -+ case ASN1_ETYPE_SEQUENCE_OF: -+ case ASN1_ETYPE_SET_OF: -+ if (move == UP) -+ { -+ len2 = p->tmp_ival; -+ if (len2 == -1) -+ { /* indefinite length method */ -+ if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1])) -+ { -+ result = _asn1_append_sequence_set (p, &tcache); -+ if (result != 0) -+ { -+ warn(); -+ goto cleanup; -+ } -+ p = tcache.tail; -+ move = RIGHT; -+ continue; -+ } -+ -+ p->tmp_ival = 0; -+ tcache.tail = NULL; /* finished decoding this structure */ -+ tcache.head = NULL; -+ DECR_LEN(ider_len, 2); -+ counter += 2; -+ } -+ else -+ { /* definite length method */ -+ if (len2 > counter) -+ { -+ result = _asn1_append_sequence_set (p, &tcache); -+ if (result != 0) -+ { -+ warn(); -+ goto cleanup; -+ } -+ p = tcache.tail; -+ move = RIGHT; -+ continue; -+ } -+ -+ p->tmp_ival = 0; -+ tcache.tail = NULL; /* finished decoding this structure */ -+ tcache.head = NULL; -+ -+ if (len2 != counter) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ } -+ } -+ else -+ { /* move==DOWN || move==RIGHT */ -+ len3 = -+ asn1_get_length_der (der + counter, ider_len, &len2); -+ if (IS_ERR(len3, flags)) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len2); -+ counter += len2; -+ if (len3) -+ { -+ if (len3 > 0) -+ { /* definite length method */ -+ p->tmp_ival = counter + len3; -+ } -+ else -+ { /* indefinite length method */ -+ p->tmp_ival = -1; -+ } -+ -+ p2 = p->down; -+ if (p2 == NULL) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ while ((type_field (p2->type) == ASN1_ETYPE_TAG) -+ || (type_field (p2->type) == ASN1_ETYPE_SIZE)) -+ p2 = p2->right; -+ if (p2->right == NULL) -+ { -+ result = _asn1_append_sequence_set (p, &tcache); -+ if (result != 0) -+ { -+ warn(); -+ goto cleanup; -+ } -+ } -+ p = p2; -+ } -+ } -+ move = RIGHT; -+ break; -+ case ASN1_ETYPE_ANY: -+ /* Check indefinite lenth method in an EXPLICIT TAG */ -+ -+ if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && (p->type & CONST_TAG) && -+ tag_len == 2 && (der[counter - 1] == 0x80)) -+ indefinite = 1; -+ else -+ indefinite = 0; -+ -+ if (asn1_get_tag_der -+ (der + counter, ider_len, &class, &len2, -+ &tag) != ASN1_SUCCESS) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len2); -+ -+ len4 = -+ asn1_get_length_der (der + counter + len2, -+ ider_len, &len3); -+ if (IS_ERR(len4, flags)) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ if (len4 != -1) /* definite */ -+ { -+ len2 += len4; -+ -+ DECR_LEN(ider_len, len4+len3); -+ _asn1_set_value_lv (p, der + counter, len2 + len3); -+ counter += len2 + len3; -+ } -+ else /* == -1 */ -+ { /* indefinite length */ -+ ider_len += len2; /* undo DECR_LEN */ -+ -+ if (counter == 0) -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ -+ result = -+ _asn1_get_indefinite_length_string (der + counter, ider_len, &len2); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ DECR_LEN(ider_len, len2); -+ _asn1_set_value_lv (p, der + counter, len2); -+ counter += len2; -+ -+ } -+ -+ /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with -+ an indefinite length method. */ -+ if (indefinite) -+ { -+ DECR_LEN(ider_len, 2); -+ if (!der[counter] && !der[counter + 1]) -+ { -+ counter += 2; -+ } -+ else -+ { -+ result = ASN1_DER_ERROR; -+ warn(); -+ goto cleanup; -+ } -+ } -+ -+ move = RIGHT; -+ break; -+ default: -+ move = (move == UP) ? RIGHT : DOWN; -+ break; -+ } -+ } -+ -+ if (p) -+ { -+ p->end = counter - 1; -+ } -+ -+ if (p == node && move != DOWN) -+ break; -+ -+ if (move == DOWN) -+ { -+ if (p->down) -+ p = p->down; -+ else -+ move = RIGHT; -+ } -+ if ((move == RIGHT) && !(p->type & CONST_SET)) -+ { -+ if (p->right) -+ p = p->right; -+ else -+ move = UP; -+ } -+ if (move == UP) -+ p = _asn1_find_up (p); -+ } -+ -+ _asn1_delete_not_used (*element); -+ -+ if ((ider_len < 0) || -+ (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0))) -+ { -+ warn(); -+ result = ASN1_DER_ERROR; -+ goto cleanup; -+ } -+ -+ *max_ider_len = total_len - ider_len; -+ -+ return ASN1_SUCCESS; -+ -+cleanup: -+ asn1_delete_structure (element); -+ return result; -+} -+ -+ -+/** -+ * asn1_der_decoding: -+ * @element: pointer to an ASN1 structure. -+ * @ider: vector that contains the DER encoding. -+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]. -+ * @errorDescription: null-terminated string contains details when an -+ * error occurred. -+ * -+ * Fill the structure *@element with values of a DER encoding -+ * string. The structure must just be created with function -+ * asn1_create_element(). -+ * -+ * Note that the *@element variable is provided as a pointer for -+ * historical reasons. -+ * -+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND -+ * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or -+ * %ASN1_DER_ERROR if the der encoding doesn't match the structure -+ * name (*@ELEMENT deleted). -+ **/ -+int -+asn1_der_decoding (asn1_node * element, const void *ider, int ider_len, -+ char *errorDescription) -+{ -+ return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription); -+} -+ -+/** -+ * asn1_der_decoding_element: -+ * @structure: pointer to an ASN1 structure -+ * @elementName: name of the element to fill -+ * @ider: vector that contains the DER encoding of the whole structure. -+ * @len: number of bytes of *der: der[0]..der[len-1] -+ * @errorDescription: null-terminated string contains details when an -+ * error occurred. -+ * -+ * Fill the element named @ELEMENTNAME with values of a DER encoding -+ * string. The structure must just be created with function -+ * asn1_create_element(). The DER vector must contain the encoding -+ * string of the whole @STRUCTURE. If an error occurs during the -+ * decoding procedure, the *@STRUCTURE is deleted and set equal to -+ * %NULL. -+ * -+ * This function is deprecated and may just be an alias to asn1_der_decoding -+ * in future versions. Use asn1_der_decoding() instead. -+ * -+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND -+ * if ELEMENT is %NULL or @elementName == NULL, and -+ * %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't -+ * match the structure @structure (*ELEMENT deleted). -+ **/ -+int -+asn1_der_decoding_element (asn1_node * structure, const char *elementName, -+ const void *ider, int len, char *errorDescription) -+{ -+ return asn1_der_decoding(structure, ider, len, errorDescription); -+} -+ -+/** -+ * asn1_der_decoding_startEnd: -+ * @element: pointer to an ASN1 element -+ * @ider: vector that contains the DER encoding. -+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1] -+ * @name_element: an element of NAME structure. -+ * @start: the position of the first byte of NAME_ELEMENT decoding -+ * (@ider[*start]) -+ * @end: the position of the last byte of NAME_ELEMENT decoding -+ * (@ider[*end]) -+ * -+ * Find the start and end point of an element in a DER encoding -+ * string. I mean that if you have a der encoding and you have already -+ * used the function asn1_der_decoding() to fill a structure, it may -+ * happen that you want to find the piece of string concerning an -+ * element of the structure. -+ * -+ * One example is the sequence "tbsCertificate" inside an X509 -+ * certificate. -+ * -+ * Note that since libtasn1 3.7 the @ider and @ider_len parameters -+ * can be omitted, if the element is already decoded using asn1_der_decoding(). -+ * -+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND -+ * if ELEMENT is %asn1_node EMPTY or @name_element is not a valid -+ * element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding -+ * doesn't match the structure ELEMENT. -+ **/ -+int -+asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len, -+ const char *name_element, int *start, int *end) -+{ -+ asn1_node node, node_to_find; -+ int result = ASN1_DER_ERROR; -+ -+ node = element; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ node_to_find = asn1_find_node (node, name_element); -+ -+ if (node_to_find == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ *start = node_to_find->start; -+ *end = node_to_find->end; -+ -+ if (*start == 0 && *end == 0) -+ { -+ if (ider == NULL || ider_len == 0) -+ return ASN1_GENERIC_ERROR; -+ -+ /* it seems asn1_der_decoding() wasn't called before. Do it now */ -+ result = asn1_der_decoding (&node, ider, ider_len, NULL); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ return result; -+ } -+ -+ node_to_find = asn1_find_node (node, name_element); -+ if (node_to_find == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ *start = node_to_find->start; -+ *end = node_to_find->end; -+ } -+ -+ if (*end < *start) -+ return ASN1_GENERIC_ERROR; -+ -+ return ASN1_SUCCESS; -+} -+ -+/** -+ * asn1_expand_any_defined_by: -+ * @definitions: ASN1 definitions -+ * @element: pointer to an ASN1 structure -+ * -+ * Expands every "ANY DEFINED BY" element of a structure created from -+ * a DER decoding process (asn1_der_decoding function). The element -+ * ANY must be defined by an OBJECT IDENTIFIER. The type used to -+ * expand the element ANY is the first one following the definition of -+ * the actual value of the OBJECT IDENTIFIER. -+ * -+ * Returns: %ASN1_SUCCESS if Substitution OK, %ASN1_ERROR_TYPE_ANY if -+ * some "ANY DEFINED BY" element couldn't be expanded due to a -+ * problem in OBJECT_ID -> TYPE association, or other error codes -+ * depending on DER decoding. -+ **/ -+int -+asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element) -+{ -+ char name[2 * ASN1_MAX_NAME_SIZE + 2], -+ value[ASN1_MAX_NAME_SIZE]; -+ int retCode = ASN1_SUCCESS, result; -+ int len, len2, len3; -+ asn1_node_const p2; -+ asn1_node p, p3, aux = NULL; -+ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; -+ const char *definitionsName; -+ -+ if ((definitions == NULL) || (*element == NULL)) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ definitionsName = definitions->name; -+ -+ p = *element; -+ while (p) -+ { -+ -+ switch (type_field (p->type)) -+ { -+ case ASN1_ETYPE_ANY: -+ if ((p->type & CONST_DEFINED_BY) && (p->value)) -+ { -+ /* search the "DEF_BY" element */ -+ p2 = p->down; -+ while ((p2) && (type_field (p2->type) != ASN1_ETYPE_CONSTANT)) -+ p2 = p2->right; -+ -+ if (!p2) -+ { -+ retCode = ASN1_ERROR_TYPE_ANY; -+ break; -+ } -+ -+ p3 = _asn1_find_up (p); -+ -+ if (!p3) -+ { -+ retCode = ASN1_ERROR_TYPE_ANY; -+ break; -+ } -+ -+ p3 = p3->down; -+ while (p3) -+ { -+ if (!(strcmp (p3->name, p2->name))) -+ break; -+ p3 = p3->right; -+ } -+ -+ if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || -+ (p3->value == NULL)) -+ { -+ -+ p3 = _asn1_find_up (p); -+ p3 = _asn1_find_up (p3); -+ -+ if (!p3) -+ { -+ retCode = ASN1_ERROR_TYPE_ANY; -+ break; -+ } -+ -+ p3 = p3->down; -+ -+ while (p3) -+ { -+ if (!(strcmp (p3->name, p2->name))) -+ break; -+ p3 = p3->right; -+ } -+ -+ if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) -+ || (p3->value == NULL)) -+ { -+ retCode = ASN1_ERROR_TYPE_ANY; -+ break; -+ } -+ } -+ -+ /* search the OBJECT_ID into definitions */ -+ p2 = definitions->down; -+ while (p2) -+ { -+ if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && -+ (p2->type & CONST_ASSIGN)) -+ { -+ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); -+ -+ len = ASN1_MAX_NAME_SIZE; -+ result = -+ asn1_read_value (definitions, name, value, &len); -+ -+ if ((result == ASN1_SUCCESS) -+ && (!_asn1_strcmp (p3->value, value))) -+ { -+ p2 = p2->right; /* pointer to the structure to -+ use for expansion */ -+ while ((p2) && (p2->type & CONST_ASSIGN)) -+ p2 = p2->right; -+ -+ if (p2) -+ { -+ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); -+ -+ result = -+ asn1_create_element (definitions, name, &aux); -+ if (result == ASN1_SUCCESS) -+ { -+ _asn1_cpy_name (aux, p); -+ len2 = -+ asn1_get_length_der (p->value, -+ p->value_len, &len3); -+ if (len2 < 0) -+ return ASN1_DER_ERROR; -+ -+ result = -+ asn1_der_decoding (&aux, p->value + len3, -+ len2, -+ errorDescription); -+ if (result == ASN1_SUCCESS) -+ { -+ -+ _asn1_set_right (aux, p->right); -+ _asn1_set_right (p, aux); -+ -+ result = asn1_delete_structure (&p); -+ if (result == ASN1_SUCCESS) -+ { -+ p = aux; -+ aux = NULL; -+ break; -+ } -+ else -+ { /* error with asn1_delete_structure */ -+ asn1_delete_structure (&aux); -+ retCode = result; -+ break; -+ } -+ } -+ else -+ { /* error with asn1_der_decoding */ -+ retCode = result; -+ break; -+ } -+ } -+ else -+ { /* error with asn1_create_element */ -+ retCode = result; -+ break; -+ } -+ } -+ else -+ { /* error with the pointer to the structure to exapand */ -+ retCode = ASN1_ERROR_TYPE_ANY; -+ break; -+ } -+ } -+ } -+ p2 = p2->right; -+ } /* end while */ -+ -+ if (!p2) -+ { -+ retCode = ASN1_ERROR_TYPE_ANY; -+ break; -+ } -+ -+ } -+ break; -+ default: -+ break; -+ } -+ -+ -+ if (p->down) -+ { -+ p = p->down; -+ } -+ else if (p == *element) -+ { -+ p = NULL; -+ break; -+ } -+ else if (p->right) -+ p = p->right; -+ else -+ { -+ while (1) -+ { -+ p = _asn1_find_up (p); -+ if (p == *element) -+ { -+ p = NULL; -+ break; -+ } -+ if (p->right) -+ { -+ p = p->right; -+ break; -+ } -+ } -+ } -+ } -+ -+ return retCode; -+} -+ -+/** -+ * asn1_expand_octet_string: -+ * @definitions: ASN1 definitions -+ * @element: pointer to an ASN1 structure -+ * @octetName: name of the OCTECT STRING field to expand. -+ * @objectName: name of the OBJECT IDENTIFIER field to use to define -+ * the type for expansion. -+ * -+ * Expands an "OCTET STRING" element of a structure created from a DER -+ * decoding process (the asn1_der_decoding() function). The type used -+ * for expansion is the first one following the definition of the -+ * actual value of the OBJECT IDENTIFIER indicated by OBJECTNAME. -+ * -+ * Returns: %ASN1_SUCCESS if substitution OK, %ASN1_ELEMENT_NOT_FOUND -+ * if @objectName or @octetName are not correct, -+ * %ASN1_VALUE_NOT_VALID if it wasn't possible to find the type to -+ * use for expansion, or other errors depending on DER decoding. -+ **/ -+int -+asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, -+ const char *octetName, const char *objectName) -+{ -+ char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; -+ int retCode = ASN1_SUCCESS, result; -+ int len, len2, len3; -+ asn1_node_const p2; -+ asn1_node aux = NULL; -+ asn1_node octetNode = NULL, objectNode = NULL; -+ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; -+ -+ if ((definitions == NULL) || (*element == NULL)) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ octetNode = asn1_find_node (*element, octetName); -+ if (octetNode == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ if (type_field (octetNode->type) != ASN1_ETYPE_OCTET_STRING) -+ return ASN1_ELEMENT_NOT_FOUND; -+ if (octetNode->value == NULL) -+ return ASN1_VALUE_NOT_FOUND; -+ -+ objectNode = asn1_find_node (*element, objectName); -+ if (objectNode == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ if (type_field (objectNode->type) != ASN1_ETYPE_OBJECT_ID) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ if (objectNode->value == NULL) -+ return ASN1_VALUE_NOT_FOUND; -+ -+ -+ /* search the OBJECT_ID into definitions */ -+ p2 = definitions->down; -+ while (p2) -+ { -+ if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && -+ (p2->type & CONST_ASSIGN)) -+ { -+ strcpy (name, definitions->name); -+ strcat (name, "."); -+ strcat (name, p2->name); -+ -+ len = sizeof (value); -+ result = asn1_read_value (definitions, name, value, &len); -+ -+ if ((result == ASN1_SUCCESS) -+ && (!_asn1_strcmp (objectNode->value, value))) -+ { -+ -+ p2 = p2->right; /* pointer to the structure to -+ use for expansion */ -+ while ((p2) && (p2->type & CONST_ASSIGN)) -+ p2 = p2->right; -+ -+ if (p2) -+ { -+ strcpy (name, definitions->name); -+ strcat (name, "."); -+ strcat (name, p2->name); -+ -+ result = asn1_create_element (definitions, name, &aux); -+ if (result == ASN1_SUCCESS) -+ { -+ _asn1_cpy_name (aux, octetNode); -+ len2 = -+ asn1_get_length_der (octetNode->value, -+ octetNode->value_len, &len3); -+ if (len2 < 0) -+ return ASN1_DER_ERROR; -+ -+ result = -+ asn1_der_decoding (&aux, octetNode->value + len3, -+ len2, errorDescription); -+ if (result == ASN1_SUCCESS) -+ { -+ -+ _asn1_set_right (aux, octetNode->right); -+ _asn1_set_right (octetNode, aux); -+ -+ result = asn1_delete_structure (&octetNode); -+ if (result == ASN1_SUCCESS) -+ { -+ aux = NULL; -+ break; -+ } -+ else -+ { /* error with asn1_delete_structure */ -+ asn1_delete_structure (&aux); -+ retCode = result; -+ break; -+ } -+ } -+ else -+ { /* error with asn1_der_decoding */ -+ retCode = result; -+ break; -+ } -+ } -+ else -+ { /* error with asn1_create_element */ -+ retCode = result; -+ break; -+ } -+ } -+ else -+ { /* error with the pointer to the structure to exapand */ -+ retCode = ASN1_VALUE_NOT_VALID; -+ break; -+ } -+ } -+ } -+ -+ p2 = p2->right; -+ -+ } -+ -+ if (!p2) -+ retCode = ASN1_VALUE_NOT_VALID; -+ -+ return retCode; -+} -+ -+/*- -+ * _asn1_decode_simple_der: -+ * @etype: The type of the string to be encoded (ASN1_ETYPE_) -+ * @der: the encoded string -+ * @_der_len: the bytes of the encoded string -+ * @str: a pointer to the data -+ * @str_len: the length of the data -+ * @dflags: DECODE_FLAG_* -+ * -+ * Decodes a simple DER encoded type (e.g. a string, which is not constructed). -+ * The output is a pointer inside the @der. -+ * -+ * Returns: %ASN1_SUCCESS if successful or an error value. -+ -*/ -+static int -+_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, const unsigned char **str, -+ unsigned int *str_len, unsigned dflags) -+{ -+ int tag_len, len_len; -+ const unsigned char *p; -+ int der_len = _der_len; -+ unsigned char class; -+ unsigned long tag; -+ long ret; -+ -+ if (der == NULL || der_len == 0) -+ return ASN1_VALUE_NOT_VALID; -+ -+ if (ETYPE_OK (etype) == 0 || ETYPE_IS_STRING(etype) == 0) -+ return ASN1_VALUE_NOT_VALID; -+ -+ /* doesn't handle constructed classes */ -+ class = ETYPE_CLASS(etype); -+ if (class != ASN1_CLASS_UNIVERSAL) -+ return ASN1_VALUE_NOT_VALID; -+ -+ p = der; -+ -+ if (dflags & DECODE_FLAG_HAVE_TAG) -+ { -+ ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); -+ if (ret != ASN1_SUCCESS) -+ return ret; -+ -+ if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype)) -+ { -+ warn(); -+ return ASN1_DER_ERROR; -+ } -+ -+ p += tag_len; -+ der_len -= tag_len; -+ if (der_len <= 0) -+ return ASN1_DER_ERROR; -+ } -+ -+ ret = asn1_get_length_der (p, der_len, &len_len); -+ if (ret < 0) -+ return ASN1_DER_ERROR; -+ -+ p += len_len; -+ der_len -= len_len; -+ if (der_len <= 0) -+ return ASN1_DER_ERROR; -+ -+ *str_len = ret; -+ *str = p; -+ -+ return ASN1_SUCCESS; -+} -+ -+/** -+ * asn1_decode_simple_der: -+ * @etype: The type of the string to be encoded (ASN1_ETYPE_) -+ * @der: the encoded string -+ * @_der_len: the bytes of the encoded string -+ * @str: a pointer to the data -+ * @str_len: the length of the data -+ * -+ * Decodes a simple DER encoded type (e.g. a string, which is not constructed). -+ * The output is a pointer inside the @der. -+ * -+ * Returns: %ASN1_SUCCESS if successful or an error value. -+ **/ -+int -+asn1_decode_simple_der (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, const unsigned char **str, -+ unsigned int *str_len) -+{ -+ return _asn1_decode_simple_der(etype, der, _der_len, str, str_len, DECODE_FLAG_HAVE_TAG); -+} -+ -+static int append(uint8_t **dst, unsigned *dst_size, const unsigned char *src, unsigned src_size) -+{ -+ if (src_size == 0) -+ return ASN1_SUCCESS; -+ -+ *dst = _asn1_realloc(*dst, *dst_size+src_size); -+ if (*dst == NULL) -+ return ASN1_MEM_ALLOC_ERROR; -+ memcpy(*dst + *dst_size, src, src_size); -+ *dst_size += src_size; -+ return ASN1_SUCCESS; -+} -+ -+/*- -+ * _asn1_decode_simple_ber: -+ * @etype: The type of the string to be encoded (ASN1_ETYPE_) -+ * @der: the encoded string -+ * @_der_len: the bytes of the encoded string -+ * @str: a pointer to the data -+ * @str_len: the length of the data -+ * @ber_len: the total length occupied by BER (may be %NULL) -+ * @have_tag: whether a DER tag is included -+ * -+ * Decodes a BER encoded type. The output is an allocated value -+ * of the data. This decodes BER STRINGS only. Other types are -+ * decoded as DER. -+ * -+ * Returns: %ASN1_SUCCESS if successful or an error value. -+ -*/ -+static int -+_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, unsigned char **str, -+ unsigned int *str_len, unsigned int *ber_len, -+ unsigned dflags) -+{ -+ int tag_len, len_len; -+ const unsigned char *p; -+ int der_len = _der_len; -+ uint8_t *total = NULL; -+ unsigned total_size = 0; -+ unsigned char class; -+ unsigned long tag; -+ unsigned char *out = NULL; -+ const unsigned char *cout = NULL; -+ unsigned out_len; -+ long result; -+ -+ if (ber_len) *ber_len = 0; -+ -+ if (der == NULL || der_len == 0) -+ { -+ warn(); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ -+ if (ETYPE_OK (etype) == 0) -+ { -+ warn(); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ -+ /* doesn't handle constructed + definite classes */ -+ class = ETYPE_CLASS (etype); -+ if (class != ASN1_CLASS_UNIVERSAL) -+ { -+ warn(); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ -+ p = der; -+ -+ if (dflags & DECODE_FLAG_HAVE_TAG) -+ { -+ result = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ return result; -+ } -+ -+ if (tag != ETYPE_TAG (etype)) -+ { -+ warn(); -+ return ASN1_DER_ERROR; -+ } -+ -+ p += tag_len; -+ -+ DECR_LEN(der_len, tag_len); -+ -+ if (ber_len) *ber_len += tag_len; -+ } -+ -+ /* indefinite constructed */ -+ if ((((dflags & DECODE_FLAG_CONSTRUCTED) || class == ASN1_CLASS_STRUCTURED) && ETYPE_IS_STRING(etype)) && -+ !(dflags & DECODE_FLAG_LEVEL3)) -+ { -+ if (der_len == 0) -+ { -+ warn(); -+ result = ASN1_DER_ERROR; -+ goto cleanup; -+ } -+ -+ if (der_len > 0 && p[0] == 0x80) /* indefinite */ -+ { -+ len_len = 1; -+ DECR_LEN(der_len, len_len); -+ p += len_len; -+ -+ if (ber_len) *ber_len += len_len; -+ -+ /* decode the available octet strings */ -+ do -+ { -+ unsigned tmp_len; -+ unsigned flags = DECODE_FLAG_HAVE_TAG; -+ -+ if (dflags & DECODE_FLAG_LEVEL1) -+ flags |= DECODE_FLAG_LEVEL2; -+ else if (dflags & DECODE_FLAG_LEVEL2) -+ flags |= DECODE_FLAG_LEVEL3; -+ else -+ flags |= DECODE_FLAG_LEVEL1; -+ -+ result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, -+ flags); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ p += tmp_len; -+ DECR_LEN(der_len, tmp_len); -+ -+ if (ber_len) *ber_len += tmp_len; -+ -+ DECR_LEN(der_len, 2); /* we need the EOC */ -+ -+ result = append(&total, &total_size, out, out_len); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ free(out); -+ out = NULL; -+ -+ if (p[0] == 0 && p[1] == 0) /* EOC */ -+ { -+ if (ber_len) *ber_len += 2; -+ break; -+ } -+ -+ /* no EOC */ -+ der_len += 2; -+ -+ if (der_len == 2) -+ { -+ warn(); -+ result = ASN1_DER_ERROR; -+ goto cleanup; -+ } -+ } -+ while(1); -+ } -+ else /* constructed */ -+ { -+ long const_len; -+ -+ result = asn1_get_length_ber(p, der_len, &len_len); -+ if (result < 0) -+ { -+ warn(); -+ result = ASN1_DER_ERROR; -+ goto cleanup; -+ } -+ -+ DECR_LEN(der_len, len_len); -+ p += len_len; -+ -+ const_len = result; -+ -+ if (ber_len) *ber_len += len_len; -+ -+ /* decode the available octet strings */ -+ while(const_len > 0) -+ { -+ unsigned tmp_len; -+ unsigned flags = DECODE_FLAG_HAVE_TAG; -+ -+ if (dflags & DECODE_FLAG_LEVEL1) -+ flags |= DECODE_FLAG_LEVEL2; -+ else if (dflags & DECODE_FLAG_LEVEL2) -+ flags |= DECODE_FLAG_LEVEL3; -+ else -+ flags |= DECODE_FLAG_LEVEL1; -+ -+ result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, -+ flags); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ p += tmp_len; -+ DECR_LEN(der_len, tmp_len); -+ DECR_LEN(const_len, tmp_len); -+ -+ if (ber_len) *ber_len += tmp_len; -+ -+ result = append(&total, &total_size, out, out_len); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ free(out); -+ out = NULL; -+ } -+ } -+ } -+ else if (class == ETYPE_CLASS(etype)) -+ { -+ if (ber_len) -+ { -+ result = asn1_get_length_der (p, der_len, &len_len); -+ if (result < 0) -+ { -+ warn(); -+ result = ASN1_DER_ERROR; -+ goto cleanup; -+ } -+ *ber_len += result + len_len; -+ } -+ -+ /* non-string values are decoded as DER */ -+ result = _asn1_decode_simple_der(etype, der, _der_len, &cout, &out_len, dflags); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ -+ result = append(&total, &total_size, cout, out_len); -+ if (result != ASN1_SUCCESS) -+ { -+ warn(); -+ goto cleanup; -+ } -+ } -+ else -+ { -+ warn(); -+ result = ASN1_DER_ERROR; -+ goto cleanup; -+ } -+ -+ *str = total; -+ *str_len = total_size; -+ -+ return ASN1_SUCCESS; -+cleanup: -+ free(out); -+ free(total); -+ return result; -+} -+ -+/** -+ * asn1_decode_simple_ber: -+ * @etype: The type of the string to be encoded (ASN1_ETYPE_) -+ * @der: the encoded string -+ * @_der_len: the bytes of the encoded string -+ * @str: a pointer to the data -+ * @str_len: the length of the data -+ * @ber_len: the total length occupied by BER (may be %NULL) -+ * -+ * Decodes a BER encoded type. The output is an allocated value -+ * of the data. This decodes BER STRINGS only. Other types are -+ * decoded as DER. -+ * -+ * Returns: %ASN1_SUCCESS if successful or an error value. -+ **/ -+int -+asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, unsigned char **str, -+ unsigned int *str_len, unsigned int *ber_len) -+{ -+ return _asn1_decode_simple_ber(etype, der, _der_len, str, str_len, ber_len, DECODE_FLAG_HAVE_TAG); -+} -diff --git a/grub-core/lib/libtasn1/lib/element.c b/grub-core/lib/libtasn1/lib/element.c -new file mode 100644 -index 00000000000..997eb2725dc ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/element.c -@@ -0,0 +1,1111 @@ -+/* -+ * Copyright (C) 2000-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+/*****************************************************/ -+/* File: element.c */ -+/* Description: Functions with the read and write */ -+/* functions. */ -+/*****************************************************/ -+ -+ -+#include -+#include "parser_aux.h" -+#include -+#include "structure.h" -+#include "c-ctype.h" -+#include "element.h" -+ -+void -+_asn1_hierarchical_name (asn1_node_const node, char *name, int name_size) -+{ -+ asn1_node_const p; -+ char tmp_name[64]; -+ -+ p = node; -+ -+ name[0] = 0; -+ -+ while (p != NULL) -+ { -+ if (p->name[0] != 0) -+ { -+ _asn1_str_cpy (tmp_name, sizeof (tmp_name), name), -+ _asn1_str_cpy (name, name_size, p->name); -+ _asn1_str_cat (name, name_size, "."); -+ _asn1_str_cat (name, name_size, tmp_name); -+ } -+ p = _asn1_find_up (p); -+ } -+ -+ if (name[0] == 0) -+ _asn1_str_cpy (name, name_size, "ROOT"); -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_convert_integer */ -+/* Description: converts an integer from a null terminated string */ -+/* to der decoding. The convertion from a null */ -+/* terminated string to an integer is made with */ -+/* the 'strtol' function. */ -+/* Parameters: */ -+/* value: null terminated string to convert. */ -+/* value_out: convertion result (memory must be already */ -+/* allocated). */ -+/* value_out_size: number of bytes of value_out. */ -+/* len: number of significant byte of value_out. */ -+/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */ -+/******************************************************************/ -+int -+_asn1_convert_integer (const unsigned char *value, unsigned char *value_out, -+ int value_out_size, int *len) -+{ -+ char negative; -+ unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; -+ long valtmp; -+ int k, k2; -+ -+ valtmp = _asn1_strtol (value, NULL, 10); -+ -+ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) -+ { -+ val[SIZEOF_UNSIGNED_LONG_INT - k - 1] = (valtmp >> (8 * k)) & 0xFF; -+ } -+ -+ if (val[0] & 0x80) -+ negative = 1; -+ else -+ negative = 0; -+ -+ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT - 1; k++) -+ { -+ if (negative && (val[k] != 0xFF)) -+ break; -+ else if (!negative && val[k]) -+ break; -+ } -+ -+ if ((negative && !(val[k] & 0x80)) || (!negative && (val[k] & 0x80))) -+ k--; -+ -+ *len = SIZEOF_UNSIGNED_LONG_INT - k; -+ -+ if (SIZEOF_UNSIGNED_LONG_INT - k > value_out_size) -+ /* VALUE_OUT is too short to contain the value conversion */ -+ return ASN1_MEM_ERROR; -+ -+ if (value_out != NULL) -+ { -+ for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++) -+ value_out[k2 - k] = val[k2]; -+ } -+ -+#if 0 -+ printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len); -+ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) -+ printf (", vOut[%d]=%d", k, value_out[k]); -+ printf ("\n"); -+#endif -+ -+ return ASN1_SUCCESS; -+} -+ -+/* Appends a new element into the sequence (or set) defined by this -+ * node. The new element will have a name of '?number', where number -+ * is a monotonically increased serial number. -+ * -+ * The last element in the list may be provided in @pcache, to avoid -+ * traversing the list, an expensive operation in long lists. -+ * -+ * On success it returns in @pcache the added element (which is the -+ * tail in the list of added elements). -+ */ -+int -+_asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) -+{ -+ asn1_node p, p2; -+ char temp[LTOSTR_MAX_SIZE]; -+ long n; -+ -+ if (!node || !(node->down)) -+ return ASN1_GENERIC_ERROR; -+ -+ p = node->down; -+ while ((type_field (p->type) == ASN1_ETYPE_TAG) -+ || (type_field (p->type) == ASN1_ETYPE_SIZE)) -+ p = p->right; -+ -+ p2 = _asn1_copy_structure3 (p); -+ if (p2 == NULL) -+ return ASN1_GENERIC_ERROR; -+ -+ if (pcache == NULL || pcache->tail == NULL || pcache->head != node) -+ { -+ while (p->right) -+ { -+ p = p->right; -+ } -+ } -+ else -+ { -+ p = pcache->tail; -+ } -+ -+ _asn1_set_right (p, p2); -+ if (pcache) -+ { -+ pcache->head = node; -+ pcache->tail = p2; -+ } -+ -+ if (p->name[0] == 0) -+ _asn1_str_cpy (temp, sizeof (temp), "?1"); -+ else -+ { -+ n = strtol (p->name + 1, NULL, 0); -+ n++; -+ temp[0] = '?'; -+ _asn1_ltostr (n, temp + 1); -+ } -+ _asn1_set_name (p2, temp); -+ /* p2->type |= CONST_OPTION; */ -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/** -+ * asn1_write_value: -+ * @node_root: pointer to a structure -+ * @name: the name of the element inside the structure that you want to set. -+ * @ivalue: vector used to specify the value to set. If len is >0, -+ * VALUE must be a two's complement form integer. if len=0 *VALUE -+ * must be a null terminated string with an integer value. -+ * @len: number of bytes of *value to use to set the value: -+ * value[0]..value[len-1] or 0 if value is a null terminated string -+ * -+ * Set the value of one element inside a structure. -+ * -+ * If an element is OPTIONAL and you want to delete it, you must use -+ * the value=NULL and len=0. Using "pkix.asn": -+ * -+ * result=asn1_write_value(cert, "tbsCertificate.issuerUniqueID", -+ * NULL, 0); -+ * -+ * Description for each type: -+ * -+ * INTEGER: VALUE must contain a two's complement form integer. -+ * -+ * value[0]=0xFF , len=1 -> integer=-1. -+ * value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1. -+ * value[0]=0x01 , len=1 -> integer= 1. -+ * value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1. -+ * value="123" , len=0 -> integer= 123. -+ * -+ * ENUMERATED: As INTEGER (but only with not negative numbers). -+ * -+ * BOOLEAN: VALUE must be the null terminated string "TRUE" or -+ * "FALSE" and LEN != 0. -+ * -+ * value="TRUE" , len=1 -> boolean=TRUE. -+ * value="FALSE" , len=1 -> boolean=FALSE. -+ * -+ * OBJECT IDENTIFIER: VALUE must be a null terminated string with -+ * each number separated by a dot (e.g. "1.2.3.543.1"). LEN != 0. -+ * -+ * value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha. -+ * -+ * UTCTime: VALUE must be a null terminated string in one of these -+ * formats: "YYMMDDhhmmssZ", "YYMMDDhhmmssZ", -+ * "YYMMDDhhmmss+hh'mm'", "YYMMDDhhmmss-hh'mm'", -+ * "YYMMDDhhmm+hh'mm'", or "YYMMDDhhmm-hh'mm'". LEN != 0. -+ * -+ * value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 -+ * at 12h 00m Greenwich Mean Time -+ * -+ * GeneralizedTime: VALUE must be in one of this format: -+ * "YYYYMMDDhhmmss.sZ", "YYYYMMDDhhmmss.sZ", -+ * "YYYYMMDDhhmmss.s+hh'mm'", "YYYYMMDDhhmmss.s-hh'mm'", -+ * "YYYYMMDDhhmm+hh'mm'", or "YYYYMMDDhhmm-hh'mm'" where ss.s -+ * indicates the seconds with any precision like "10.1" or "01.02". -+ * LEN != 0 -+ * -+ * value="2001010112001.12-0700" , len=1 -> time=Jannuary -+ * 1st, 2001 at 12h 00m 01.12s Pacific Daylight Time -+ * -+ * OCTET STRING: VALUE contains the octet string and LEN is the -+ * number of octets. -+ * -+ * value="$\backslash$x01$\backslash$x02$\backslash$x03" , -+ * len=3 -> three bytes octet string -+ * -+ * GeneralString: VALUE contains the generalstring and LEN is the -+ * number of octets. -+ * -+ * value="$\backslash$x01$\backslash$x02$\backslash$x03" , -+ * len=3 -> three bytes generalstring -+ * -+ * BIT STRING: VALUE contains the bit string organized by bytes and -+ * LEN is the number of bits. -+ * -+ * value="$\backslash$xCF" , len=6 -> bit string="110011" (six -+ * bits) -+ * -+ * CHOICE: if NAME indicates a choice type, VALUE must specify one of -+ * the alternatives with a null terminated string. LEN != 0. Using -+ * "pkix.asn"\: -+ * -+ * result=asn1_write_value(cert, -+ * "certificate1.tbsCertificate.subject", "rdnSequence", -+ * 1); -+ * -+ * ANY: VALUE indicates the der encoding of a structure. LEN != 0. -+ * -+ * SEQUENCE OF: VALUE must be the null terminated string "NEW" and -+ * LEN != 0. With this instruction another element is appended in -+ * the sequence. The name of this element will be "?1" if it's the -+ * first one, "?2" for the second and so on. -+ * -+ * Using "pkix.asn"\: -+ * -+ * result=asn1_write_value(cert, -+ * "certificate1.tbsCertificate.subject.rdnSequence", "NEW", 1); -+ * -+ * SET OF: the same as SEQUENCE OF. Using "pkix.asn": -+ * -+ * result=asn1_write_value(cert, -+ * "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1); -+ * -+ * Returns: %ASN1_SUCCESS if the value was set, -+ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and -+ * %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format. -+ **/ -+int -+asn1_write_value (asn1_node node_root, const char *name, -+ const void *ivalue, int len) -+{ -+ asn1_node node, p, p2; -+ unsigned char *temp, *value_temp = NULL, *default_temp = NULL; -+ int len2, k, k2, negative; -+ size_t i; -+ const unsigned char *value = ivalue; -+ unsigned int type; -+ -+ node = asn1_find_node (node_root, name); -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ if ((node->type & CONST_OPTION) && (value == NULL) && (len == 0)) -+ { -+ asn1_delete_structure (&node); -+ return ASN1_SUCCESS; -+ } -+ -+ type = type_field (node->type); -+ -+ if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0)) -+ { -+ p = node->down; -+ while ((type_field (p->type) == ASN1_ETYPE_TAG) -+ || (type_field (p->type) == ASN1_ETYPE_SIZE)) -+ p = p->right; -+ -+ while (p->right) -+ asn1_delete_structure (&p->right); -+ -+ return ASN1_SUCCESS; -+ } -+ -+ /* Don't allow element deletion for other types */ -+ if (value == NULL) -+ { -+ return ASN1_VALUE_NOT_VALID; -+ } -+ -+ switch (type) -+ { -+ case ASN1_ETYPE_BOOLEAN: -+ if (!_asn1_strcmp (value, "TRUE")) -+ { -+ if (node->type & CONST_DEFAULT) -+ { -+ p = node->down; -+ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) -+ p = p->right; -+ if (p->type & CONST_TRUE) -+ _asn1_set_value (node, NULL, 0); -+ else -+ _asn1_set_value (node, "T", 1); -+ } -+ else -+ _asn1_set_value (node, "T", 1); -+ } -+ else if (!_asn1_strcmp (value, "FALSE")) -+ { -+ if (node->type & CONST_DEFAULT) -+ { -+ p = node->down; -+ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) -+ p = p->right; -+ if (p->type & CONST_FALSE) -+ _asn1_set_value (node, NULL, 0); -+ else -+ _asn1_set_value (node, "F", 1); -+ } -+ else -+ _asn1_set_value (node, "F", 1); -+ } -+ else -+ return ASN1_VALUE_NOT_VALID; -+ break; -+ case ASN1_ETYPE_INTEGER: -+ case ASN1_ETYPE_ENUMERATED: -+ if (len == 0) -+ { -+ if ((c_isdigit (value[0])) || (value[0] == '-')) -+ { -+ value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); -+ if (value_temp == NULL) -+ return ASN1_MEM_ALLOC_ERROR; -+ -+ _asn1_convert_integer (value, value_temp, -+ SIZEOF_UNSIGNED_LONG_INT, &len); -+ } -+ else -+ { /* is an identifier like v1 */ -+ if (!(node->type & CONST_LIST)) -+ return ASN1_VALUE_NOT_VALID; -+ p = node->down; -+ while (p) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_CONSTANT) -+ { -+ if (!_asn1_strcmp (p->name, value)) -+ { -+ value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); -+ if (value_temp == NULL) -+ return ASN1_MEM_ALLOC_ERROR; -+ -+ _asn1_convert_integer (p->value, -+ value_temp, -+ SIZEOF_UNSIGNED_LONG_INT, -+ &len); -+ break; -+ } -+ } -+ p = p->right; -+ } -+ if (p == NULL) -+ return ASN1_VALUE_NOT_VALID; -+ } -+ } -+ else -+ { /* len != 0 */ -+ value_temp = malloc (len); -+ if (value_temp == NULL) -+ return ASN1_MEM_ALLOC_ERROR; -+ memcpy (value_temp, value, len); -+ } -+ -+ if (value_temp[0] & 0x80) -+ negative = 1; -+ else -+ negative = 0; -+ -+ if (negative && (type_field (node->type) == ASN1_ETYPE_ENUMERATED)) -+ { -+ free (value_temp); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ -+ for (k = 0; k < len - 1; k++) -+ if (negative && (value_temp[k] != 0xFF)) -+ break; -+ else if (!negative && value_temp[k]) -+ break; -+ -+ if ((negative && !(value_temp[k] & 0x80)) || -+ (!negative && (value_temp[k] & 0x80))) -+ k--; -+ -+ _asn1_set_value_lv (node, value_temp + k, len - k); -+ -+ if (node->type & CONST_DEFAULT) -+ { -+ p = node->down; -+ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) -+ p = p->right; -+ if ((c_isdigit (p->value[0])) || (p->value[0] == '-')) -+ { -+ default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); -+ if (default_temp == NULL) -+ { -+ free (value_temp); -+ return ASN1_MEM_ALLOC_ERROR; -+ } -+ -+ _asn1_convert_integer (p->value, default_temp, -+ SIZEOF_UNSIGNED_LONG_INT, &len2); -+ } -+ else -+ { /* is an identifier like v1 */ -+ if (!(node->type & CONST_LIST)) -+ { -+ free (value_temp); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ p2 = node->down; -+ while (p2) -+ { -+ if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) -+ { -+ if (!_asn1_strcmp (p2->name, p->value)) -+ { -+ default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); -+ if (default_temp == NULL) -+ { -+ free (value_temp); -+ return ASN1_MEM_ALLOC_ERROR; -+ } -+ -+ _asn1_convert_integer (p2->value, -+ default_temp, -+ SIZEOF_UNSIGNED_LONG_INT, -+ &len2); -+ break; -+ } -+ } -+ p2 = p2->right; -+ } -+ if (p2 == NULL) -+ { -+ free (value_temp); -+ return ASN1_VALUE_NOT_VALID; -+ } -+ } -+ -+ -+ if ((len - k) == len2) -+ { -+ for (k2 = 0; k2 < len2; k2++) -+ if (value_temp[k + k2] != default_temp[k2]) -+ { -+ break; -+ } -+ if (k2 == len2) -+ _asn1_set_value (node, NULL, 0); -+ } -+ free (default_temp); -+ } -+ free (value_temp); -+ break; -+ case ASN1_ETYPE_OBJECT_ID: -+ for (i = 0; i < _asn1_strlen (value); i++) -+ if ((!c_isdigit (value[i])) && (value[i] != '.') && (value[i] != '+')) -+ return ASN1_VALUE_NOT_VALID; -+ if (node->type & CONST_DEFAULT) -+ { -+ p = node->down; -+ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) -+ p = p->right; -+ if (!_asn1_strcmp (value, p->value)) -+ { -+ _asn1_set_value (node, NULL, 0); -+ break; -+ } -+ } -+ _asn1_set_value (node, value, _asn1_strlen (value) + 1); -+ break; -+ case ASN1_ETYPE_UTC_TIME: -+ { -+ len = _asn1_strlen (value); -+ if (len < 11) -+ return ASN1_VALUE_NOT_VALID; -+ for (k = 0; k < 10; k++) -+ if (!c_isdigit (value[k])) -+ return ASN1_VALUE_NOT_VALID; -+ switch (len) -+ { -+ case 11: -+ if (value[10] != 'Z') -+ return ASN1_VALUE_NOT_VALID; -+ break; -+ case 13: -+ if ((!c_isdigit (value[10])) || (!c_isdigit (value[11])) || -+ (value[12] != 'Z')) -+ return ASN1_VALUE_NOT_VALID; -+ break; -+ case 15: -+ if ((value[10] != '+') && (value[10] != '-')) -+ return ASN1_VALUE_NOT_VALID; -+ for (k = 11; k < 15; k++) -+ if (!c_isdigit (value[k])) -+ return ASN1_VALUE_NOT_VALID; -+ break; -+ case 17: -+ if ((!c_isdigit (value[10])) || (!c_isdigit (value[11]))) -+ return ASN1_VALUE_NOT_VALID; -+ if ((value[12] != '+') && (value[12] != '-')) -+ return ASN1_VALUE_NOT_VALID; -+ for (k = 13; k < 17; k++) -+ if (!c_isdigit (value[k])) -+ return ASN1_VALUE_NOT_VALID; -+ break; -+ default: -+ return ASN1_VALUE_NOT_FOUND; -+ } -+ _asn1_set_value (node, value, len); -+ } -+ break; -+ case ASN1_ETYPE_GENERALIZED_TIME: -+ len = _asn1_strlen (value); -+ _asn1_set_value (node, value, len); -+ break; -+ case ASN1_ETYPE_OCTET_STRING: -+ case ASN1_ETYPE_GENERALSTRING: -+ case ASN1_ETYPE_NUMERIC_STRING: -+ case ASN1_ETYPE_IA5_STRING: -+ case ASN1_ETYPE_TELETEX_STRING: -+ case ASN1_ETYPE_PRINTABLE_STRING: -+ case ASN1_ETYPE_UNIVERSAL_STRING: -+ case ASN1_ETYPE_BMP_STRING: -+ case ASN1_ETYPE_UTF8_STRING: -+ case ASN1_ETYPE_VISIBLE_STRING: -+ if (len == 0) -+ len = _asn1_strlen (value); -+ _asn1_set_value_lv (node, value, len); -+ break; -+ case ASN1_ETYPE_BIT_STRING: -+ if (len == 0) -+ len = _asn1_strlen (value); -+ asn1_length_der ((len >> 3) + 2, NULL, &len2); -+ temp = malloc ((len >> 3) + 2 + len2); -+ if (temp == NULL) -+ return ASN1_MEM_ALLOC_ERROR; -+ -+ asn1_bit_der (value, len, temp, &len2); -+ _asn1_set_value_m (node, temp, len2); -+ temp = NULL; -+ break; -+ case ASN1_ETYPE_CHOICE: -+ p = node->down; -+ while (p) -+ { -+ if (!_asn1_strcmp (p->name, value)) -+ { -+ p2 = node->down; -+ while (p2) -+ { -+ if (p2 != p) -+ { -+ asn1_delete_structure (&p2); -+ p2 = node->down; -+ } -+ else -+ p2 = p2->right; -+ } -+ break; -+ } -+ p = p->right; -+ } -+ if (!p) -+ return ASN1_ELEMENT_NOT_FOUND; -+ break; -+ case ASN1_ETYPE_ANY: -+ _asn1_set_value_lv (node, value, len); -+ break; -+ case ASN1_ETYPE_SEQUENCE_OF: -+ case ASN1_ETYPE_SET_OF: -+ if (_asn1_strcmp (value, "NEW")) -+ return ASN1_VALUE_NOT_VALID; -+ _asn1_append_sequence_set (node, NULL); -+ break; -+ default: -+ return ASN1_ELEMENT_NOT_FOUND; -+ break; -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+#define PUT_VALUE( ptr, ptr_size, data, data_size) \ -+ *len = data_size; \ -+ if (ptr_size < data_size) { \ -+ return ASN1_MEM_ERROR; \ -+ } else { \ -+ if (ptr && data_size > 0) \ -+ memcpy (ptr, data, data_size); \ -+ } -+ -+#define PUT_STR_VALUE( ptr, ptr_size, data) \ -+ *len = _asn1_strlen (data) + 1; \ -+ if (ptr_size < *len) { \ -+ return ASN1_MEM_ERROR; \ -+ } else { \ -+ /* this strcpy is checked */ \ -+ if (ptr) { \ -+ _asn1_strcpy (ptr, data); \ -+ } \ -+ } -+ -+#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \ -+ *len = data_size + 1; \ -+ if (ptr_size < *len) { \ -+ return ASN1_MEM_ERROR; \ -+ } else { \ -+ /* this strcpy is checked */ \ -+ if (ptr) { \ -+ if (data_size > 0) \ -+ memcpy (ptr, data, data_size); \ -+ ptr[data_size] = 0; \ -+ } \ -+ } -+ -+#define ADD_STR_VALUE( ptr, ptr_size, data) \ -+ *len += _asn1_strlen(data); \ -+ if (ptr_size < (int) *len) { \ -+ (*len)++; \ -+ return ASN1_MEM_ERROR; \ -+ } else { \ -+ /* this strcat is checked */ \ -+ if (ptr) _asn1_strcat (ptr, data); \ -+ } -+ -+/** -+ * asn1_read_value: -+ * @root: pointer to a structure. -+ * @name: the name of the element inside a structure that you want to read. -+ * @ivalue: vector that will contain the element's content, must be a -+ * pointer to memory cells already allocated (may be %NULL). -+ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy -+ * holds the sizeof value. -+ * -+ * Returns the value of one element inside a structure. -+ * If an element is OPTIONAL and this returns -+ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present -+ * in the der encoding that created the structure. The first element -+ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and -+ * so on. If the @root provided is a node to specific sequence element, -+ * then the keyword "?CURRENT" is also acceptable and indicates the -+ * current sequence element of this node. -+ * -+ * Note that there can be valid values with length zero. In these case -+ * this function will succeed and @len will be zero. -+ * -+ * INTEGER: VALUE will contain a two's complement form integer. -+ * -+ * integer=-1 -> value[0]=0xFF , len=1. -+ * integer=1 -> value[0]=0x01 , len=1. -+ * -+ * ENUMERATED: As INTEGER (but only with not negative numbers). -+ * -+ * BOOLEAN: VALUE will be the null terminated string "TRUE" or -+ * "FALSE" and LEN=5 or LEN=6. -+ * -+ * OBJECT IDENTIFIER: VALUE will be a null terminated string with -+ * each number separated by a dot (i.e. "1.2.3.543.1"). -+ * -+ * LEN = strlen(VALUE)+1 -+ * -+ * UTCTime: VALUE will be a null terminated string in one of these -+ * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'". -+ * LEN=strlen(VALUE)+1. -+ * -+ * GeneralizedTime: VALUE will be a null terminated string in the -+ * same format used to set the value. -+ * -+ * OCTET STRING: VALUE will contain the octet string and LEN will be -+ * the number of octets. -+ * -+ * GeneralString: VALUE will contain the generalstring and LEN will -+ * be the number of octets. -+ * -+ * BIT STRING: VALUE will contain the bit string organized by bytes -+ * and LEN will be the number of bits. -+ * -+ * CHOICE: If NAME indicates a choice type, VALUE will specify the -+ * alternative selected. -+ * -+ * ANY: If NAME indicates an any type, VALUE will indicate the DER -+ * encoding of the structure actually used. -+ * -+ * Returns: %ASN1_SUCCESS if value is returned, -+ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, -+ * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element -+ * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough -+ * to store the result, and in this case @len will contain the number of -+ * bytes needed. On the occasion that the stored data are of zero-length -+ * this function may return %ASN1_SUCCESS even if the provided @len is zero. -+ **/ -+int -+asn1_read_value (asn1_node_const root, const char *name, void *ivalue, int *len) -+{ -+ return asn1_read_value_type (root, name, ivalue, len, NULL); -+} -+ -+/** -+ * asn1_read_value_type: -+ * @root: pointer to a structure. -+ * @name: the name of the element inside a structure that you want to read. -+ * @ivalue: vector that will contain the element's content, must be a -+ * pointer to memory cells already allocated (may be %NULL). -+ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy -+ * holds the sizeof value. -+ * @etype: The type of the value read (ASN1_ETYPE) -+ * -+ * Returns the type and value of one element inside a structure. -+ * If an element is OPTIONAL and this returns -+ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present -+ * in the der encoding that created the structure. The first element -+ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and -+ * so on. If the @root provided is a node to specific sequence element, -+ * then the keyword "?CURRENT" is also acceptable and indicates the -+ * current sequence element of this node. -+ * -+ * Note that there can be valid values with length zero. In these case -+ * this function will succeed and @len will be zero. -+ * -+ * -+ * INTEGER: VALUE will contain a two's complement form integer. -+ * -+ * integer=-1 -> value[0]=0xFF , len=1. -+ * integer=1 -> value[0]=0x01 , len=1. -+ * -+ * ENUMERATED: As INTEGER (but only with not negative numbers). -+ * -+ * BOOLEAN: VALUE will be the null terminated string "TRUE" or -+ * "FALSE" and LEN=5 or LEN=6. -+ * -+ * OBJECT IDENTIFIER: VALUE will be a null terminated string with -+ * each number separated by a dot (i.e. "1.2.3.543.1"). -+ * -+ * LEN = strlen(VALUE)+1 -+ * -+ * UTCTime: VALUE will be a null terminated string in one of these -+ * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'". -+ * LEN=strlen(VALUE)+1. -+ * -+ * GeneralizedTime: VALUE will be a null terminated string in the -+ * same format used to set the value. -+ * -+ * OCTET STRING: VALUE will contain the octet string and LEN will be -+ * the number of octets. -+ * -+ * GeneralString: VALUE will contain the generalstring and LEN will -+ * be the number of octets. -+ * -+ * BIT STRING: VALUE will contain the bit string organized by bytes -+ * and LEN will be the number of bits. -+ * -+ * CHOICE: If NAME indicates a choice type, VALUE will specify the -+ * alternative selected. -+ * -+ * ANY: If NAME indicates an any type, VALUE will indicate the DER -+ * encoding of the structure actually used. -+ * -+ * Returns: %ASN1_SUCCESS if value is returned, -+ * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, -+ * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element -+ * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough -+ * to store the result, and in this case @len will contain the number of -+ * bytes needed. On the occasion that the stored data are of zero-length -+ * this function may return %ASN1_SUCCESS even if the provided @len is zero. -+ **/ -+int -+asn1_read_value_type (asn1_node_const root, const char *name, void *ivalue, -+ int *len, unsigned int *etype) -+{ -+ asn1_node_const node, p, p2; -+ int len2, len3, result; -+ int value_size = *len; -+ unsigned char *value = ivalue; -+ unsigned type; -+ -+ node = asn1_find_node (root, name); -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ type = type_field (node->type); -+ -+ if ((type != ASN1_ETYPE_NULL) && -+ (type != ASN1_ETYPE_CHOICE) && -+ !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) && -+ (node->value == NULL)) -+ return ASN1_VALUE_NOT_FOUND; -+ -+ if (etype) -+ *etype = type; -+ switch (type) -+ { -+ case ASN1_ETYPE_NULL: -+ PUT_STR_VALUE (value, value_size, "NULL"); -+ break; -+ case ASN1_ETYPE_BOOLEAN: -+ if ((node->type & CONST_DEFAULT) && (node->value == NULL)) -+ { -+ p = node->down; -+ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) -+ p = p->right; -+ if (p->type & CONST_TRUE) -+ { -+ PUT_STR_VALUE (value, value_size, "TRUE"); -+ } -+ else -+ { -+ PUT_STR_VALUE (value, value_size, "FALSE"); -+ } -+ } -+ else if (node->value[0] == 'T') -+ { -+ PUT_STR_VALUE (value, value_size, "TRUE"); -+ } -+ else -+ { -+ PUT_STR_VALUE (value, value_size, "FALSE"); -+ } -+ break; -+ case ASN1_ETYPE_INTEGER: -+ case ASN1_ETYPE_ENUMERATED: -+ if ((node->type & CONST_DEFAULT) && (node->value == NULL)) -+ { -+ p = node->down; -+ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) -+ p = p->right; -+ if ((c_isdigit (p->value[0])) || (p->value[0] == '-') -+ || (p->value[0] == '+')) -+ { -+ result = _asn1_convert_integer -+ (p->value, value, value_size, len); -+ if (result != ASN1_SUCCESS) -+ return result; -+ } -+ else -+ { /* is an identifier like v1 */ -+ p2 = node->down; -+ while (p2) -+ { -+ if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) -+ { -+ if (!_asn1_strcmp (p2->name, p->value)) -+ { -+ result = _asn1_convert_integer -+ (p2->value, value, value_size, -+ len); -+ if (result != ASN1_SUCCESS) -+ return result; -+ break; -+ } -+ } -+ p2 = p2->right; -+ } -+ } -+ } -+ else -+ { -+ len2 = -1; -+ result = asn1_get_octet_der -+ (node->value, node->value_len, &len2, value, value_size, -+ len); -+ if (result != ASN1_SUCCESS) -+ return result; -+ } -+ break; -+ case ASN1_ETYPE_OBJECT_ID: -+ if (node->type & CONST_ASSIGN) -+ { -+ *len = 0; -+ if (value) -+ value[0] = 0; -+ p = node->down; -+ while (p) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_CONSTANT) -+ { -+ ADD_STR_VALUE (value, value_size, p->value); -+ if (p->right) -+ { -+ ADD_STR_VALUE (value, value_size, "."); -+ } -+ } -+ p = p->right; -+ } -+ (*len)++; -+ } -+ else if ((node->type & CONST_DEFAULT) && (node->value == NULL)) -+ { -+ p = node->down; -+ while (type_field (p->type) != ASN1_ETYPE_DEFAULT) -+ p = p->right; -+ PUT_STR_VALUE (value, value_size, p->value); -+ } -+ else -+ { -+ PUT_STR_VALUE (value, value_size, node->value); -+ } -+ break; -+ case ASN1_ETYPE_GENERALIZED_TIME: -+ case ASN1_ETYPE_UTC_TIME: -+ PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len); -+ break; -+ case ASN1_ETYPE_OCTET_STRING: -+ case ASN1_ETYPE_GENERALSTRING: -+ case ASN1_ETYPE_NUMERIC_STRING: -+ case ASN1_ETYPE_IA5_STRING: -+ case ASN1_ETYPE_TELETEX_STRING: -+ case ASN1_ETYPE_PRINTABLE_STRING: -+ case ASN1_ETYPE_UNIVERSAL_STRING: -+ case ASN1_ETYPE_BMP_STRING: -+ case ASN1_ETYPE_UTF8_STRING: -+ case ASN1_ETYPE_VISIBLE_STRING: -+ len2 = -1; -+ result = asn1_get_octet_der -+ (node->value, node->value_len, &len2, value, value_size, -+ len); -+ if (result != ASN1_SUCCESS) -+ return result; -+ break; -+ case ASN1_ETYPE_BIT_STRING: -+ len2 = -1; -+ result = asn1_get_bit_der -+ (node->value, node->value_len, &len2, value, value_size, -+ len); -+ if (result != ASN1_SUCCESS) -+ return result; -+ break; -+ case ASN1_ETYPE_CHOICE: -+ PUT_STR_VALUE (value, value_size, node->down->name); -+ break; -+ case ASN1_ETYPE_ANY: -+ len3 = -1; -+ len2 = asn1_get_length_der (node->value, node->value_len, &len3); -+ if (len2 < 0) -+ return ASN1_DER_ERROR; -+ PUT_VALUE (value, value_size, node->value + len3, len2); -+ break; -+ default: -+ return ASN1_ELEMENT_NOT_FOUND; -+ break; -+ } -+ return ASN1_SUCCESS; -+} -+ -+ -+/** -+ * asn1_read_tag: -+ * @root: pointer to a structure -+ * @name: the name of the element inside a structure. -+ * @tagValue: variable that will contain the TAG value. -+ * @classValue: variable that will specify the TAG type. -+ * -+ * Returns the TAG and the CLASS of one element inside a structure. -+ * CLASS can have one of these constants: %ASN1_CLASS_APPLICATION, -+ * %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or -+ * %ASN1_CLASS_CONTEXT_SPECIFIC. -+ * -+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if -+ * @name is not a valid element. -+ **/ -+int -+asn1_read_tag (asn1_node_const root, const char *name, int *tagValue, -+ int *classValue) -+{ -+ asn1_node node, p, pTag; -+ -+ node = asn1_find_node (root, name); -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node->down; -+ -+ /* pTag will points to the IMPLICIT TAG */ -+ pTag = NULL; -+ if (node->type & CONST_TAG) -+ { -+ while (p) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_TAG) -+ { -+ if ((p->type & CONST_IMPLICIT) && (pTag == NULL)) -+ pTag = p; -+ else if (p->type & CONST_EXPLICIT) -+ pTag = NULL; -+ } -+ p = p->right; -+ } -+ } -+ -+ if (pTag) -+ { -+ *tagValue = _asn1_strtoul (pTag->value, NULL, 10); -+ -+ if (pTag->type & CONST_APPLICATION) -+ *classValue = ASN1_CLASS_APPLICATION; -+ else if (pTag->type & CONST_UNIVERSAL) -+ *classValue = ASN1_CLASS_UNIVERSAL; -+ else if (pTag->type & CONST_PRIVATE) -+ *classValue = ASN1_CLASS_PRIVATE; -+ else -+ *classValue = ASN1_CLASS_CONTEXT_SPECIFIC; -+ } -+ else -+ { -+ unsigned type = type_field (node->type); -+ *classValue = ASN1_CLASS_UNIVERSAL; -+ -+ switch (type) -+ { -+ CASE_HANDLED_ETYPES: -+ *tagValue = _asn1_tags[type].tag; -+ break; -+ case ASN1_ETYPE_TAG: -+ case ASN1_ETYPE_CHOICE: -+ case ASN1_ETYPE_ANY: -+ *tagValue = -1; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+/** -+ * asn1_read_node_value: -+ * @node: pointer to a node. -+ * @data: a point to a asn1_data_node_st -+ * -+ * Returns the value a data node inside a asn1_node structure. -+ * The data returned should be handled as constant values. -+ * -+ * Returns: %ASN1_SUCCESS if the node exists. -+ **/ -+int -+asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data) -+{ -+ data->name = node->name; -+ data->value = node->value; -+ data->value_len = node->value_len; -+ data->type = type_field (node->type); -+ -+ return ASN1_SUCCESS; -+} -diff --git a/grub-core/lib/libtasn1/lib/errors.c b/grub-core/lib/libtasn1/lib/errors.c -new file mode 100644 -index 00000000000..cee74daf795 ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/errors.c -@@ -0,0 +1,100 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#include -+#ifdef STDC_HEADERS -+#include -+#endif -+ -+#define LIBTASN1_ERROR_ENTRY(name) { #name, name } -+ -+struct libtasn1_error_entry -+{ -+ const char *name; -+ int number; -+}; -+typedef struct libtasn1_error_entry libtasn1_error_entry; -+ -+static const libtasn1_error_entry error_algorithms[] = { -+ LIBTASN1_ERROR_ENTRY (ASN1_SUCCESS), -+ LIBTASN1_ERROR_ENTRY (ASN1_FILE_NOT_FOUND), -+ LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_FOUND), -+ LIBTASN1_ERROR_ENTRY (ASN1_IDENTIFIER_NOT_FOUND), -+ LIBTASN1_ERROR_ENTRY (ASN1_DER_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_FOUND), -+ LIBTASN1_ERROR_ENTRY (ASN1_GENERIC_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_VALID), -+ LIBTASN1_ERROR_ENTRY (ASN1_TAG_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_TAG_IMPLICIT), -+ LIBTASN1_ERROR_ENTRY (ASN1_ERROR_TYPE_ANY), -+ LIBTASN1_ERROR_ENTRY (ASN1_SYNTAX_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_MEM_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_MEM_ALLOC_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_DER_OVERFLOW), -+ LIBTASN1_ERROR_ENTRY (ASN1_NAME_TOO_LONG), -+ LIBTASN1_ERROR_ENTRY (ASN1_ARRAY_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_EMPTY), -+ LIBTASN1_ERROR_ENTRY (ASN1_TIME_ENCODING_ERROR), -+ LIBTASN1_ERROR_ENTRY (ASN1_RECURSION), -+ {0, 0} -+}; -+ -+/** -+ * asn1_perror: -+ * @error: is an error returned by a libtasn1 function. -+ * -+ * Prints a string to stderr with a description of an error. This -+ * function is like perror(). The only difference is that it accepts -+ * an error returned by a libtasn1 function. -+ * -+ * Since: 1.6 -+ **/ -+void -+asn1_perror (int error) -+{ -+ const char *str = asn1_strerror (error); -+ fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)"); -+} -+ -+/** -+ * asn1_strerror: -+ * @error: is an error returned by a libtasn1 function. -+ * -+ * Returns a string with a description of an error. This function is -+ * similar to strerror. The only difference is that it accepts an -+ * error (number) returned by a libtasn1 function. -+ * -+ * Returns: Pointer to static zero-terminated string describing error -+ * code. -+ * -+ * Since: 1.6 -+ **/ -+const char * -+asn1_strerror (int error) -+{ -+ const libtasn1_error_entry *p; -+ -+ for (p = error_algorithms; p->name != NULL; p++) -+ if (p->number == error) -+ return p->name + sizeof ("ASN1_") - 1; -+ -+ return NULL; -+} -diff --git a/grub-core/lib/libtasn1/lib/gstr.c b/grub-core/lib/libtasn1/lib/gstr.c -new file mode 100644 -index 00000000000..e91a3a151c0 ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/gstr.c -@@ -0,0 +1,74 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#include -+#include "gstr.h" -+ -+/* These function are like strcat, strcpy. They only -+ * do bounds checking (they shouldn't cause buffer overruns), -+ * and they always produce null terminated strings. -+ * -+ * They should be used only with null terminated strings. -+ */ -+void -+_asn1_str_cat (char *dest, size_t dest_tot_size, const char *src) -+{ -+ size_t str_size = strlen (src); -+ size_t dest_size = strlen (dest); -+ -+ if (dest_tot_size - dest_size > str_size) -+ { -+ strcat (dest, src); -+ } -+ else -+ { -+ if (dest_tot_size - dest_size > 0) -+ { -+ strncat (dest, src, (dest_tot_size - dest_size) - 1); -+ dest[dest_tot_size - 1] = 0; -+ } -+ } -+} -+ -+/* Returns the bytes copied (not including the null terminator) */ -+unsigned int -+_asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src) -+{ -+ size_t str_size = strlen (src); -+ -+ if (dest_tot_size > str_size) -+ { -+ strcpy (dest, src); -+ return str_size; -+ } -+ else -+ { -+ if (dest_tot_size > 0) -+ { -+ str_size = dest_tot_size - 1; -+ memcpy (dest, src, str_size); -+ dest[str_size] = 0; -+ return str_size; -+ } -+ else -+ return 0; -+ } -+} -diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c b/grub-core/lib/libtasn1/lib/parser_aux.c -new file mode 100644 -index 00000000000..d5dbbf8765d ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/parser_aux.c -@@ -0,0 +1,1173 @@ -+/* -+ * Copyright (C) 2000-2016 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#include // WORD_BIT -+ -+#include "int.h" -+#include "parser_aux.h" -+#include "gstr.h" -+#include "structure.h" -+#include "element.h" -+#include "c-ctype.h" -+ -+char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not found */ -+ -+/* Return a hash of the N bytes of X using the method described by -+ Bruno Haible in https://www.haible.de/bruno/hashfunc.html. -+ Note that while many hash functions reduce their result via modulo -+ to a 0..table_size-1 range, this function does not do that. -+ -+ This implementation has been changed from size_t -> unsigned int. */ -+ -+#ifdef __clang__ -+__attribute__((no_sanitize("integer"))) -+#endif -+_GL_ATTRIBUTE_PURE -+static unsigned int -+_asn1_hash_name (const char *x) -+{ -+ const unsigned char *s = (unsigned char *) x; -+ unsigned h = 0; -+ -+ while (*s) -+ h = (*s++) + ((h << 9) | (h >> (WORD_BIT - 9))); -+ -+ return h; -+} -+ -+/******************************************************/ -+/* Function : _asn1_add_static_node */ -+/* Description: creates a new NODE_ASN element and */ -+/* puts it in the list pointed by e_list. */ -+/* Parameters: */ -+/* e_list: of type list_type; must be NULL initially */ -+/* type: type of the new element (see ASN1_ETYPE_ */ -+/* and CONST_ constants). */ -+/* Return: pointer to the new element. */ -+/******************************************************/ -+asn1_node -+_asn1_add_static_node (list_type **e_list, unsigned int type) -+{ -+ list_type *p; -+ asn1_node punt; -+ -+ punt = calloc (1, sizeof (struct asn1_node_st)); -+ if (punt == NULL) -+ return NULL; -+ -+ p = malloc (sizeof (list_type)); -+ if (p == NULL) -+ { -+ free (punt); -+ return NULL; -+ } -+ -+ p->node = punt; -+ p->next = *e_list; -+ *e_list = p; -+ -+ punt->type = type; -+ -+ return punt; -+} -+ -+static -+int _asn1_add_static_node2 (list_type **e_list, asn1_node node) -+{ -+ list_type *p; -+ -+ p = malloc (sizeof (list_type)); -+ if (p == NULL) -+ { -+ return -1; -+ } -+ -+ p->node = node; -+ p->next = *e_list; -+ *e_list = p; -+ -+ return 0; -+} -+ -+/** -+ * asn1_find_node: -+ * @pointer: NODE_ASN element pointer. -+ * @name: null terminated string with the element's name to find. -+ * -+ * Searches for an element called @name starting from @pointer. The -+ * name is composed by different identifiers separated by dots. When -+ * *@pointer has a name, the first identifier must be the name of -+ * *@pointer, otherwise it must be the name of one child of *@pointer. -+ * -+ * Returns: the search result, or %NULL if not found. -+ **/ -+asn1_node -+asn1_find_node (asn1_node_const pointer, const char *name) -+{ -+ asn1_node_const p; -+ char *n_end, n[ASN1_MAX_NAME_SIZE + 1]; -+ const char *n_start; -+ unsigned int nsize; -+ unsigned int nhash; -+ -+ if (pointer == NULL) -+ return NULL; -+ -+ if (name == NULL) -+ return NULL; -+ -+ p = pointer; -+ n_start = name; -+ -+ if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?') -+ { /* ?CURRENT */ -+ n_start = strchr(n_start, '.'); -+ if (n_start) -+ n_start++; -+ } -+ else if (p->name[0] != 0) -+ { /* has *pointer got a name ? */ -+ n_end = strchr (n_start, '.'); /* search the first dot */ -+ if (n_end) -+ { -+ nsize = n_end - n_start; -+ if (nsize >= sizeof(n)) -+ return NULL; -+ -+ memcpy (n, n_start, nsize); -+ n[nsize] = 0; -+ n_start = n_end; -+ n_start++; -+ -+ nhash = _asn1_hash_name (n); -+ } -+ else -+ { -+ _asn1_str_cpy (n, sizeof (n), n_start); -+ nhash = _asn1_hash_name (n); -+ -+ n_start = NULL; -+ } -+ -+ while (p) -+ { -+ if (nhash == p->name_hash && (!strcmp (p->name, n))) -+ break; -+ else -+ p = p->right; -+ } /* while */ -+ -+ if (p == NULL) -+ return NULL; -+ } -+ else -+ { /* *pointer doesn't have a name */ -+ if (n_start[0] == 0) -+ return (asn1_node) p; -+ } -+ -+ while (n_start) -+ { /* Has the end of NAME been reached? */ -+ n_end = strchr (n_start, '.'); /* search the next dot */ -+ if (n_end) -+ { -+ nsize = n_end - n_start; -+ if (nsize >= sizeof(n)) -+ return NULL; -+ -+ memcpy (n, n_start, nsize); -+ n[nsize] = 0; -+ n_start = n_end; -+ n_start++; -+ -+ nhash = _asn1_hash_name (n); -+ } -+ else -+ { -+ _asn1_str_cpy (n, sizeof (n), n_start); -+ nhash = _asn1_hash_name (n); -+ n_start = NULL; -+ } -+ -+ if (p->down == NULL) -+ return NULL; -+ -+ p = p->down; -+ if (p == NULL) -+ return NULL; -+ -+ /* The identifier "?LAST" indicates the last element -+ in the right chain. */ -+ if (n[0] == '?' && n[1] == 'L') /* ?LAST */ -+ { -+ while (p->right) -+ p = p->right; -+ } -+ else -+ { /* no "?LAST" */ -+ while (p) -+ { -+ if (p->name_hash == nhash && !strcmp (p->name, n)) -+ break; -+ else -+ p = p->right; -+ } -+ } -+ if (p == NULL) -+ return NULL; -+ } /* while */ -+ -+ return (asn1_node) p; -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_set_value */ -+/* Description: sets the field VALUE in a NODE_ASN element. The */ -+/* previous value (if exist) will be lost */ -+/* Parameters: */ -+/* node: element pointer. */ -+/* value: pointer to the value that you want to set. */ -+/* len: character number of value. */ -+/* Return: pointer to the NODE_ASN element. */ -+/******************************************************************/ -+asn1_node -+_asn1_set_value (asn1_node node, const void *value, unsigned int len) -+{ -+ if (node == NULL) -+ return node; -+ if (node->value) -+ { -+ if (node->value != node->small_value) -+ free (node->value); -+ node->value = NULL; -+ node->value_len = 0; -+ } -+ -+ if (!len) -+ return node; -+ -+ if (len < sizeof (node->small_value)) -+ { -+ node->value = node->small_value; -+ } -+ else -+ { -+ node->value = malloc (len); -+ if (node->value == NULL) -+ return NULL; -+ } -+ node->value_len = len; -+ -+ memcpy (node->value, value, len); -+ return node; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_set_value_lv */ -+/* Description: sets the field VALUE in a NODE_ASN element. The */ -+/* previous value (if exist) will be lost. The value */ -+/* given is stored as an length-value format (LV */ -+/* Parameters: */ -+/* node: element pointer. */ -+/* value: pointer to the value that you want to set. */ -+/* len: character number of value. */ -+/* Return: pointer to the NODE_ASN element. */ -+/******************************************************************/ -+asn1_node -+_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len) -+{ -+ int len2; -+ void *temp; -+ -+ if (node == NULL) -+ return node; -+ -+ asn1_length_der (len, NULL, &len2); -+ temp = malloc (len + len2); -+ if (temp == NULL) -+ return NULL; -+ -+ asn1_octet_der (value, len, temp, &len2); -+ return _asn1_set_value_m (node, temp, len2); -+} -+ -+/* the same as _asn1_set_value except that it sets an already malloc'ed -+ * value. -+ */ -+asn1_node -+_asn1_set_value_m (asn1_node node, void *value, unsigned int len) -+{ -+ if (node == NULL) -+ return node; -+ -+ if (node->value) -+ { -+ if (node->value != node->small_value) -+ free (node->value); -+ node->value = NULL; -+ node->value_len = 0; -+ } -+ -+ if (!len) -+ return node; -+ -+ node->value = value; -+ node->value_len = len; -+ -+ return node; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_append_value */ -+/* Description: appends to the field VALUE in a NODE_ASN element. */ -+/* */ -+/* Parameters: */ -+/* node: element pointer. */ -+/* value: pointer to the value that you want to be appended. */ -+/* len: character number of value. */ -+/* Return: pointer to the NODE_ASN element. */ -+/******************************************************************/ -+asn1_node -+_asn1_append_value (asn1_node node, const void *value, unsigned int len) -+{ -+ if (node == NULL) -+ return node; -+ -+ if (node->value == NULL) -+ return _asn1_set_value (node, value, len); -+ -+ if (len == 0) -+ return node; -+ -+ if (node->value == node->small_value) -+ { -+ /* value is in node */ -+ int prev_len = node->value_len; -+ node->value_len += len; -+ node->value = malloc (node->value_len); -+ if (node->value == NULL) -+ { -+ node->value_len = 0; -+ return NULL; -+ } -+ -+ if (prev_len > 0) -+ memcpy (node->value, node->small_value, prev_len); -+ -+ memcpy (&node->value[prev_len], value, len); -+ -+ return node; -+ } -+ else /* if (node->value != NULL && node->value != node->small_value) */ -+ { -+ /* value is allocated */ -+ int prev_len = node->value_len; -+ node->value_len += len; -+ -+ node->value = _asn1_realloc (node->value, node->value_len); -+ if (node->value == NULL) -+ { -+ node->value_len = 0; -+ return NULL; -+ } -+ -+ memcpy (&node->value[prev_len], value, len); -+ -+ return node; -+ } -+} -+ -+/******************************************************************/ -+/* Function : _asn1_set_name */ -+/* Description: sets the field NAME in a NODE_ASN element. The */ -+/* previous value (if exist) will be lost */ -+/* Parameters: */ -+/* node: element pointer. */ -+/* name: a null terminated string with the name that you want */ -+/* to set. */ -+/* Return: pointer to the NODE_ASN element. */ -+/******************************************************************/ -+asn1_node -+_asn1_set_name (asn1_node node, const char *name) -+{ -+ if (node == NULL) -+ return node; -+ -+ _asn1_str_cpy (node->name, sizeof (node->name), name ? name : ""); -+ node->name_hash = _asn1_hash_name (node->name); -+ -+ return node; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_cpy_name */ -+/* Description: copies the field NAME in a NODE_ASN element. */ -+/* Parameters: */ -+/* dst: a dest element pointer. */ -+/* src: a source element pointer. */ -+/* Return: pointer to the NODE_ASN element. */ -+/******************************************************************/ -+asn1_node -+_asn1_cpy_name (asn1_node dst, asn1_node_const src) -+{ -+ if (dst == NULL) -+ return dst; -+ -+ if (src == NULL) -+ { -+ dst->name[0] = 0; -+ dst->name_hash = _asn1_hash_name (dst->name); -+ return dst; -+ } -+ -+ _asn1_str_cpy (dst->name, sizeof (dst->name), src->name); -+ dst->name_hash = src->name_hash; -+ -+ return dst; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_set_right */ -+/* Description: sets the field RIGHT in a NODE_ASN element. */ -+/* Parameters: */ -+/* node: element pointer. */ -+/* right: pointer to a NODE_ASN element that you want be pointed*/ -+/* by NODE. */ -+/* Return: pointer to *NODE. */ -+/******************************************************************/ -+asn1_node -+_asn1_set_right (asn1_node node, asn1_node right) -+{ -+ if (node == NULL) -+ return node; -+ node->right = right; -+ if (right) -+ right->left = node; -+ return node; -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_get_last_right */ -+/* Description: return the last element along the right chain. */ -+/* Parameters: */ -+/* node: starting element pointer. */ -+/* Return: pointer to the last element along the right chain. */ -+/******************************************************************/ -+asn1_node -+_asn1_get_last_right (asn1_node_const node) -+{ -+ asn1_node_const p; -+ -+ if (node == NULL) -+ return NULL; -+ p = node; -+ while (p->right) -+ p = p->right; -+ return (asn1_node) p; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_remove_node */ -+/* Description: gets free the memory allocated for an NODE_ASN */ -+/* element (not the elements pointed by it). */ -+/* Parameters: */ -+/* node: NODE_ASN element pointer. */ -+/* flags: ASN1_DELETE_FLAG_* */ -+/******************************************************************/ -+void -+_asn1_remove_node (asn1_node node, unsigned int flags) -+{ -+ if (node == NULL) -+ return; -+ -+ if (node->value != NULL) -+ { -+ if (flags & ASN1_DELETE_FLAG_ZEROIZE) -+ { -+ safe_memset(node->value, 0, node->value_len); -+ } -+ -+ if (node->value != node->small_value) -+ free (node->value); -+ } -+ free (node); -+} -+ -+/******************************************************************/ -+/* Function : _asn1_find_up */ -+/* Description: return the father of the NODE_ASN element. */ -+/* Parameters: */ -+/* node: NODE_ASN element pointer. */ -+/* Return: Null if not found. */ -+/******************************************************************/ -+asn1_node -+_asn1_find_up (asn1_node_const node) -+{ -+ asn1_node_const p; -+ -+ if (node == NULL) -+ return NULL; -+ -+ p = node; -+ -+ while ((p->left != NULL) && (p->left->right == p)) -+ p = p->left; -+ -+ return p->left; -+} -+ -+static -+unsigned _asn1_is_up (asn1_node_const up_cand, asn1_node_const down) -+{ -+ asn1_node_const d, u; -+ -+ if (up_cand == NULL || down == NULL) -+ return 0; -+ -+ d = down; -+ -+ while ((u = _asn1_find_up(d)) != NULL && u != d) -+ { -+ if (u == up_cand) -+ return 1; -+ d = u; -+ } -+ -+ return 0; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_delete_node_from_list */ -+/* Description: deletes the list element given */ -+/******************************************************************/ -+void -+_asn1_delete_node_from_list (list_type *list, asn1_node node) -+{ -+ list_type *p = list; -+ -+ while (p) -+ { -+ if (p->node == node) -+ p->node = NULL; -+ p = p->next; -+ } -+} -+ -+/******************************************************************/ -+/* Function : _asn1_delete_list */ -+/* Description: deletes the list elements (not the elements */ -+/* pointed by them). */ -+/******************************************************************/ -+void -+_asn1_delete_list (list_type *e_list) -+{ -+ list_type *p; -+ -+ while (e_list) -+ { -+ p = e_list; -+ e_list = e_list->next; -+ free (p); -+ } -+} -+ -+/******************************************************************/ -+/* Function : _asn1_delete_list_and nodes */ -+/* Description: deletes the list elements and the elements */ -+/* pointed by them. */ -+/******************************************************************/ -+void -+_asn1_delete_list_and_nodes (list_type *e_list) -+{ -+ list_type *p; -+ -+ while (e_list) -+ { -+ p = e_list; -+ e_list = e_list->next; -+ _asn1_remove_node (p->node, 0); -+ free (p); -+ } -+} -+ -+ -+char * -+_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]) -+{ -+ uint64_t d, r; -+ char temp[LTOSTR_MAX_SIZE]; -+ int count, k, start; -+ uint64_t val; -+ -+ if (v < 0) -+ { -+ str[0] = '-'; -+ start = 1; -+ val = -((uint64_t)v); -+ } -+ else -+ { -+ val = v; -+ start = 0; -+ } -+ -+ count = 0; -+ do -+ { -+ d = val / 10; -+ r = val - d * 10; -+ temp[start + count] = '0' + (char) r; -+ count++; -+ val = d; -+ } -+ while (val && ((start+count) < LTOSTR_MAX_SIZE-1)); -+ -+ for (k = 0; k < count; k++) -+ str[k + start] = temp[start + count - k - 1]; -+ str[count + start] = 0; -+ return str; -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_change_integer_value */ -+/* Description: converts into DER coding the value assign to an */ -+/* INTEGER constant. */ -+/* Parameters: */ -+/* node: root of an ASN1element. */ -+/* Return: */ -+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ -+/* otherwise ASN1_SUCCESS */ -+/******************************************************************/ -+int -+_asn1_change_integer_value (asn1_node node) -+{ -+ asn1_node p; -+ unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; -+ unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1]; -+ int len; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node; -+ while (p) -+ { -+ if ((type_field (p->type) == ASN1_ETYPE_INTEGER) -+ && (p->type & CONST_ASSIGN)) -+ { -+ if (p->value) -+ { -+ _asn1_convert_integer (p->value, val, sizeof (val), &len); -+ asn1_octet_der (val, len, val2, &len); -+ _asn1_set_value (p, val2, len); -+ } -+ } -+ -+ if (p->down) -+ { -+ p = p->down; -+ } -+ else -+ { -+ if (p == node) -+ p = NULL; -+ else if (p->right) -+ p = p->right; -+ else -+ { -+ while (1) -+ { -+ p = _asn1_find_up (p); -+ if (p == node) -+ { -+ p = NULL; -+ break; -+ } -+ if (p && p->right) -+ { -+ p = p->right; -+ break; -+ } -+ } -+ } -+ } -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+#define MAX_CONSTANTS 1024 -+/******************************************************************/ -+/* Function : _asn1_expand_object_id */ -+/* Description: expand the IDs of an OBJECT IDENTIFIER constant. */ -+/* Parameters: */ -+/* list: root of an object list */ -+/* node: root of an ASN1 element. */ -+/* Return: */ -+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ -+/* otherwise ASN1_SUCCESS */ -+/******************************************************************/ -+int -+_asn1_expand_object_id (list_type **list, asn1_node node) -+{ -+ asn1_node p, p2, p3, p4, p5; -+ char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1]; -+ int move, tlen, tries; -+ unsigned max_constants; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ _asn1_str_cpy (name_root, sizeof (name_root), node->name); -+ -+ p = node; -+ move = DOWN; -+ tries = 0; -+ -+ while (!((p == node) && (move == UP))) -+ { -+ if (move != UP) -+ { -+ if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) -+ && (p->type & CONST_ASSIGN)) -+ { -+ p2 = p->down; -+ if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) -+ { -+ if (p2->value && !c_isdigit (p2->value[0])) -+ { -+ _asn1_str_cpy (name2, sizeof (name2), name_root); -+ _asn1_str_cat (name2, sizeof (name2), "."); -+ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); -+ p3 = asn1_find_node (node, name2); -+ if (!p3 || _asn1_is_up(p2, p3) || -+ (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || -+ !(p3->type & CONST_ASSIGN)) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ _asn1_set_down (p, p2->right); -+ if (p2->down) -+ _asn1_delete_structure (*list, &p2->down, 0); -+ _asn1_delete_node_from_list(*list, p2); -+ _asn1_remove_node (p2, 0); -+ p2 = p; -+ p4 = p3->down; -+ max_constants = 0; -+ while (p4) -+ { -+ if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) -+ { -+ max_constants++; -+ if (max_constants == MAX_CONSTANTS) -+ return ASN1_RECURSION; -+ -+ p5 = -+ _asn1_add_single_node (ASN1_ETYPE_CONSTANT); -+ _asn1_set_name (p5, p4->name); -+ if (p4->value) -+ { -+ tlen = _asn1_strlen (p4->value); -+ if (tlen > 0) -+ _asn1_set_value (p5, p4->value, tlen + 1); -+ } -+ _asn1_add_static_node2(list, p5); -+ -+ if (p2 == p) -+ { -+ _asn1_set_right (p5, p->down); -+ _asn1_set_down (p, p5); -+ } -+ else -+ { -+ _asn1_set_right (p5, p2->right); -+ _asn1_set_right (p2, p5); -+ } -+ p2 = p5; -+ } -+ p4 = p4->right; -+ } -+ move = DOWN; -+ -+ tries++; -+ if (tries >= EXPAND_OBJECT_ID_MAX_RECURSION) -+ return ASN1_RECURSION; -+ -+ continue; -+ } -+ } -+ } -+ move = DOWN; -+ } -+ else -+ move = RIGHT; -+ -+ tries = 0; -+ if (move == DOWN) -+ { -+ if (p->down) -+ p = p->down; -+ else -+ move = RIGHT; -+ } -+ -+ if (p == node) -+ { -+ move = UP; -+ continue; -+ } -+ -+ if (move == RIGHT) -+ { -+ if (p && p->right) -+ p = p->right; -+ else -+ move = UP; -+ } -+ if (move == UP) -+ p = _asn1_find_up (p); -+ } -+ -+ /*******************************/ -+ /* expand DEFAULT */ -+ /*******************************/ -+ p = node; -+ move = DOWN; -+ -+ while (!((p == node) && (move == UP))) -+ { -+ if (move != UP) -+ { -+ if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && -+ (p->type & CONST_DEFAULT)) -+ { -+ p2 = p->down; -+ if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) -+ { -+ _asn1_str_cpy (name2, sizeof (name2), name_root); -+ _asn1_str_cat (name2, sizeof (name2), "."); -+ if (p2->value) -+ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); -+ p3 = asn1_find_node (node, name2); -+ if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) -+ || !(p3->type & CONST_ASSIGN)) -+ return ASN1_ELEMENT_NOT_FOUND; -+ p4 = p3->down; -+ name2[0] = 0; -+ while (p4) -+ { -+ if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) -+ { -+ if (p4->value == NULL) -+ return ASN1_VALUE_NOT_FOUND; -+ -+ if (name2[0]) -+ _asn1_str_cat (name2, sizeof (name2), "."); -+ _asn1_str_cat (name2, sizeof (name2), -+ (char *) p4->value); -+ } -+ p4 = p4->right; -+ } -+ tlen = strlen (name2); -+ if (tlen > 0) -+ _asn1_set_value (p2, name2, tlen + 1); -+ } -+ } -+ move = DOWN; -+ } -+ else -+ move = RIGHT; -+ -+ if (move == DOWN) -+ { -+ if (p->down) -+ p = p->down; -+ else -+ move = RIGHT; -+ } -+ -+ if (p == node) -+ { -+ move = UP; -+ continue; -+ } -+ -+ if (move == RIGHT) -+ { -+ if (p && p->right) -+ p = p->right; -+ else -+ move = UP; -+ } -+ if (move == UP) -+ p = _asn1_find_up (p); -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_type_set_config */ -+/* Description: sets the CONST_SET and CONST_NOT_USED properties */ -+/* in the fields of the SET elements. */ -+/* Parameters: */ -+/* node: root of an ASN1 element. */ -+/* Return: */ -+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ -+/* otherwise ASN1_SUCCESS */ -+/******************************************************************/ -+int -+_asn1_type_set_config (asn1_node node) -+{ -+ asn1_node p, p2; -+ int move; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node; -+ move = DOWN; -+ -+ while (!((p == node) && (move == UP))) -+ { -+ if (move != UP) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_SET) -+ { -+ p2 = p->down; -+ while (p2) -+ { -+ if (type_field (p2->type) != ASN1_ETYPE_TAG) -+ p2->type |= CONST_SET | CONST_NOT_USED; -+ p2 = p2->right; -+ } -+ } -+ move = DOWN; -+ } -+ else -+ move = RIGHT; -+ -+ if (move == DOWN) -+ { -+ if (p->down) -+ p = p->down; -+ else -+ move = RIGHT; -+ } -+ -+ if (p == node) -+ { -+ move = UP; -+ continue; -+ } -+ -+ if (move == RIGHT) -+ { -+ if (p && p->right) -+ p = p->right; -+ else -+ move = UP; -+ } -+ if (move == UP) -+ p = _asn1_find_up (p); -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_check_identifier */ -+/* Description: checks the definitions of all the identifiers */ -+/* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */ -+/* The _asn1_identifierMissing global variable is filled if */ -+/* necessary. */ -+/* Parameters: */ -+/* node: root of an ASN1 element. */ -+/* Return: */ -+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ -+/* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */ -+/* otherwise ASN1_SUCCESS */ -+/******************************************************************/ -+int -+_asn1_check_identifier (asn1_node_const node) -+{ -+ asn1_node_const p, p2; -+ char name2[ASN1_MAX_NAME_SIZE * 2 + 2]; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node; -+ while (p) -+ { -+ if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER) -+ { -+ _asn1_str_cpy (name2, sizeof (name2), node->name); -+ _asn1_str_cat (name2, sizeof (name2), "."); -+ _asn1_str_cat (name2, sizeof (name2), (char *) p->value); -+ p2 = asn1_find_node (node, name2); -+ if (p2 == NULL) -+ { -+ if (p->value) -+ _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p->value); -+ else -+ _asn1_strcpy (_asn1_identifierMissing, "(null)"); -+ return ASN1_IDENTIFIER_NOT_FOUND; -+ } -+ } -+ else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && -+ (p->type & CONST_DEFAULT)) -+ { -+ p2 = p->down; -+ if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) -+ { -+ _asn1_str_cpy (name2, sizeof (name2), node->name); -+ if (p2->value) -+ { -+ _asn1_str_cat (name2, sizeof (name2), "."); -+ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); -+ _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); -+ } -+ else -+ _asn1_strcpy (_asn1_identifierMissing, "(null)"); -+ -+ p2 = asn1_find_node (node, name2); -+ if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) || -+ !(p2->type & CONST_ASSIGN)) -+ return ASN1_IDENTIFIER_NOT_FOUND; -+ else -+ _asn1_identifierMissing[0] = 0; -+ } -+ } -+ else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && -+ (p->type & CONST_ASSIGN)) -+ { -+ p2 = p->down; -+ if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) -+ { -+ if (p2->value && !c_isdigit (p2->value[0])) -+ { -+ _asn1_str_cpy (name2, sizeof (name2), node->name); -+ _asn1_str_cat (name2, sizeof (name2), "."); -+ _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); -+ _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); -+ -+ p2 = asn1_find_node (node, name2); -+ if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) -+ || !(p2->type & CONST_ASSIGN)) -+ return ASN1_IDENTIFIER_NOT_FOUND; -+ else -+ _asn1_identifierMissing[0] = 0; -+ } -+ } -+ } -+ -+ if (p->down) -+ { -+ p = p->down; -+ } -+ else if (p->right) -+ p = p->right; -+ else -+ { -+ while (p) -+ { -+ p = _asn1_find_up (p); -+ if (p == node) -+ { -+ p = NULL; -+ break; -+ } -+ if (p && p->right) -+ { -+ p = p->right; -+ break; -+ } -+ } -+ } -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_set_default_tag */ -+/* Description: sets the default IMPLICIT or EXPLICIT property in */ -+/* the tagged elements that don't have this declaration. */ -+/* Parameters: */ -+/* node: pointer to a DEFINITIONS element. */ -+/* Return: */ -+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */ -+/* a DEFINITIONS element, */ -+/* otherwise ASN1_SUCCESS */ -+/******************************************************************/ -+int -+_asn1_set_default_tag (asn1_node node) -+{ -+ asn1_node p; -+ -+ if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS)) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node; -+ while (p) -+ { -+ if ((type_field (p->type) == ASN1_ETYPE_TAG) && -+ !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT)) -+ { -+ if (node->type & CONST_EXPLICIT) -+ p->type |= CONST_EXPLICIT; -+ else -+ p->type |= CONST_IMPLICIT; -+ } -+ -+ if (p->down) -+ { -+ p = p->down; -+ } -+ else if (p->right) -+ p = p->right; -+ else -+ { -+ while (1) -+ { -+ p = _asn1_find_up (p); -+ if (p == node) -+ { -+ p = NULL; -+ break; -+ } -+ if (p && p->right) -+ { -+ p = p->right; -+ break; -+ } -+ } -+ } -+ } -+ -+ return ASN1_SUCCESS; -+} -diff --git a/grub-core/lib/libtasn1/lib/structure.c b/grub-core/lib/libtasn1/lib/structure.c -new file mode 100644 -index 00000000000..8189c56a4c9 ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/structure.c -@@ -0,0 +1,1220 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+ -+/*****************************************************/ -+/* File: structure.c */ -+/* Description: Functions to create and delete an */ -+/* ASN1 tree. */ -+/*****************************************************/ -+ -+ -+#include -+#include -+#include "parser_aux.h" -+#include -+ -+ -+extern char _asn1_identifierMissing[]; -+ -+ -+/******************************************************/ -+/* Function : _asn1_add_single_node */ -+/* Description: creates a new NODE_ASN element. */ -+/* Parameters: */ -+/* type: type of the new element (see ASN1_ETYPE_ */ -+/* and CONST_ constants). */ -+/* Return: pointer to the new element. */ -+/******************************************************/ -+asn1_node -+_asn1_add_single_node (unsigned int type) -+{ -+ asn1_node punt; -+ -+ punt = calloc (1, sizeof (struct asn1_node_st)); -+ if (punt == NULL) -+ return NULL; -+ -+ punt->type = type; -+ -+ return punt; -+} -+ -+ -+/******************************************************************/ -+/* Function : _asn1_find_left */ -+/* Description: returns the NODE_ASN element with RIGHT field that*/ -+/* points the element NODE. */ -+/* Parameters: */ -+/* node: NODE_ASN element pointer. */ -+/* Return: NULL if not found. */ -+/******************************************************************/ -+asn1_node -+_asn1_find_left (asn1_node_const node) -+{ -+ if ((node == NULL) || (node->left == NULL) || (node->left->down == node)) -+ return NULL; -+ -+ return node->left; -+} -+ -+ -+int -+_asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, -+ char *vector_name) -+{ -+ FILE *file; -+ asn1_node_const p; -+ unsigned long t; -+ -+ file = fopen (output_file_name, "w"); -+ -+ if (file == NULL) -+ return ASN1_FILE_NOT_FOUND; -+ -+ fprintf (file, "#if HAVE_CONFIG_H\n"); -+ fprintf (file, "# include \"config.h\"\n"); -+ fprintf (file, "#endif\n\n"); -+ -+ fprintf (file, "#include \n\n"); -+ -+ fprintf (file, "const asn1_static_node %s[] = {\n", vector_name); -+ -+ p = pointer; -+ -+ while (p) -+ { -+ fprintf (file, " { "); -+ -+ if (p->name[0] != 0) -+ fprintf (file, "\"%s\", ", p->name); -+ else -+ fprintf (file, "NULL, "); -+ -+ t = p->type; -+ if (p->down) -+ t |= CONST_DOWN; -+ if (p->right) -+ t |= CONST_RIGHT; -+ -+ fprintf (file, "%lu, ", t); -+ -+ if (p->value) -+ fprintf (file, "\"%s\"},\n", p->value); -+ else -+ fprintf (file, "NULL },\n"); -+ -+ if (p->down) -+ { -+ p = p->down; -+ } -+ else if (p->right) -+ { -+ p = p->right; -+ } -+ else -+ { -+ while (1) -+ { -+ p = _asn1_find_up (p); -+ if (p == pointer) -+ { -+ p = NULL; -+ break; -+ } -+ if (p->right) -+ { -+ p = p->right; -+ break; -+ } -+ } -+ } -+ } -+ -+ fprintf (file, " { NULL, 0, NULL }\n};\n"); -+ -+ fclose (file); -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/** -+ * asn1_array2tree: -+ * @array: specify the array that contains ASN.1 declarations -+ * @definitions: return the pointer to the structure created by -+ * *ARRAY ASN.1 declarations -+ * @errorDescription: return the error description. -+ * -+ * Creates the structures needed to manage the ASN.1 definitions. -+ * @array is a vector created by asn1_parser2array(). -+ * -+ * Returns: %ASN1_SUCCESS if structure was created correctly, -+ * %ASN1_ELEMENT_NOT_EMPTY if *@definitions not NULL, -+ * %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier -+ * that is not defined (see @errorDescription for more information), -+ * %ASN1_ARRAY_ERROR if the array pointed by @array is wrong. -+ **/ -+int -+asn1_array2tree (const asn1_static_node * array, asn1_node * definitions, -+ char *errorDescription) -+{ -+ asn1_node p, p_last = NULL; -+ unsigned long k; -+ int move; -+ int result; -+ unsigned int type; -+ list_type *e_list = NULL; -+ -+ if (errorDescription) -+ errorDescription[0] = 0; -+ -+ if (*definitions != NULL) -+ return ASN1_ELEMENT_NOT_EMPTY; -+ -+ move = UP; -+ -+ for (k = 0; array[k].value || array[k].type || array[k].name; k++) -+ { -+ type = convert_old_type (array[k].type); -+ -+ p = _asn1_add_static_node (&e_list, type & (~CONST_DOWN)); -+ if (array[k].name) -+ _asn1_set_name (p, array[k].name); -+ if (array[k].value) -+ _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1); -+ -+ if (*definitions == NULL) -+ *definitions = p; -+ -+ if (move == DOWN) -+ { -+ if (p_last && p_last->down) -+ _asn1_delete_structure (e_list, &p_last->down, 0); -+ _asn1_set_down (p_last, p); -+ } -+ else if (move == RIGHT) -+ { -+ if (p_last && p_last->right) -+ _asn1_delete_structure (e_list, &p_last->right, 0); -+ _asn1_set_right (p_last, p); -+ } -+ -+ p_last = p; -+ -+ if (type & CONST_DOWN) -+ move = DOWN; -+ else if (type & CONST_RIGHT) -+ move = RIGHT; -+ else -+ { -+ while (p_last != *definitions) -+ { -+ p_last = _asn1_find_up (p_last); -+ -+ if (p_last == NULL) -+ break; -+ -+ if (p_last->type & CONST_RIGHT) -+ { -+ p_last->type &= ~CONST_RIGHT; -+ move = RIGHT; -+ break; -+ } -+ } /* while */ -+ } -+ } /* while */ -+ -+ if (p_last == *definitions) -+ { -+ result = _asn1_check_identifier (*definitions); -+ if (result == ASN1_SUCCESS) -+ { -+ _asn1_change_integer_value (*definitions); -+ result = _asn1_expand_object_id (&e_list, *definitions); -+ } -+ } -+ else -+ { -+ result = ASN1_ARRAY_ERROR; -+ } -+ -+ if (errorDescription != NULL) -+ { -+ if (result == ASN1_IDENTIFIER_NOT_FOUND) -+ { -+ Estrcpy (errorDescription, ":: identifier '"); -+ Estrcat (errorDescription, _asn1_identifierMissing); -+ Estrcat (errorDescription, "' not found"); -+ } -+ else -+ errorDescription[0] = 0; -+ } -+ -+ if (result != ASN1_SUCCESS) -+ { -+ _asn1_delete_list_and_nodes (e_list); -+ *definitions = NULL; -+ } -+ else -+ _asn1_delete_list (e_list); -+ -+ return result; -+} -+ -+/** -+ * asn1_delete_structure: -+ * @structure: pointer to the structure that you want to delete. -+ * -+ * Deletes the structure *@structure. At the end, *@structure is set -+ * to NULL. -+ * -+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if -+ * *@structure was NULL. -+ **/ -+int -+asn1_delete_structure (asn1_node * structure) -+{ -+ return _asn1_delete_structure (NULL, structure, 0); -+} -+ -+/** -+ * asn1_delete_structure2: -+ * @structure: pointer to the structure that you want to delete. -+ * @flags: additional flags (see %ASN1_DELETE_FLAG) -+ * -+ * Deletes the structure *@structure. At the end, *@structure is set -+ * to NULL. -+ * -+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if -+ * *@structure was NULL. -+ **/ -+int -+asn1_delete_structure2 (asn1_node * structure, unsigned int flags) -+{ -+ return _asn1_delete_structure (NULL, structure, flags); -+} -+ -+int -+_asn1_delete_structure (list_type *e_list, asn1_node * structure, unsigned int flags) -+{ -+ asn1_node p, p2, p3; -+ -+ if (*structure == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = *structure; -+ while (p) -+ { -+ if (p->down) -+ { -+ p = p->down; -+ } -+ else -+ { /* no down */ -+ p2 = p->right; -+ if (p != *structure) -+ { -+ p3 = _asn1_find_up (p); -+ _asn1_set_down (p3, p2); -+ if (e_list) -+ _asn1_delete_node_from_list (e_list, p); -+ _asn1_remove_node (p, flags); -+ p = p3; -+ } -+ else -+ { /* p==root */ -+ p3 = _asn1_find_left (p); -+ if (!p3) -+ { -+ p3 = _asn1_find_up (p); -+ if (p3) -+ _asn1_set_down (p3, p2); -+ else -+ { -+ if (p->right) -+ p->right->left = NULL; -+ } -+ } -+ else -+ _asn1_set_right (p3, p2); -+ if (e_list) -+ _asn1_delete_node_from_list (e_list, p); -+ _asn1_remove_node (p, flags); -+ p = NULL; -+ } -+ } -+ } -+ -+ *structure = NULL; -+ return ASN1_SUCCESS; -+} -+ -+ -+/** -+ * asn1_delete_element: -+ * @structure: pointer to the structure that contains the element you -+ * want to delete. -+ * @element_name: element's name you want to delete. -+ * -+ * Deletes the element named *@element_name inside *@structure. -+ * -+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if -+ * the @element_name was not found. -+ **/ -+int -+asn1_delete_element (asn1_node structure, const char *element_name) -+{ -+ asn1_node p2, p3, source_node; -+ -+ source_node = asn1_find_node (structure, element_name); -+ -+ if (source_node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p2 = source_node->right; -+ p3 = _asn1_find_left (source_node); -+ if (!p3) -+ { -+ p3 = _asn1_find_up (source_node); -+ if (p3) -+ _asn1_set_down (p3, p2); -+ else if (source_node->right) -+ source_node->right->left = NULL; -+ } -+ else -+ _asn1_set_right (p3, p2); -+ -+ return asn1_delete_structure (&source_node); -+} -+ -+#ifndef __clang_analyzer__ -+asn1_node -+_asn1_copy_structure3 (asn1_node_const source_node) -+{ -+ asn1_node_const p_s; -+ asn1_node dest_node, p_d, p_d_prev; -+ int move; -+ -+ if (source_node == NULL) -+ return NULL; -+ -+ dest_node = _asn1_add_single_node (source_node->type); -+ -+ p_s = source_node; -+ p_d = dest_node; -+ -+ move = DOWN; -+ -+ do -+ { -+ if (move != UP) -+ { -+ if (p_s->name[0] != 0) -+ _asn1_cpy_name (p_d, p_s); -+ if (p_s->value) -+ _asn1_set_value (p_d, p_s->value, p_s->value_len); -+ if (p_s->down) -+ { -+ p_s = p_s->down; -+ p_d_prev = p_d; -+ p_d = _asn1_add_single_node (p_s->type); -+ _asn1_set_down (p_d_prev, p_d); -+ continue; -+ } -+ p_d->start = p_s->start; -+ p_d->end = p_s->end; -+ } -+ -+ if (p_s == source_node) -+ break; -+ -+ if (p_s->right) -+ { -+ move = RIGHT; -+ p_s = p_s->right; -+ p_d_prev = p_d; -+ p_d = _asn1_add_single_node (p_s->type); -+ _asn1_set_right (p_d_prev, p_d); -+ } -+ else -+ { -+ move = UP; -+ p_s = _asn1_find_up (p_s); -+ p_d = _asn1_find_up (p_d); -+ } -+ } -+ while (p_s != source_node); -+ return dest_node; -+} -+#else -+ -+/* Non-production code */ -+asn1_node -+_asn1_copy_structure3 (asn1_node_const source_node) -+{ -+ return NULL; -+} -+#endif /* __clang_analyzer__ */ -+ -+ -+static asn1_node -+_asn1_copy_structure2 (asn1_node_const root, const char *source_name) -+{ -+ asn1_node source_node; -+ -+ source_node = asn1_find_node (root, source_name); -+ -+ return _asn1_copy_structure3 (source_node); -+ -+} -+ -+ -+static int -+_asn1_type_choice_config (asn1_node node) -+{ -+ asn1_node p, p2, p3, p4; -+ int move, tlen; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node; -+ move = DOWN; -+ -+ while (!((p == node) && (move == UP))) -+ { -+ if (move != UP) -+ { -+ if ((type_field (p->type) == ASN1_ETYPE_CHOICE) -+ && (p->type & CONST_TAG)) -+ { -+ p2 = p->down; -+ while (p2) -+ { -+ if (type_field (p2->type) != ASN1_ETYPE_TAG) -+ { -+ p2->type |= CONST_TAG; -+ p3 = _asn1_find_left (p2); -+ while (p3) -+ { -+ if (type_field (p3->type) == ASN1_ETYPE_TAG) -+ { -+ p4 = _asn1_add_single_node (p3->type); -+ tlen = _asn1_strlen (p3->value); -+ if (tlen > 0) -+ _asn1_set_value (p4, p3->value, tlen + 1); -+ _asn1_set_right (p4, p2->down); -+ _asn1_set_down (p2, p4); -+ } -+ p3 = _asn1_find_left (p3); -+ } -+ } -+ p2 = p2->right; -+ } -+ p->type &= ~(CONST_TAG); -+ p2 = p->down; -+ while (p2) -+ { -+ p3 = p2->right; -+ if (type_field (p2->type) == ASN1_ETYPE_TAG) -+ asn1_delete_structure (&p2); -+ p2 = p3; -+ } -+ } -+ move = DOWN; -+ } -+ else -+ move = RIGHT; -+ -+ if (move == DOWN) -+ { -+ if (p->down) -+ p = p->down; -+ else -+ move = RIGHT; -+ } -+ -+ if (p == node) -+ { -+ move = UP; -+ continue; -+ } -+ -+ if (move == RIGHT) -+ { -+ if (p->right) -+ p = p->right; -+ else -+ move = UP; -+ } -+ if (move == UP) -+ p = _asn1_find_up (p); -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+static int -+_asn1_expand_identifier (asn1_node * node, asn1_node_const root) -+{ -+ asn1_node p, p2, p3; -+ char name2[ASN1_MAX_NAME_SIZE + 2]; -+ int move; -+ -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = *node; -+ move = DOWN; -+ -+ while (!((p == *node) && (move == UP))) -+ { -+ if (move != UP) -+ { -+ if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER) -+ { -+ snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value); -+ p2 = _asn1_copy_structure2 (root, name2); -+ if (p2 == NULL) -+ { -+ return ASN1_IDENTIFIER_NOT_FOUND; -+ } -+ _asn1_cpy_name (p2, p); -+ p2->right = p->right; -+ p2->left = p->left; -+ if (p->right) -+ p->right->left = p2; -+ p3 = p->down; -+ if (p3) -+ { -+ while (p3->right) -+ p3 = p3->right; -+ _asn1_set_right (p3, p2->down); -+ _asn1_set_down (p2, p->down); -+ } -+ -+ p3 = _asn1_find_left (p); -+ if (p3) -+ _asn1_set_right (p3, p2); -+ else -+ { -+ p3 = _asn1_find_up (p); -+ if (p3) -+ _asn1_set_down (p3, p2); -+ else -+ { -+ p2->left = NULL; -+ } -+ } -+ -+ if (p->type & CONST_SIZE) -+ p2->type |= CONST_SIZE; -+ if (p->type & CONST_TAG) -+ p2->type |= CONST_TAG; -+ if (p->type & CONST_OPTION) -+ p2->type |= CONST_OPTION; -+ if (p->type & CONST_DEFAULT) -+ p2->type |= CONST_DEFAULT; -+ if (p->type & CONST_SET) -+ p2->type |= CONST_SET; -+ if (p->type & CONST_NOT_USED) -+ p2->type |= CONST_NOT_USED; -+ -+ if (p == *node) -+ *node = p2; -+ _asn1_remove_node (p, 0); -+ p = p2; -+ move = DOWN; -+ continue; -+ } -+ move = DOWN; -+ } -+ else -+ move = RIGHT; -+ -+ if (move == DOWN) -+ { -+ if (p->down) -+ p = p->down; -+ else -+ move = RIGHT; -+ } -+ -+ if (p == *node) -+ { -+ move = UP; -+ continue; -+ } -+ -+ if (move == RIGHT) -+ { -+ if (p->right) -+ p = p->right; -+ else -+ move = UP; -+ } -+ if (move == UP) -+ p = _asn1_find_up (p); -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/** -+ * asn1_create_element: -+ * @definitions: pointer to the structure returned by "parser_asn1" function -+ * @source_name: the name of the type of the new structure (must be -+ * inside p_structure). -+ * @element: pointer to the structure created. -+ * -+ * Creates a structure of type @source_name. Example using -+ * "pkix.asn": -+ * -+ * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr); -+ * -+ * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if -+ * @source_name is not known. -+ **/ -+int -+asn1_create_element (asn1_node_const definitions, const char *source_name, -+ asn1_node * element) -+{ -+ asn1_node dest_node; -+ int res; -+ -+ dest_node = _asn1_copy_structure2 (definitions, source_name); -+ -+ if (dest_node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ _asn1_set_name (dest_node, ""); -+ -+ res = _asn1_expand_identifier (&dest_node, definitions); -+ _asn1_type_choice_config (dest_node); -+ -+ *element = dest_node; -+ -+ return res; -+} -+ -+ -+/** -+ * asn1_print_structure: -+ * @out: pointer to the output file (e.g. stdout). -+ * @structure: pointer to the structure that you want to visit. -+ * @name: an element of the structure -+ * @mode: specify how much of the structure to print, can be -+ * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE, -+ * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL. -+ * -+ * Prints on the @out file descriptor the structure's tree starting -+ * from the @name element inside the structure @structure. -+ **/ -+void -+asn1_print_structure (FILE * out, asn1_node_const structure, const char *name, -+ int mode) -+{ -+ asn1_node_const p, root; -+ int k, indent = 0, len, len2, len3; -+ -+ if (out == NULL) -+ return; -+ -+ root = asn1_find_node (structure, name); -+ -+ if (root == NULL) -+ return; -+ -+ p = root; -+ while (p) -+ { -+ if (mode == ASN1_PRINT_ALL) -+ { -+ for (k = 0; k < indent; k++) -+ fprintf (out, " "); -+ fprintf (out, "name:"); -+ if (p->name[0] != 0) -+ fprintf (out, "%s ", p->name); -+ else -+ fprintf (out, "NULL "); -+ } -+ else -+ { -+ switch (type_field (p->type)) -+ { -+ case ASN1_ETYPE_CONSTANT: -+ case ASN1_ETYPE_TAG: -+ case ASN1_ETYPE_SIZE: -+ break; -+ default: -+ for (k = 0; k < indent; k++) -+ fprintf (out, " "); -+ fprintf (out, "name:"); -+ if (p->name[0] != 0) -+ fprintf (out, "%s ", p->name); -+ else -+ fprintf (out, "NULL "); -+ } -+ } -+ -+ if (mode != ASN1_PRINT_NAME) -+ { -+ unsigned type = type_field (p->type); -+ switch (type) -+ { -+ case ASN1_ETYPE_CONSTANT: -+ if (mode == ASN1_PRINT_ALL) -+ fprintf (out, "type:CONST"); -+ break; -+ case ASN1_ETYPE_TAG: -+ if (mode == ASN1_PRINT_ALL) -+ fprintf (out, "type:TAG"); -+ break; -+ case ASN1_ETYPE_SIZE: -+ if (mode == ASN1_PRINT_ALL) -+ fprintf (out, "type:SIZE"); -+ break; -+ case ASN1_ETYPE_DEFAULT: -+ fprintf (out, "type:DEFAULT"); -+ break; -+ case ASN1_ETYPE_IDENTIFIER: -+ fprintf (out, "type:IDENTIFIER"); -+ break; -+ case ASN1_ETYPE_ANY: -+ fprintf (out, "type:ANY"); -+ break; -+ case ASN1_ETYPE_CHOICE: -+ fprintf (out, "type:CHOICE"); -+ break; -+ case ASN1_ETYPE_DEFINITIONS: -+ fprintf (out, "type:DEFINITIONS"); -+ break; -+ CASE_HANDLED_ETYPES: -+ fprintf (out, "%s", _asn1_tags[type].desc); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL)) -+ { -+ switch (type_field (p->type)) -+ { -+ case ASN1_ETYPE_CONSTANT: -+ if (mode == ASN1_PRINT_ALL) -+ if (p->value) -+ fprintf (out, " value:%s", p->value); -+ break; -+ case ASN1_ETYPE_TAG: -+ if (mode == ASN1_PRINT_ALL) -+ if (p->value) -+ fprintf (out, " value:%s", p->value); -+ break; -+ case ASN1_ETYPE_SIZE: -+ if (mode == ASN1_PRINT_ALL) -+ if (p->value) -+ fprintf (out, " value:%s", p->value); -+ break; -+ case ASN1_ETYPE_DEFAULT: -+ if (p->value) -+ fprintf (out, " value:%s", p->value); -+ else if (p->type & CONST_TRUE) -+ fprintf (out, " value:TRUE"); -+ else if (p->type & CONST_FALSE) -+ fprintf (out, " value:FALSE"); -+ break; -+ case ASN1_ETYPE_IDENTIFIER: -+ if (p->value) -+ fprintf (out, " value:%s", p->value); -+ break; -+ case ASN1_ETYPE_INTEGER: -+ if (p->value) -+ { -+ len2 = -1; -+ len = asn1_get_length_der (p->value, p->value_len, &len2); -+ fprintf (out, " value:0x"); -+ if (len > 0) -+ for (k = 0; k < len; k++) -+ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); -+ } -+ break; -+ case ASN1_ETYPE_ENUMERATED: -+ if (p->value) -+ { -+ len2 = -1; -+ len = asn1_get_length_der (p->value, p->value_len, &len2); -+ fprintf (out, " value:0x"); -+ if (len > 0) -+ for (k = 0; k < len; k++) -+ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); -+ } -+ break; -+ case ASN1_ETYPE_BOOLEAN: -+ if (p->value) -+ { -+ if (p->value[0] == 'T') -+ fprintf (out, " value:TRUE"); -+ else if (p->value[0] == 'F') -+ fprintf (out, " value:FALSE"); -+ } -+ break; -+ case ASN1_ETYPE_BIT_STRING: -+ if (p->value) -+ { -+ len2 = -1; -+ len = asn1_get_length_der (p->value, p->value_len, &len2); -+ if (len > 0) -+ { -+ fprintf (out, " value(%i):", -+ (len - 1) * 8 - (p->value[len2])); -+ for (k = 1; k < len; k++) -+ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); -+ } -+ } -+ break; -+ case ASN1_ETYPE_GENERALIZED_TIME: -+ case ASN1_ETYPE_UTC_TIME: -+ if (p->value) -+ { -+ fprintf (out, " value:"); -+ for (k = 0; k < p->value_len; k++) -+ fprintf (out, "%c", (p->value)[k]); -+ } -+ break; -+ case ASN1_ETYPE_GENERALSTRING: -+ case ASN1_ETYPE_NUMERIC_STRING: -+ case ASN1_ETYPE_IA5_STRING: -+ case ASN1_ETYPE_TELETEX_STRING: -+ case ASN1_ETYPE_PRINTABLE_STRING: -+ case ASN1_ETYPE_UNIVERSAL_STRING: -+ case ASN1_ETYPE_UTF8_STRING: -+ case ASN1_ETYPE_VISIBLE_STRING: -+ if (p->value) -+ { -+ len2 = -1; -+ len = asn1_get_length_der (p->value, p->value_len, &len2); -+ fprintf (out, " value:"); -+ if (len > 0) -+ for (k = 0; k < len; k++) -+ fprintf (out, "%c", (p->value)[k + len2]); -+ } -+ break; -+ case ASN1_ETYPE_BMP_STRING: -+ case ASN1_ETYPE_OCTET_STRING: -+ if (p->value) -+ { -+ len2 = -1; -+ len = asn1_get_length_der (p->value, p->value_len, &len2); -+ fprintf (out, " value:"); -+ if (len > 0) -+ for (k = 0; k < len; k++) -+ fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); -+ } -+ break; -+ case ASN1_ETYPE_OBJECT_ID: -+ if (p->value) -+ fprintf (out, " value:%s", p->value); -+ break; -+ case ASN1_ETYPE_ANY: -+ if (p->value) -+ { -+ len3 = -1; -+ len2 = asn1_get_length_der (p->value, p->value_len, &len3); -+ fprintf (out, " value:"); -+ if (len2 > 0) -+ for (k = 0; k < len2; k++) -+ fprintf (out, "%02x", (unsigned) (p->value)[k + len3]); -+ } -+ break; -+ case ASN1_ETYPE_SET: -+ case ASN1_ETYPE_SET_OF: -+ case ASN1_ETYPE_CHOICE: -+ case ASN1_ETYPE_DEFINITIONS: -+ case ASN1_ETYPE_SEQUENCE_OF: -+ case ASN1_ETYPE_SEQUENCE: -+ case ASN1_ETYPE_NULL: -+ break; -+ default: -+ break; -+ } -+ } -+ -+ if (mode == ASN1_PRINT_ALL) -+ { -+ if (p->type & 0x1FFFFF00) -+ { -+ fprintf (out, " attr:"); -+ if (p->type & CONST_UNIVERSAL) -+ fprintf (out, "UNIVERSAL,"); -+ if (p->type & CONST_PRIVATE) -+ fprintf (out, "PRIVATE,"); -+ if (p->type & CONST_APPLICATION) -+ fprintf (out, "APPLICATION,"); -+ if (p->type & CONST_EXPLICIT) -+ fprintf (out, "EXPLICIT,"); -+ if (p->type & CONST_IMPLICIT) -+ fprintf (out, "IMPLICIT,"); -+ if (p->type & CONST_TAG) -+ fprintf (out, "TAG,"); -+ if (p->type & CONST_DEFAULT) -+ fprintf (out, "DEFAULT,"); -+ if (p->type & CONST_TRUE) -+ fprintf (out, "TRUE,"); -+ if (p->type & CONST_FALSE) -+ fprintf (out, "FALSE,"); -+ if (p->type & CONST_LIST) -+ fprintf (out, "LIST,"); -+ if (p->type & CONST_MIN_MAX) -+ fprintf (out, "MIN_MAX,"); -+ if (p->type & CONST_OPTION) -+ fprintf (out, "OPTION,"); -+ if (p->type & CONST_1_PARAM) -+ fprintf (out, "1_PARAM,"); -+ if (p->type & CONST_SIZE) -+ fprintf (out, "SIZE,"); -+ if (p->type & CONST_DEFINED_BY) -+ fprintf (out, "DEF_BY,"); -+ if (p->type & CONST_GENERALIZED) -+ fprintf (out, "GENERALIZED,"); -+ if (p->type & CONST_UTC) -+ fprintf (out, "UTC,"); -+ if (p->type & CONST_SET) -+ fprintf (out, "SET,"); -+ if (p->type & CONST_NOT_USED) -+ fprintf (out, "NOT_USED,"); -+ if (p->type & CONST_ASSIGN) -+ fprintf (out, "ASSIGNMENT,"); -+ } -+ } -+ -+ if (mode == ASN1_PRINT_ALL) -+ { -+ fprintf (out, "\n"); -+ } -+ else -+ { -+ switch (type_field (p->type)) -+ { -+ case ASN1_ETYPE_CONSTANT: -+ case ASN1_ETYPE_TAG: -+ case ASN1_ETYPE_SIZE: -+ break; -+ default: -+ fprintf (out, "\n"); -+ } -+ } -+ -+ if (p->down) -+ { -+ p = p->down; -+ indent += 2; -+ } -+ else if (p == root) -+ { -+ p = NULL; -+ break; -+ } -+ else if (p->right) -+ p = p->right; -+ else -+ { -+ while (1) -+ { -+ p = _asn1_find_up (p); -+ if (p == root) -+ { -+ p = NULL; -+ break; -+ } -+ indent -= 2; -+ if (p->right) -+ { -+ p = p->right; -+ break; -+ } -+ } -+ } -+ } -+} -+ -+ -+ -+/** -+ * asn1_number_of_elements: -+ * @element: pointer to the root of an ASN1 structure. -+ * @name: the name of a sub-structure of ROOT. -+ * @num: pointer to an integer where the result will be stored -+ * -+ * Counts the number of elements of a sub-structure called NAME with -+ * names equal to "?1","?2", ... -+ * -+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if -+ * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL. -+ **/ -+int -+asn1_number_of_elements (asn1_node_const element, const char *name, int *num) -+{ -+ asn1_node_const node, p; -+ -+ if (num == NULL) -+ return ASN1_GENERIC_ERROR; -+ -+ *num = 0; -+ -+ node = asn1_find_node (element, name); -+ if (node == NULL) -+ return ASN1_ELEMENT_NOT_FOUND; -+ -+ p = node->down; -+ -+ while (p) -+ { -+ if (p->name[0] == '?') -+ (*num)++; -+ p = p->right; -+ } -+ -+ return ASN1_SUCCESS; -+} -+ -+ -+/** -+ * asn1_find_structure_from_oid: -+ * @definitions: ASN1 definitions -+ * @oidValue: value of the OID to search (e.g. "1.2.3.4"). -+ * -+ * Search the structure that is defined just after an OID definition. -+ * -+ * Returns: %NULL when @oidValue not found, otherwise the pointer to a -+ * constant string that contains the element name defined just after -+ * the OID. -+ **/ -+const char * -+asn1_find_structure_from_oid (asn1_node_const definitions, const char *oidValue) -+{ -+ char name[2 * ASN1_MAX_NAME_SIZE + 2]; -+ char value[ASN1_MAX_NAME_SIZE]; -+ asn1_node p; -+ int len; -+ int result; -+ const char *definitionsName; -+ -+ if ((definitions == NULL) || (oidValue == NULL)) -+ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ -+ -+ definitionsName = definitions->name; -+ -+ /* search the OBJECT_ID into definitions */ -+ p = definitions->down; -+ while (p) -+ { -+ if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && -+ (p->type & CONST_ASSIGN)) -+ { -+ snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name); -+ -+ len = ASN1_MAX_NAME_SIZE; -+ result = asn1_read_value (definitions, name, value, &len); -+ -+ if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value))) -+ { -+ p = p->right; -+ if (p == NULL) /* reach the end of ASN1 definitions */ -+ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ -+ -+ return p->name; -+ } -+ } -+ p = p->right; -+ } -+ -+ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ -+} -+ -+/** -+ * asn1_copy_node: -+ * @dst: Destination asn1 node. -+ * @dst_name: Field name in destination node. -+ * @src: Source asn1 node. -+ * @src_name: Field name in source node. -+ * -+ * Create a deep copy of a asn1_node variable. That -+ * function requires @dst to be expanded using asn1_create_element(). -+ * -+ * Returns: Return %ASN1_SUCCESS on success. -+ **/ -+int -+asn1_copy_node (asn1_node dst, const char *dst_name, -+ asn1_node_const src, const char *src_name) -+{ -+ int result; -+ asn1_node dst_node; -+ void *data = NULL; -+ int size = 0; -+ -+ result = asn1_der_coding (src, src_name, NULL, &size, NULL); -+ if (result != ASN1_MEM_ERROR) -+ return result; -+ -+ data = malloc (size); -+ if (data == NULL) -+ return ASN1_MEM_ERROR; -+ -+ result = asn1_der_coding (src, src_name, data, &size, NULL); -+ if (result != ASN1_SUCCESS) -+ { -+ free (data); -+ return result; -+ } -+ -+ dst_node = asn1_find_node (dst, dst_name); -+ if (dst_node == NULL) -+ { -+ free (data); -+ return ASN1_ELEMENT_NOT_FOUND; -+ } -+ -+ result = asn1_der_decoding (&dst_node, data, size, NULL); -+ -+ free (data); -+ -+ return result; -+} -+ -+/** -+ * asn1_dup_node: -+ * @src: Source asn1 node. -+ * @src_name: Field name in source node. -+ * -+ * Create a deep copy of a asn1_node variable. This function -+ * will return an exact copy of the provided structure. -+ * -+ * Returns: Return %NULL on failure. -+ **/ -+asn1_node -+asn1_dup_node (asn1_node_const src, const char *src_name) -+{ -+ return _asn1_copy_structure2(src, src_name); -+} -diff --git a/grub-core/lib/libtasn1/lib/element.h b/grub-core/lib/libtasn1/lib/element.h -new file mode 100644 -index 00000000000..440a33f4bb1 ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/element.h -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2000-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#ifndef _ELEMENT_H -+#define _ELEMENT_H -+ -+ -+struct node_tail_cache_st -+{ -+ asn1_node head; /* the first element of the sequence */ -+ asn1_node tail; -+}; -+ -+int _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcached); -+ -+int _asn1_convert_integer (const unsigned char *value, -+ unsigned char *value_out, -+ int value_out_size, int *len); -+ -+void _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size); -+ -+#endif -diff --git a/grub-core/lib/libtasn1/lib/gstr.h b/grub-core/lib/libtasn1/lib/gstr.h -new file mode 100644 -index 00000000000..48229844ff3 ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/gstr.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#ifndef GSTR_H -+# define GSTR_H -+ -+unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size, -+ const char *src); -+void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src); -+ -+#define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) -+#define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) -+ -+inline static -+void safe_memset(void *data, int c, size_t size) -+{ -+ volatile unsigned volatile_zero = 0; -+ volatile char *vdata = (volatile char*)data; -+ -+ /* This is based on a nice trick for safe memset, -+ * sent by David Jacobson in the openssl-dev mailing list. -+ */ -+ -+ if (size > 0) do { -+ memset(data, c, size); -+ } while(vdata[volatile_zero] != c); -+} -+ -+#endif /* GSTR_H */ -diff --git a/grub-core/lib/libtasn1/lib/int.h b/grub-core/lib/libtasn1/lib/int.h -new file mode 100644 -index 00000000000..ea1625786c1 ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/int.h -@@ -0,0 +1,221 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#ifndef INT_H -+#define INT_H -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+ -+#ifdef HAVE_SYS_TYPES_H -+#include -+#endif -+ -+#include -+ -+#define ASN1_SMALL_VALUE_SIZE 16 -+ -+/* This structure is also in libtasn1.h, but then contains less -+ fields. You cannot make any modifications to these first fields -+ without breaking ABI. */ -+struct asn1_node_st -+{ -+ /* public fields: */ -+ char name[ASN1_MAX_NAME_SIZE + 1]; /* Node name */ -+ unsigned int name_hash; -+ unsigned int type; /* Node type */ -+ unsigned char *value; /* Node value */ -+ int value_len; -+ asn1_node down; /* Pointer to the son node */ -+ asn1_node right; /* Pointer to the brother node */ -+ asn1_node left; /* Pointer to the next list element */ -+ /* private fields: */ -+ unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */ -+ -+ /* values used during decoding/coding */ -+ int tmp_ival; -+ unsigned start; /* the start of the DER sequence - if decoded */ -+ unsigned end; /* the end of the DER sequence - if decoded */ -+}; -+ -+typedef struct tag_and_class_st -+{ -+ unsigned tag; -+ unsigned class; -+ const char *desc; -+} tag_and_class_st; -+ -+/* the types that are handled in _asn1_tags */ -+#define CASE_HANDLED_ETYPES \ -+ case ASN1_ETYPE_NULL: \ -+ case ASN1_ETYPE_BOOLEAN: \ -+ case ASN1_ETYPE_INTEGER: \ -+ case ASN1_ETYPE_ENUMERATED: \ -+ case ASN1_ETYPE_OBJECT_ID: \ -+ case ASN1_ETYPE_OCTET_STRING: \ -+ case ASN1_ETYPE_GENERALSTRING: \ -+ case ASN1_ETYPE_NUMERIC_STRING: \ -+ case ASN1_ETYPE_IA5_STRING: \ -+ case ASN1_ETYPE_TELETEX_STRING: \ -+ case ASN1_ETYPE_PRINTABLE_STRING: \ -+ case ASN1_ETYPE_UNIVERSAL_STRING: \ -+ case ASN1_ETYPE_BMP_STRING: \ -+ case ASN1_ETYPE_UTF8_STRING: \ -+ case ASN1_ETYPE_VISIBLE_STRING: \ -+ case ASN1_ETYPE_BIT_STRING: \ -+ case ASN1_ETYPE_SEQUENCE: \ -+ case ASN1_ETYPE_SEQUENCE_OF: \ -+ case ASN1_ETYPE_SET: \ -+ case ASN1_ETYPE_UTC_TIME: \ -+ case ASN1_ETYPE_GENERALIZED_TIME: \ -+ case ASN1_ETYPE_SET_OF -+ -+#define ETYPE_TAG(etype) (_asn1_tags[etype].tag) -+#define ETYPE_CLASS(etype) (_asn1_tags[etype].class) -+#define ETYPE_OK(etype) (((etype) != ASN1_ETYPE_INVALID && \ -+ (etype) <= _asn1_tags_size && \ -+ _asn1_tags[(etype)].desc != NULL)?1:0) -+ -+#define ETYPE_IS_STRING(etype) ((etype == ASN1_ETYPE_GENERALSTRING || \ -+ etype == ASN1_ETYPE_NUMERIC_STRING || etype == ASN1_ETYPE_IA5_STRING || \ -+ etype == ASN1_ETYPE_TELETEX_STRING || etype == ASN1_ETYPE_PRINTABLE_STRING || \ -+ etype == ASN1_ETYPE_UNIVERSAL_STRING || etype == ASN1_ETYPE_BMP_STRING || \ -+ etype == ASN1_ETYPE_UTF8_STRING || etype == ASN1_ETYPE_VISIBLE_STRING || \ -+ etype == ASN1_ETYPE_OCTET_STRING)?1:0) -+ -+extern unsigned int _asn1_tags_size; -+extern const tag_and_class_st _asn1_tags[]; -+ -+#define _asn1_strlen(s) strlen((const char *) s) -+#define _asn1_strtol(n,e,b) strtol((const char *) n, e, b) -+#define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b) -+#define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b) -+#define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b) -+#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b) -+ -+#if SIZEOF_UNSIGNED_LONG_INT == 8 -+# define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b) -+#else -+# define _asn1_strtou64(n,e,b) strtoull((const char *) n, e, b) -+#endif -+ -+#define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */ -+ -+/* Define used for visiting trees. */ -+#define UP 1 -+#define RIGHT 2 -+#define DOWN 3 -+ -+/***********************************************************************/ -+/* List of constants to better specify the type of typedef asn1_node_st. */ -+/***********************************************************************/ -+/* Used with TYPE_TAG */ -+#define CONST_UNIVERSAL (1U<<8) -+#define CONST_PRIVATE (1U<<9) -+#define CONST_APPLICATION (1U<<10) -+#define CONST_EXPLICIT (1U<<11) -+#define CONST_IMPLICIT (1U<<12) -+ -+#define CONST_TAG (1U<<13) /* Used in ASN.1 assignement */ -+#define CONST_OPTION (1U<<14) -+#define CONST_DEFAULT (1U<<15) -+#define CONST_TRUE (1U<<16) -+#define CONST_FALSE (1U<<17) -+ -+#define CONST_LIST (1U<<18) /* Used with TYPE_INTEGER and TYPE_BIT_STRING */ -+#define CONST_MIN_MAX (1U<<19) -+ -+#define CONST_1_PARAM (1U<<20) -+ -+#define CONST_SIZE (1U<<21) -+ -+#define CONST_DEFINED_BY (1U<<22) -+ -+/* Those two are deprecated and used for backwards compatibility */ -+#define CONST_GENERALIZED (1U<<23) -+#define CONST_UTC (1U<<24) -+ -+/* #define CONST_IMPORTS (1U<<25) */ -+ -+#define CONST_NOT_USED (1U<<26) -+#define CONST_SET (1U<<27) -+#define CONST_ASSIGN (1U<<28) -+ -+#define CONST_DOWN (1U<<29) -+#define CONST_RIGHT (1U<<30) -+ -+ -+#define ASN1_ETYPE_TIME 17 -+/****************************************/ -+/* Returns the first 8 bits. */ -+/* Used with the field type of asn1_node_st */ -+/****************************************/ -+inline static unsigned int -+type_field (unsigned int ntype) -+{ -+ return (ntype & 0xff); -+} -+ -+/* To convert old types from a static structure */ -+inline static unsigned int -+convert_old_type (unsigned int ntype) -+{ -+ unsigned int type = ntype & 0xff; -+ if (type == ASN1_ETYPE_TIME) -+ { -+ if (ntype & CONST_UTC) -+ type = ASN1_ETYPE_UTC_TIME; -+ else -+ type = ASN1_ETYPE_GENERALIZED_TIME; -+ -+ ntype &= ~(CONST_UTC | CONST_GENERALIZED); -+ ntype &= 0xffffff00; -+ ntype |= type; -+ -+ return ntype; -+ } -+ else -+ return ntype; -+} -+ -+static inline -+void *_asn1_realloc(void *ptr, size_t size) -+{ -+ void *ret; -+ -+ if (size == 0) -+ return ptr; -+ -+ ret = realloc(ptr, size); -+ if (ret == NULL) -+ { -+ free(ptr); -+ } -+ return ret; -+} -+ -+#endif /* INT_H */ -diff --git a/grub-core/lib/libtasn1/lib/parser_aux.h b/grub-core/lib/libtasn1/lib/parser_aux.h -new file mode 100644 -index 00000000000..598e684b355 ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/parser_aux.h -@@ -0,0 +1,172 @@ -+/* -+ * Copyright (C) 2000-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#ifndef _PARSER_AUX_H -+#define _PARSER_AUX_H -+ -+/***********************************************/ -+/* Type: list_type */ -+/* Description: type used in the list during */ -+/* the structure creation. */ -+/***********************************************/ -+typedef struct list_struct -+{ -+ asn1_node node; -+ struct list_struct *next; -+} list_type; -+ -+/***************************************/ -+/* Functions used by ASN.1 parser */ -+/***************************************/ -+asn1_node _asn1_add_static_node (list_type **e_list, unsigned int type); -+ -+void _asn1_delete_list (list_type *e_list); -+ -+void _asn1_delete_list_and_nodes (list_type *e_list); -+ -+void _asn1_delete_node_from_list (list_type *list, asn1_node node); -+ -+asn1_node -+_asn1_set_value (asn1_node node, const void *value, unsigned int len); -+ -+asn1_node _asn1_set_value_m (asn1_node node, void *value, unsigned int len); -+ -+asn1_node -+_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len); -+ -+asn1_node -+_asn1_append_value (asn1_node node, const void *value, unsigned int len); -+ -+asn1_node _asn1_set_name (asn1_node node, const char *name); -+ -+asn1_node _asn1_cpy_name (asn1_node dst, asn1_node_const src); -+ -+asn1_node _asn1_set_right (asn1_node node, asn1_node right); -+ -+asn1_node _asn1_get_last_right (asn1_node_const node); -+ -+void _asn1_remove_node (asn1_node node, unsigned int flags); -+ -+/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */ -+#define LTOSTR_MAX_SIZE 22 -+char *_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]); -+ -+asn1_node _asn1_find_up (asn1_node_const node); -+ -+int _asn1_change_integer_value (asn1_node node); -+ -+#define EXPAND_OBJECT_ID_MAX_RECURSION 16 -+int _asn1_expand_object_id (list_type **list, asn1_node node); -+ -+int _asn1_type_set_config (asn1_node node); -+ -+int _asn1_check_identifier (asn1_node_const node); -+ -+int _asn1_set_default_tag (asn1_node node); -+ -+/******************************************************************/ -+/* Function : _asn1_get_right */ -+/* Description: returns the element pointed by the RIGHT field of */ -+/* a NODE_ASN element. */ -+/* Parameters: */ -+/* node: NODE_ASN element pointer. */ -+/* Return: field RIGHT of NODE. */ -+/******************************************************************/ -+inline static asn1_node -+_asn1_get_right (asn1_node_const node) -+{ -+ if (node == NULL) -+ return NULL; -+ return node->right; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_set_down */ -+/* Description: sets the field DOWN in a NODE_ASN element. */ -+/* Parameters: */ -+/* node: element pointer. */ -+/* down: pointer to a NODE_ASN element that you want be pointed */ -+/* by NODE. */ -+/* Return: pointer to *NODE. */ -+/******************************************************************/ -+inline static asn1_node -+_asn1_set_down (asn1_node node, asn1_node down) -+{ -+ if (node == NULL) -+ return node; -+ node->down = down; -+ if (down) -+ down->left = node; -+ return node; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_get_down */ -+/* Description: returns the element pointed by the DOWN field of */ -+/* a NODE_ASN element. */ -+/* Parameters: */ -+/* node: NODE_ASN element pointer. */ -+/* Return: field DOWN of NODE. */ -+/******************************************************************/ -+inline static asn1_node -+_asn1_get_down (asn1_node_const node) -+{ -+ if (node == NULL) -+ return NULL; -+ return node->down; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_get_name */ -+/* Description: returns the name of a NODE_ASN element. */ -+/* Parameters: */ -+/* node: NODE_ASN element pointer. */ -+/* Return: a null terminated string. */ -+/******************************************************************/ -+inline static char * -+_asn1_get_name (asn1_node_const node) -+{ -+ if (node == NULL) -+ return NULL; -+ return (char *) node->name; -+} -+ -+/******************************************************************/ -+/* Function : _asn1_mod_type */ -+/* Description: change the field TYPE of an NODE_ASN element. */ -+/* The new value is the old one | (bitwise or) the */ -+/* paramener VALUE. */ -+/* Parameters: */ -+/* node: NODE_ASN element pointer. */ -+/* value: the integer value that must be or-ed with the current */ -+/* value of field TYPE. */ -+/* Return: NODE pointer. */ -+/******************************************************************/ -+inline static asn1_node -+_asn1_mod_type (asn1_node node, unsigned int value) -+{ -+ if (node == NULL) -+ return node; -+ node->type |= value; -+ return node; -+} -+ -+#endif -diff --git a/grub-core/lib/libtasn1/lib/structure.h b/grub-core/lib/libtasn1/lib/structure.h -new file mode 100644 -index 00000000000..99e685da07a ---- /dev/null -+++ b/grub-core/lib/libtasn1/lib/structure.h -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * The LIBTASN1 library is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+/*************************************************/ -+/* File: structure.h */ -+/* Description: list of exported object by */ -+/* "structure.c" */ -+/*************************************************/ -+ -+#ifndef _STRUCTURE_H -+#define _STRUCTURE_H -+ -+#include "parser_aux.h" // list_type -+ -+int _asn1_create_static_structure (asn1_node_const pointer, -+ char *output_file_name, char *vector_name); -+ -+asn1_node _asn1_copy_structure3 (asn1_node_const source_node); -+ -+asn1_node _asn1_add_single_node (unsigned int type); -+ -+asn1_node _asn1_find_left (asn1_node_const node); -+ -+int -+_asn1_delete_structure (list_type *e_list, asn1_node *structure, unsigned int flags); -+ -+#endif -diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h -new file mode 100644 -index 00000000000..6fd7a30dc35 ---- /dev/null -+++ b/include/grub/libtasn1.h -@@ -0,0 +1,588 @@ -+/* -+ * Copyright (C) 2002-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * LIBTASN1 is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Lesser General Public License as -+ * published by the Free Software Foundation; either version 2.1 of -+ * the License, or (at your option) any later version. -+ * -+ * LIBTASN1 is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with LIBTASN1; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * -+ */ -+ -+/** -+ * libtasn1:Short_Description: -+ * -+ * GNU ASN.1 library -+ */ -+/** -+ * libtasn1:Long_Description: -+ * -+ * The Libtasn1 library provides Abstract Syntax Notation One (ASN.1, as -+ * specified by the X.680 ITU-T recommendation) parsing and structures -+ * management, and Distinguished Encoding Rules (DER, as per X.690) -+ * encoding and decoding functions. -+ */ -+ -+ -+#ifndef LIBTASN1_H -+#define LIBTASN1_H -+ -+#ifndef ASN1_API -+#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY -+#define ASN1_API __attribute__((__visibility__("default"))) -+#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC -+#define ASN1_API __declspec(dllexport) -+#elif defined _MSC_VER && ! defined ASN1_STATIC -+#define ASN1_API __declspec(dllimport) -+#else -+#define ASN1_API -+#endif -+#endif -+ -+#ifdef __GNUC__ -+# define __LIBTASN1_CONST__ __attribute__((const)) -+# define __LIBTASN1_PURE__ __attribute__((pure)) -+#else -+# define __LIBTASN1_CONST__ -+# define __LIBTASN1_PURE__ -+#endif -+ -+#include -+#include -+#include /* for FILE* */ -+ -+#ifdef __cplusplus -+extern "C" -+{ -+#endif -+ -+/** -+ * ASN1_VERSION: -+ * -+ * Version of the library as a string. -+ */ -+#define ASN1_VERSION "4.16.0" -+ -+/** -+ * ASN1_VERSION_MAJOR: -+ * -+ * Major version number of the library. -+ */ -+#define ASN1_VERSION_MAJOR 4 -+ -+/** -+ * ASN1_VERSION_MINOR: -+ * -+ * Minor version number of the library. -+ */ -+#define ASN1_VERSION_MINOR 16 -+ -+/** -+ * ASN1_VERSION_PATCH: -+ * -+ * Patch version number of the library. -+ */ -+#define ASN1_VERSION_PATCH 0 -+ -+/** -+ * ASN1_VERSION_NUMBER: -+ * -+ * Version number of the library as a number. -+ */ -+#define ASN1_VERSION_NUMBER 0x041000 -+ -+ -+#if defined __GNUC__ && !defined ASN1_INTERNAL_BUILD -+# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -+# if _ASN1_GCC_VERSION >= 30100 -+# define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__)) -+# endif -+#endif -+ -+#ifndef _ASN1_GCC_ATTR_DEPRECATED -+#define _ASN1_GCC_ATTR_DEPRECATED -+#endif -+ -+/*****************************************/ -+/* Errors returned by libtasn1 functions */ -+/*****************************************/ -+#define ASN1_SUCCESS 0 -+#define ASN1_FILE_NOT_FOUND 1 -+#define ASN1_ELEMENT_NOT_FOUND 2 -+#define ASN1_IDENTIFIER_NOT_FOUND 3 -+#define ASN1_DER_ERROR 4 -+#define ASN1_VALUE_NOT_FOUND 5 -+#define ASN1_GENERIC_ERROR 6 -+#define ASN1_VALUE_NOT_VALID 7 -+#define ASN1_TAG_ERROR 8 -+#define ASN1_TAG_IMPLICIT 9 -+#define ASN1_ERROR_TYPE_ANY 10 -+#define ASN1_SYNTAX_ERROR 11 -+#define ASN1_MEM_ERROR 12 -+#define ASN1_MEM_ALLOC_ERROR 13 -+#define ASN1_DER_OVERFLOW 14 -+#define ASN1_NAME_TOO_LONG 15 -+#define ASN1_ARRAY_ERROR 16 -+#define ASN1_ELEMENT_NOT_EMPTY 17 -+#define ASN1_TIME_ENCODING_ERROR 18 -+#define ASN1_RECURSION 19 -+ -+/*************************************/ -+/* Constants used in asn1_visit_tree */ -+/*************************************/ -+#define ASN1_PRINT_NAME 1 -+#define ASN1_PRINT_NAME_TYPE 2 -+#define ASN1_PRINT_NAME_TYPE_VALUE 3 -+#define ASN1_PRINT_ALL 4 -+ -+/*****************************************/ -+/* Constants returned by asn1_read_tag */ -+/*****************************************/ -+#define ASN1_CLASS_UNIVERSAL 0x00 /* old: 1 */ -+#define ASN1_CLASS_APPLICATION 0x40 /* old: 2 */ -+#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /* old: 3 */ -+#define ASN1_CLASS_PRIVATE 0xC0 /* old: 4 */ -+#define ASN1_CLASS_STRUCTURED 0x20 -+ -+/*****************************************/ -+/* Constants returned by asn1_read_tag */ -+/*****************************************/ -+#define ASN1_TAG_BOOLEAN 0x01 -+#define ASN1_TAG_INTEGER 0x02 -+#define ASN1_TAG_SEQUENCE 0x10 -+#define ASN1_TAG_SET 0x11 -+#define ASN1_TAG_OCTET_STRING 0x04 -+#define ASN1_TAG_BIT_STRING 0x03 -+#define ASN1_TAG_UTCTime 0x17 -+#define ASN1_TAG_GENERALIZEDTime 0x18 -+#define ASN1_TAG_OBJECT_ID 0x06 -+#define ASN1_TAG_ENUMERATED 0x0A -+#define ASN1_TAG_NULL 0x05 -+#define ASN1_TAG_GENERALSTRING 0x1B -+#define ASN1_TAG_NUMERIC_STRING 0x12 -+#define ASN1_TAG_IA5_STRING 0x16 -+#define ASN1_TAG_TELETEX_STRING 0x14 -+#define ASN1_TAG_PRINTABLE_STRING 0x13 -+#define ASN1_TAG_UNIVERSAL_STRING 0x1C -+#define ASN1_TAG_BMP_STRING 0x1E -+#define ASN1_TAG_UTF8_STRING 0x0C -+#define ASN1_TAG_VISIBLE_STRING 0x1A -+ -+/** -+ * asn1_node: -+ * -+ * Structure definition used for the node of the tree -+ * that represents an ASN.1 DEFINITION. -+ */ -+typedef struct asn1_node_st asn1_node_st; -+ -+typedef asn1_node_st *asn1_node; -+typedef const asn1_node_st *asn1_node_const; -+ -+/** -+ * ASN1_MAX_NAME_SIZE: -+ * -+ * Maximum number of characters of a name -+ * inside a file with ASN1 definitions. -+ */ -+#define ASN1_MAX_NAME_SIZE 64 -+ -+ -+/** -+ * asn1_static_node: -+ * @name: Node name -+ * @type: Node typ -+ * @value: Node value -+ * -+ * For the on-disk format of ASN.1 trees, created by asn1_parser2array(). -+ */ -+struct asn1_static_node_st -+{ -+ const char *name; /* Node name */ -+ unsigned int type; /* Node type */ -+ const void *value; /* Node value */ -+}; -+typedef struct asn1_static_node_st asn1_static_node; -+ -+/* List of constants for field type of node_asn */ -+#define ASN1_ETYPE_INVALID 0 -+#define ASN1_ETYPE_CONSTANT 1 -+#define ASN1_ETYPE_IDENTIFIER 2 -+#define ASN1_ETYPE_INTEGER 3 -+#define ASN1_ETYPE_BOOLEAN 4 -+#define ASN1_ETYPE_SEQUENCE 5 -+#define ASN1_ETYPE_BIT_STRING 6 -+#define ASN1_ETYPE_OCTET_STRING 7 -+#define ASN1_ETYPE_TAG 8 -+#define ASN1_ETYPE_DEFAULT 9 -+#define ASN1_ETYPE_SIZE 10 -+#define ASN1_ETYPE_SEQUENCE_OF 11 -+#define ASN1_ETYPE_OBJECT_ID 12 -+#define ASN1_ETYPE_ANY 13 -+#define ASN1_ETYPE_SET 14 -+#define ASN1_ETYPE_SET_OF 15 -+#define ASN1_ETYPE_DEFINITIONS 16 -+#define ASN1_ETYPE_CHOICE 18 -+#define ASN1_ETYPE_IMPORTS 19 -+#define ASN1_ETYPE_NULL 20 -+#define ASN1_ETYPE_ENUMERATED 21 -+#define ASN1_ETYPE_GENERALSTRING 27 -+#define ASN1_ETYPE_NUMERIC_STRING 28 -+#define ASN1_ETYPE_IA5_STRING 29 -+#define ASN1_ETYPE_TELETEX_STRING 30 -+#define ASN1_ETYPE_PRINTABLE_STRING 31 -+#define ASN1_ETYPE_UNIVERSAL_STRING 32 -+#define ASN1_ETYPE_BMP_STRING 33 -+#define ASN1_ETYPE_UTF8_STRING 34 -+#define ASN1_ETYPE_VISIBLE_STRING 35 -+#define ASN1_ETYPE_UTC_TIME 36 -+#define ASN1_ETYPE_GENERALIZED_TIME 37 -+ -+/** -+ * ASN1_DELETE_FLAG_ZEROIZE: -+ * -+ * Used by: asn1_delete_structure2() -+ * -+ * Zeroize values prior to deinitialization. -+ */ -+#define ASN1_DELETE_FLAG_ZEROIZE 1 -+ -+/** -+ * ASN1_DECODE_FLAG_ALLOW_PADDING: -+ * -+ * Used by: asn1_der_decoding2() -+ * -+ * This flag would allow arbitrary data past the DER data. -+ */ -+#define ASN1_DECODE_FLAG_ALLOW_PADDING 1 -+/** -+ * ASN1_DECODE_FLAG_STRICT_DER: -+ * -+ * Used by: asn1_der_decoding2() -+ * -+ * This flag would ensure that no BER decoding takes place. -+ */ -+#define ASN1_DECODE_FLAG_STRICT_DER (1<<1) -+/** -+ * ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME: -+ * -+ * Used by: asn1_der_decoding2() -+ * -+ * This flag will tolerate Time encoding errors when in strict DER. -+ */ -+#define ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME (1<<2) -+ -+ -+/** -+ * asn1_data_node_st: -+ * @name: Node name -+ * @value: Node value -+ * @value_len: Node value size -+ * @type: Node value type (ASN1_ETYPE_*) -+ * -+ * Data node inside a #asn1_node structure. -+ */ -+struct asn1_data_node_st -+{ -+ const char *name; /* Node name */ -+ const void *value; /* Node value */ -+ unsigned int value_len; /* Node value size */ -+ unsigned int type; /* Node value type (ASN1_ETYPE_*) */ -+}; -+typedef struct asn1_data_node_st asn1_data_node_st; -+ -+/***********************************/ -+/* Fixed constants */ -+/***********************************/ -+ -+/** -+ * ASN1_MAX_ERROR_DESCRIPTION_SIZE: -+ * -+ * Maximum number of characters -+ * of a description message -+ * (null character included). -+ */ -+#define ASN1_MAX_ERROR_DESCRIPTION_SIZE 128 -+ -+/***********************************/ -+/* Functions definitions */ -+/***********************************/ -+ -+extern ASN1_API int -+ asn1_parser2tree (const char *file, -+ asn1_node * definitions, char *error_desc); -+ -+extern ASN1_API int -+ asn1_parser2array (const char *inputFileName, -+ const char *outputFileName, -+ const char *vectorName, char *error_desc); -+ -+extern ASN1_API int -+ asn1_array2tree (const asn1_static_node * array, -+ asn1_node * definitions, char *errorDescription); -+ -+extern ASN1_API void -+ asn1_print_structure (FILE * out, asn1_node_const structure, -+ const char *name, int mode); -+ -+extern ASN1_API int -+ asn1_create_element (asn1_node_const definitions, -+ const char *source_name, asn1_node * element); -+ -+extern ASN1_API int asn1_delete_structure (asn1_node * structure); -+ -+extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int flags); -+ -+extern ASN1_API int -+ asn1_delete_element (asn1_node structure, const char *element_name); -+ -+extern ASN1_API int -+ asn1_write_value (asn1_node node_root, const char *name, -+ const void *ivalue, int len); -+ -+extern ASN1_API int -+ asn1_read_value (asn1_node_const root, const char *name, -+ void *ivalue, int *len); -+ -+extern ASN1_API int -+ asn1_read_value_type (asn1_node_const root, const char *name, -+ void *ivalue, int *len, unsigned int *etype); -+ -+extern ASN1_API int -+ asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data); -+ -+extern ASN1_API int -+ asn1_number_of_elements (asn1_node_const element, const char *name, int *num); -+ -+extern ASN1_API int -+ asn1_der_coding (asn1_node_const element, const char *name, -+ void *ider, int *len, char *ErrorDescription); -+ -+extern ASN1_API int -+ asn1_der_decoding2 (asn1_node *element, const void *ider, -+ int *max_ider_len, unsigned int flags, -+ char *errorDescription); -+ -+extern ASN1_API int -+ asn1_der_decoding (asn1_node * element, const void *ider, -+ int ider_len, char *errorDescription); -+ -+/* Do not use. Use asn1_der_decoding() instead. */ -+extern ASN1_API int -+ asn1_der_decoding_element (asn1_node * structure, -+ const char *elementName, -+ const void *ider, int len, -+ char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED; -+ -+extern ASN1_API int -+ asn1_der_decoding_startEnd (asn1_node element, -+ const void *ider, int ider_len, -+ const char *name_element, -+ int *start, int *end); -+ -+extern ASN1_API int -+ asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element); -+ -+extern ASN1_API int -+ asn1_expand_octet_string (asn1_node_const definitions, -+ asn1_node * element, -+ const char *octetName, const char *objectName); -+ -+extern ASN1_API int -+ asn1_read_tag (asn1_node_const root, const char *name, -+ int *tagValue, int *classValue); -+ -+extern ASN1_API const char *asn1_find_structure_from_oid (asn1_node_const -+ definitions, -+ const char -+ *oidValue); -+ -+__LIBTASN1_PURE__ -+extern ASN1_API const char *asn1_check_version (const char *req_version); -+ -+__LIBTASN1_PURE__ -+extern ASN1_API const char *asn1_strerror (int error); -+ -+extern ASN1_API void asn1_perror (int error); -+ -+#define ASN1_MAX_TAG_SIZE 4 -+#define ASN1_MAX_LENGTH_SIZE 9 -+#define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE) -+extern ASN1_API long -+ asn1_get_length_der (const unsigned char *der, int der_len, int *len); -+ -+extern ASN1_API long -+ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len); -+ -+extern ASN1_API void -+ asn1_length_der (unsigned long int len, unsigned char *der, int *der_len); -+ -+/* Other utility functions. */ -+ -+extern ASN1_API -+ int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, -+ const unsigned char **str, -+ unsigned int *str_len); -+ -+extern ASN1_API -+ int asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, -+ unsigned int _der_len, -+ unsigned char **str, -+ unsigned int *str_len, -+ unsigned int *ber_len); -+ -+extern ASN1_API int -+ asn1_encode_simple_der (unsigned int etype, const unsigned char *str, -+ unsigned int str_len, unsigned char *tl, -+ unsigned int *tl_len); -+ -+extern ASN1_API asn1_node -+ asn1_find_node (asn1_node_const pointer, const char *name); -+ -+extern ASN1_API int -+ asn1_copy_node (asn1_node dst, const char *dst_name, -+ asn1_node_const src, const char *src_name); -+extern ASN1_API asn1_node -+ asn1_dup_node (asn1_node_const src, const char *src_name); -+ -+/* Internal and low-level DER utility functions. */ -+ -+extern ASN1_API int -+ asn1_get_tag_der (const unsigned char *der, int der_len, -+ unsigned char *cls, int *len, unsigned long *tag); -+ -+extern ASN1_API void -+ asn1_octet_der (const unsigned char *str, int str_len, -+ unsigned char *der, int *der_len); -+ -+extern ASN1_API int -+ asn1_get_octet_der (const unsigned char *der, int der_len, -+ int *ret_len, unsigned char *str, -+ int str_size, int *str_len); -+ -+extern ASN1_API void asn1_bit_der (const unsigned char *str, int bit_len, -+ unsigned char *der, int *der_len); -+ -+extern ASN1_API int -+ asn1_get_bit_der (const unsigned char *der, int der_len, -+ int *ret_len, unsigned char *str, -+ int str_size, int *bit_len); -+ -+extern ASN1_API int -+ asn1_get_object_id_der (const unsigned char *der, -+ int der_len, int *ret_len, -+ char *str, int str_size); -+ -+extern ASN1_API int -+ asn1_object_id_der (const char *str, unsigned char *der, int *der_len, -+ unsigned flags); -+ -+/* Compatibility types */ -+ -+/** -+ * asn1_retCode: -+ * -+ * Type formerly returned by libtasn1 functions. -+ * -+ * Deprecated: 3.0: Use int instead. -+ */ -+typedef int asn1_retCode; -+ -+/** -+ * node_asn_struct: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_node instead. -+ */ -+#define node_asn_struct asn1_node_st -+ -+/** -+ * node_asn: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_node instead. -+ */ -+#define node_asn asn1_node_st -+ -+/** -+ * ASN1_TYPE: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_node instead. -+ */ -+#define ASN1_TYPE asn1_node -+ -+/** -+ * ASN1_TYPE_EMPTY: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use NULL instead. -+ */ -+#define ASN1_TYPE_EMPTY NULL -+ -+/** -+ * static_struct_asn: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_static_node instead. -+ */ -+#define static_struct_asn asn1_static_node_st -+ -+/** -+ * ASN1_ARRAY_TYPE: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_static_node instead. -+ */ -+#define ASN1_ARRAY_TYPE asn1_static_node -+ -+/** -+ * asn1_static_node_t: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_static_node instead. -+ */ -+#define asn1_static_node_t asn1_static_node -+ -+/** -+ * node_data_struct: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_data_node_st instead. -+ */ -+#define node_data_struct asn1_data_node_st -+ -+/** -+ * ASN1_DATA_NODE: -+ * -+ * Compat #define. -+ * -+ * Deprecated: 3.0: Use #asn1_data_node_st instead. -+ */ -+#define ASN1_DATA_NODE asn1_data_node_st -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* LIBTASN1_H */ -diff --git a/grub-core/lib/libtasn1/LICENSE b/grub-core/lib/libtasn1/LICENSE -new file mode 100644 -index 00000000000..e8b3628db9b ---- /dev/null -+++ b/grub-core/lib/libtasn1/LICENSE -@@ -0,0 +1,16 @@ -+LICENSING -+========= -+ -+The libtasn1 library is released under the GNU Lesser General Public -+License (LGPL) version 2.1 or later; see [COPYING.LESSER](doc/COPYING.LESSER) -+for the license terms. -+ -+The GNU LGPL applies to the main libtasn1 library, while the -+included applications library are under the GNU GPL version 3. -+The libtasn1 library is located in the lib directory, while the applications -+in src/. -+ -+The documentation in doc/ is under the GNU FDL license 1.3. -+ -+For any copyright year range specified as YYYY-ZZZZ in this package -+note that the range specifies every single year in that closed interval. -diff --git a/grub-core/lib/libtasn1/README.md b/grub-core/lib/libtasn1/README.md -new file mode 100644 -index 00000000000..50a8642296c ---- /dev/null -+++ b/grub-core/lib/libtasn1/README.md -@@ -0,0 +1,91 @@ -+|Branch|CI system|Status| -+|:----:|:-------:|-----:| -+|Master|Gitlab|[![build status](https://gitlab.com/gnutls/libtasn1/badges/master/pipeline.svg)](https://gitlab.com/gnutls/libtasn1/commits/master)[![coverage report](https://gitlab.com/gnutls/libtasn1/badges/master/coverage.svg)](https://gnutls.gitlab.io/libtasn1/coverage)| -+ -+# libtasn1 -+ -+This is GNU Libtasn1, a small ASN.1 library. -+ -+The C library (libtasn1.*) is licensed under the GNU Lesser General -+Public License version 2.1 or later. See the file COPYING.LIB. -+ -+The command line tool, self tests, examples, and other auxilliary -+files, are licensed under the GNU General Public License version 3.0 -+or later. See the file COPYING. -+ -+## Building the library -+ -+We require several tools to build the software, including: -+ -+* [Make](https://www.gnu.org/software/make/) -+* [Automake](https://www.gnu.org/software/automake/) (use 1.11.3 or later) -+* [Autoconf](https://www.gnu.org/software/autoconf/) -+* [Libtool](https://www.gnu.org/software/libtool/) -+* [Texinfo](https://www.gnu.org/software/texinfo/) -+* [help2man](http://www.gnu.org/software/help2man/) -+* [Tar](https://www.gnu.org/software/tar/) -+* [Gzip](https://www.gnu.org/software/gzip/) -+* [bison](https://www.gnu.org/software/bison/) -+* [Texlive & epsf](https://www.tug.org/texlive/) (for PDF manual) -+* [GTK-DOC](https://www.gtk.org/gtk-doc/) (for API manual) -+* [Git](https://git-scm.com/) -+* [libabigail](https://pagure.io/libabigail/) (for abi comparison in make dist) -+* [Valgrind](https://valgrind.org/) (optional) -+ -+The required software is typically distributed with your operating -+system, and the instructions for installing them differ. Here are -+some hints: -+ -+gNewSense/Debian/Ubuntu: -+``` -+sudo apt-get install make git-core autoconf automake libtool -+sudo apt-get install texinfo texlive texlive-generic-recommended texlive-extra-utils -+sudo apt-get install help2man gtk-doc-tools valgrind abigail-tools -+``` -+ -+The next step is to run autoreconf, ./configure, etc: -+ -+``` -+$ ./bootstrap -+``` -+ -+Then build the project normally: -+ -+``` -+$ make -+$ make check -+``` -+ -+Happy hacking! -+ -+ -+## Manual -+ -+The manual is in the `doc/` directory of the release. You can also browse -+the manual online at: -+ -+ - https://gnutls.gitlab.io/libtasn1/ -+ -+ -+## Code coverage report -+ -+The coverage report is at: -+ -+ - https://gnutls.gitlab.io/libtasn1/coverage -+ -+ -+## Issue trackers -+ -+ - [Main issue tracker](https://gitlab.com/gnutls/libtasn1/issues) -+ - [oss-fuzz found issues](https://bugs.chromium.org/p/oss-fuzz/issues/list?q=libtasn1&can=2) -+ -+ -+## Homepage -+ -+The project homepage at the gnu site is at: -+ -+http://www.gnu.org/software/libtasn1/ -+ -+ -+For any copyright year range specified as YYYY-ZZZZ in this package -+note that the range specifies every single year in that closed interval. diff --git a/SOURCES/0186-normal-main-Discover-the-device-to-read-the-config-f.patch b/SOURCES/0186-normal-main-Discover-the-device-to-read-the-config-f.patch new file mode 100644 index 0000000..2c9ca3a --- /dev/null +++ b/SOURCES/0186-normal-main-Discover-the-device-to-read-the-config-f.patch @@ -0,0 +1,123 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 30 Aug 2021 12:31:18 +0200 +Subject: [PATCH] normal/main: Discover the device to read the config from as a + fallback + +The GRUB core.img is generated locally, when this is done the grub2-probe +tool figures out the device and partition that needs to be read to parse +the GRUB configuration file. + +But in some cases the core.img can't be generated on the host and instead +has to be done at package build time. For example, if needs to get signed +with a key that's only available on the package building infrastructure. + +If that's the case, the prefix variable won't have a device and partition +but only a directory path. So there's no way for GRUB to know from which +device has to read the configuration file. + +To allow GRUB to continue working on that scenario, fallback to iterating +over all the available devices, if reading the config failed when using +the prefix and fw_path variables. + +Signed-off-by: Javier Martinez Canillas +--- + grub-core/normal/main.c | 58 +++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 51 insertions(+), 7 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 7de9e4c36d..8f5fd81003 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -337,18 +337,13 @@ grub_enter_normal_mode (const char *config) + } + + static grub_err_t +-grub_try_normal (const char *variable) ++grub_try_normal_prefix (const char *prefix) + { + char *config; +- const char *prefix; + grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; + const char *net_search_cfg; + int disable_net_search = 0; + +- prefix = grub_env_get (variable); +- if (!prefix) +- return GRUB_ERR_FILE_NOT_FOUND; +- + net_search_cfg = grub_env_get ("feature_net_search_cfg"); + if (net_search_cfg && net_search_cfg[0] == 'n') + disable_net_search = 1; +@@ -362,7 +357,7 @@ grub_try_normal (const char *variable) + config = grub_malloc (config_len); + + if (! config) +- return GRUB_ERR_FILE_NOT_FOUND; ++ return err; + + grub_snprintf (config, config_len, "%s/grub.cfg", prefix); + err = grub_net_search_config_file (config); +@@ -391,6 +386,53 @@ grub_try_normal (const char *variable) + return err; + } + ++static int ++grub_try_normal_dev (const char *name, void *data) ++{ ++ grub_err_t err; ++ const char *prefix = grub_xasprintf ("(%s)%s", name, (char *)data); ++ ++ if (!prefix) ++ return 0; ++ ++ err = grub_try_normal_prefix (prefix); ++ if (err == GRUB_ERR_NONE) ++ return 1; ++ ++ return 0; ++} ++ ++static grub_err_t ++grub_try_normal_discover (void) ++{ ++ char *prefix = grub_env_get ("prefix"); ++ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; ++ ++ if (!prefix) ++ return err; ++ ++ if (grub_device_iterate (grub_try_normal_dev, (void *)prefix)) ++ return GRUB_ERR_NONE; ++ ++ return err; ++} ++ ++static grub_err_t ++grub_try_normal (const char *variable) ++{ ++ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; ++ const char *prefix; ++ ++ if (!variable) ++ return err; ++ ++ prefix = grub_env_get (variable); ++ if (!prefix) ++ return err; ++ ++ return grub_try_normal_prefix (prefix); ++} ++ + /* Enter normal mode from rescue mode. */ + static grub_err_t + grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), +@@ -405,6 +447,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + err = grub_try_normal ("fw_path"); + if (err == GRUB_ERR_FILE_NOT_FOUND) + err = grub_try_normal ("prefix"); ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ err = grub_try_normal_discover (); + if (err == GRUB_ERR_FILE_NOT_FOUND) + grub_enter_normal_mode (0); + } diff --git a/SOURCES/0187-libtasn1-disable-code-not-needed-in-grub.patch b/SOURCES/0187-libtasn1-disable-code-not-needed-in-grub.patch deleted file mode 100644 index 00f5588..0000000 --- a/SOURCES/0187-libtasn1-disable-code-not-needed-in-grub.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 1 May 2020 17:12:23 +1000 -Subject: [PATCH] libtasn1: disable code not needed in grub - -We don't expect to be able to write ASN.1, only read it, -so we can disable some code. - -Do that with #if 0/#endif, rather than deletion. This means -that the difference between upstream and grub is smaller, -which should make updating libtasn1 easier in the future. - -With these exclusions we also avoid the need for minmax.h, -which is convenient because it means we don't have to -import it from gnulib. - -Signed-off-by: Daniel Axtens ---- - grub-core/lib/libtasn1/lib/coding.c | 12 ++++++++++-- - grub-core/lib/libtasn1/lib/decoding.c | 2 ++ - grub-core/lib/libtasn1/lib/element.c | 4 ++-- - grub-core/lib/libtasn1/lib/errors.c | 3 +++ - grub-core/lib/libtasn1/lib/structure.c | 10 ++++++---- - include/grub/libtasn1.h | 15 +++++++++++++++ - 6 files changed, 38 insertions(+), 8 deletions(-) - -diff --git a/grub-core/lib/libtasn1/lib/coding.c b/grub-core/lib/libtasn1/lib/coding.c -index 245ea64cf0a..52def598368 100644 ---- a/grub-core/lib/libtasn1/lib/coding.c -+++ b/grub-core/lib/libtasn1/lib/coding.c -@@ -30,11 +30,11 @@ - #include "parser_aux.h" - #include - #include "element.h" --#include "minmax.h" - #include - - #define MAX_TAG_LEN 16 - -+#if 0 - /******************************************************/ - /* Function : _asn1_error_description_value_not_found */ - /* Description: creates the ErrorDescription string */ -@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node, - Estrcat (ErrorDescription, "' not found"); - - } -+#endif - - /** - * asn1_length_der: -@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const unsigned char *str, - return ASN1_SUCCESS; - } - -+#if 0 - /******************************************************/ - /* Function : _asn1_time_der */ - /* Description: creates the DER coding for a TIME */ -@@ -281,7 +283,7 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned char *der, - - return ASN1_SUCCESS; - } -- -+#endif - - /* - void -@@ -520,6 +522,7 @@ asn1_bit_der (const unsigned char *str, int bit_len, - } - - -+#if 0 - /******************************************************/ - /* Function : _asn1_complete_explicit_tag */ - /* Description: add the length coding to the EXPLICIT */ -@@ -596,6 +599,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der, - - return ASN1_SUCCESS; - } -+#endif - - const tag_and_class_st _asn1_tags[] = { - [ASN1_ETYPE_GENERALSTRING] = -@@ -648,6 +652,8 @@ const tag_and_class_st _asn1_tags[] = { - - unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]); - -+ -+#if 0 - /******************************************************/ - /* Function : _asn1_insert_tag_der */ - /* Description: creates the DER coding of tags of one */ -@@ -1413,3 +1419,5 @@ error: - asn1_delete_structure (&node); - return err; - } -+ -+#endif -\ No newline at end of file -diff --git a/grub-core/lib/libtasn1/lib/decoding.c b/grub-core/lib/libtasn1/lib/decoding.c -index ff04eb778cb..42f9a92b5d4 100644 ---- a/grub-core/lib/libtasn1/lib/decoding.c -+++ b/grub-core/lib/libtasn1/lib/decoding.c -@@ -1613,6 +1613,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len, - return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription); - } - -+#if 0 - /** - * asn1_der_decoding_element: - * @structure: pointer to an ASN1 structure -@@ -1643,6 +1644,7 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName, - { - return asn1_der_decoding(structure, ider, len, errorDescription); - } -+#endif - - /** - * asn1_der_decoding_startEnd: -diff --git a/grub-core/lib/libtasn1/lib/element.c b/grub-core/lib/libtasn1/lib/element.c -index 997eb2725dc..539008d8e94 100644 ---- a/grub-core/lib/libtasn1/lib/element.c -+++ b/grub-core/lib/libtasn1/lib/element.c -@@ -191,7 +191,7 @@ _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) - return ASN1_SUCCESS; - } - -- -+#if 0 - /** - * asn1_write_value: - * @node_root: pointer to a structure -@@ -645,7 +645,7 @@ asn1_write_value (asn1_node node_root, const char *name, - - return ASN1_SUCCESS; - } -- -+#endif - - #define PUT_VALUE( ptr, ptr_size, data, data_size) \ - *len = data_size; \ -diff --git a/grub-core/lib/libtasn1/lib/errors.c b/grub-core/lib/libtasn1/lib/errors.c -index cee74daf795..42785e8622b 100644 ---- a/grub-core/lib/libtasn1/lib/errors.c -+++ b/grub-core/lib/libtasn1/lib/errors.c -@@ -57,6 +57,8 @@ static const libtasn1_error_entry error_algorithms[] = { - {0, 0} - }; - -+ -+#if 0 - /** - * asn1_perror: - * @error: is an error returned by a libtasn1 function. -@@ -73,6 +75,7 @@ asn1_perror (int error) - const char *str = asn1_strerror (error); - fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)"); - } -+#endif - - /** - * asn1_strerror: -diff --git a/grub-core/lib/libtasn1/lib/structure.c b/grub-core/lib/libtasn1/lib/structure.c -index 8189c56a4c9..fcfde01a393 100644 ---- a/grub-core/lib/libtasn1/lib/structure.c -+++ b/grub-core/lib/libtasn1/lib/structure.c -@@ -76,7 +76,7 @@ _asn1_find_left (asn1_node_const node) - return node->left; - } - -- -+#if 0 - int - _asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, - char *vector_name) -@@ -155,7 +155,7 @@ _asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, - - return ASN1_SUCCESS; - } -- -+#endif - - /** - * asn1_array2tree: -@@ -718,7 +718,7 @@ asn1_create_element (asn1_node_const definitions, const char *source_name, - return res; - } - -- -+#if 0 - /** - * asn1_print_structure: - * @out: pointer to the output file (e.g. stdout). -@@ -1058,7 +1058,7 @@ asn1_print_structure (FILE * out, asn1_node_const structure, const char *name, - } - } - } -- -+#endif - - - /** -@@ -1153,6 +1153,7 @@ asn1_find_structure_from_oid (asn1_node_const definitions, const char *oidValue) - return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ - } - -+#if 0 - /** - * asn1_copy_node: - * @dst: Destination asn1 node. -@@ -1202,6 +1203,7 @@ asn1_copy_node (asn1_node dst, const char *dst_name, - - return result; - } -+#endif - - /** - * asn1_dup_node: -diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h -index 6fd7a30dc35..785eda2ae3f 100644 ---- a/include/grub/libtasn1.h -+++ b/include/grub/libtasn1.h -@@ -319,6 +319,8 @@ typedef struct asn1_data_node_st asn1_data_node_st; - /* Functions definitions */ - /***********************************/ - -+/* These functions are not used in grub and should not be referenced. */ -+#if 0 - extern ASN1_API int - asn1_parser2tree (const char *file, - asn1_node * definitions, char *error_desc); -@@ -327,14 +329,17 @@ extern ASN1_API int - asn1_parser2array (const char *inputFileName, - const char *outputFileName, - const char *vectorName, char *error_desc); -+#endif - - extern ASN1_API int - asn1_array2tree (const asn1_static_node * array, - asn1_node * definitions, char *errorDescription); - -+#if 0 - extern ASN1_API void - asn1_print_structure (FILE * out, asn1_node_const structure, - const char *name, int mode); -+#endif - - extern ASN1_API int - asn1_create_element (asn1_node_const definitions, -@@ -347,9 +352,11 @@ extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int - extern ASN1_API int - asn1_delete_element (asn1_node structure, const char *element_name); - -+#if 0 - extern ASN1_API int - asn1_write_value (asn1_node node_root, const char *name, - const void *ivalue, int len); -+#endif - - extern ASN1_API int - asn1_read_value (asn1_node_const root, const char *name, -@@ -365,9 +372,11 @@ extern ASN1_API int - extern ASN1_API int - asn1_number_of_elements (asn1_node_const element, const char *name, int *num); - -+#if 0 - extern ASN1_API int - asn1_der_coding (asn1_node_const element, const char *name, - void *ider, int *len, char *ErrorDescription); -+#endif - - extern ASN1_API int - asn1_der_decoding2 (asn1_node *element, const void *ider, -@@ -378,12 +387,14 @@ extern ASN1_API int - asn1_der_decoding (asn1_node * element, const void *ider, - int ider_len, char *errorDescription); - -+#if 0 - /* Do not use. Use asn1_der_decoding() instead. */ - extern ASN1_API int - asn1_der_decoding_element (asn1_node * structure, - const char *elementName, - const void *ider, int len, - char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED; -+#endif - - extern ASN1_API int - asn1_der_decoding_startEnd (asn1_node element, -@@ -408,13 +419,17 @@ extern ASN1_API const char *asn1_find_structure_from_oid (asn1_node_const - const char - *oidValue); - -+#if 0 - __LIBTASN1_PURE__ - extern ASN1_API const char *asn1_check_version (const char *req_version); -+#endif - - __LIBTASN1_PURE__ - extern ASN1_API const char *asn1_strerror (int error); - -+#if 0 - extern ASN1_API void asn1_perror (int error); -+#endif - - #define ASN1_MAX_TAG_SIZE 4 - #define ASN1_MAX_LENGTH_SIZE 9 diff --git a/SOURCES/0187-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch b/SOURCES/0187-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch new file mode 100644 index 0000000..b9bc140 --- /dev/null +++ b/SOURCES/0187-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 19 Jul 2021 14:35:55 +1000 +Subject: [PATCH] powerpc: adjust setting of prefix for signed binary case + +On RHEL-signed powerpc grub, we sign a grub with -p /grub2 and expect +that there's a boot partition. + +Unfortunately grub_set_prefix_and_root tries to convert this to +($fwdevice)/grub2. This ends up being (ieee1275/disk)/grub2 and that +falls apart pretty quickly - there's no file-system on ieee1275/disk, +and it makes the search routine try things like +(ieee1275/disk,msdos2)(ieee1275/disk)/grub2 which also doesn't work. + +Detect if we would be about to create (ieee1275/disk)/path and don't: +preserve a prefix of /path instead and hope the search later finds us. + +Related: rhbz#1899864 + +Signed-off-by: Daniel Axtens +[rharwood@redhat.com: squash in fixup commit] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 44 insertions(+), 5 deletions(-) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index b573be6650..3fc3401472 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -216,13 +216,52 @@ grub_set_prefix_and_root (void) + if (device) + { + char *prefix_set; +- +- prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); +- if (prefix_set) ++ ++#ifdef __powerpc__ ++ /* We have to be careful here on powerpc-ieee1275 + signed grub. We ++ will have signed something with a prefix that doesn't have a device ++ because we cannot know in advance what partition we're on. ++ ++ We will have had !device earlier, so we will have set device=fwdevice ++ However, we want to make sure we do not end up setting prefix to be ++ ($fwdevice)/path, because we will then end up trying to boot or search ++ based on a prefix of (ieee1275/disk)/path, which will not work because ++ it's missing a partition. ++ ++ Also: ++ - You can end up with a device with an FS directly on it, without ++ a partition, e.g. ieee1275/cdrom. ++ ++ - powerpc-ieee1275 + grub-install sets e.g. prefix=(,gpt2)/path, ++ which will have now been extended to device=$fwdisk,partition ++ and path=/path ++ ++ - PowerVM will give us device names like ++ ieee1275//vdevice/v-scsi@3000006c/disk@8100000000000000 ++ and we don't want to try to encode some sort of truth table about ++ what sorts of paths represent disks with partition tables and those ++ without partition tables. ++ ++ So we act unless there is a comma in the device, which would indicate ++ a partition has already been specified. ++ ++ (If we only have a path, the code in normal to discover config files ++ will try both without partitions and then with any partitions so we ++ will cover both CDs and HDs.) ++ */ ++ if (grub_strchr (device, ',') == NULL) ++ grub_env_set ("prefix", path); ++ else ++#endif + { +- grub_env_set ("prefix", prefix_set); +- grub_free (prefix_set); ++ prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); ++ if (prefix_set) ++ { ++ grub_env_set ("prefix", prefix_set); ++ grub_free (prefix_set); ++ } + } ++ + grub_env_set ("root", device); + } + diff --git a/SOURCES/0188-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch b/SOURCES/0188-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch new file mode 100644 index 0000000..7fc40f1 --- /dev/null +++ b/SOURCES/0188-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Erwan Velu +Date: Wed, 25 Aug 2021 15:31:52 +0200 +Subject: [PATCH] fs/xfs: Fix unreadable filesystem with v4 superblock + +The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) +introduced the bigtime support by adding some features in v3 inodes. +This change extended grub_xfs_inode struct by 76 bytes but also changed +the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this +commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes +XFS_V2_INODE_SIZE becomes 16 bytes too small. + +As a result, the data structures aren't properly aligned and the GRUB +generates "attempt to read or write outside of partition" errors when +trying to read the XFS filesystem: + + GNU GRUB version 2.11 + .... + grub> set debug=efi,gpt,xfs + grub> insmod part_gpt + grub> ls (hd0,gpt1)/ + partmap/gpt.c:93: Read a valid GPT header + partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840 + error: attempt to read or write outside of partition. + +This commit change the XFS_V2_INODE_SIZE computation by subtracting 76 +bytes instead of 92 bytes from the actual size of grub_xfs_inode struct. +This 76 bytes value comes from added members: + 20 grub_uint8_t unused5 + 1 grub_uint64_t flags2 + 48 grub_uint8_t unused6 + +This patch explicitly splits the v2 and v3 parts of the structure. +The unused4 is still ending of the v2 structures and the v3 starts +at unused5. Thanks to this we will avoid future corruptions of v2 +or v3 inodes. + +The XFS_V2_INODE_SIZE is returning to its expected size and the +filesystem is back to a readable state: + + GNU GRUB version 2.11 + .... + grub> set debug=efi,gpt,xfs + grub> insmod part_gpt + grub> ls (hd0,gpt1)/ + partmap/gpt.c:93: Read a valid GPT header + partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:931: Reading sb + fs/xfs.c:270: Validating superblock + fs/xfs.c:295: XFS v4 superblock detected + fs/xfs.c:962: Reading root ino 128 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (128) - 64, 0 + fs/xfs.c:515: Reading inode (131) - 64, 768 + efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0 + grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024 + grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816 + grub> + +Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) + +Signed-off-by: Erwan Velu +Tested-by: Carlos Maiolino +Reviewed-by: Daniel Kiper +(cherry picked from commit a4b495520e4dc41a896a8b916a64eda9970c50ea) +--- + grub-core/fs/xfs.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 0f524c3a8a..e3816d1ec4 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy + grub_uint32_t nanosec; + } GRUB_PACKED; + ++/* ++ * The struct grub_xfs_inode layout was taken from the ++ * struct xfs_dinode_core which is described here: ++ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf ++ */ + struct grub_xfs_inode + { + grub_uint8_t magic[2]; +@@ -208,14 +213,15 @@ struct grub_xfs_inode + grub_uint32_t nextents; + grub_uint16_t unused3; + grub_uint8_t fork_offset; +- grub_uint8_t unused4[37]; ++ grub_uint8_t unused4[17]; /* Last member of inode v2. */ ++ grub_uint8_t unused5[20]; /* First member of inode v3. */ + grub_uint64_t flags2; +- grub_uint8_t unused5[48]; ++ grub_uint8_t unused6[48]; /* Last member of inode v3. */ + } GRUB_PACKED; + + #define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) +-/* Size of struct grub_xfs_inode until fork_offset (included). */ +-#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) ++/* Size of struct grub_xfs_inode v2, up to unused4 member included. */ ++#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) + + struct grub_xfs_dirblock_tail + { diff --git a/SOURCES/0188-libtasn1-changes-for-grub-compatibility.patch b/SOURCES/0188-libtasn1-changes-for-grub-compatibility.patch deleted file mode 100644 index 9b2275c..0000000 --- a/SOURCES/0188-libtasn1-changes-for-grub-compatibility.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 1 May 2020 20:44:29 +1000 -Subject: [PATCH] libtasn1: changes for grub compatibility - -Do a few things to make libtasn1 compile as part of grub: - - - replace strcat. grub removed strcat so replace it with the appropriate - calls to memcpy and strlen. - - - replace c_isdigit with grub_isdigit (and don't import c-ctype from - gnulib) grub_isdigit provides the same functionality as c_isdigit: it - determines if the input is an ASCII digit without regard for locale. - - - replace GL_ATTRIBUTE_PURE with __attribute__((pure)) which been - supported since gcc-2.96. This avoids messing around with gnulib. - - - adjust libtasn1.h: drop the ASN1_API logic, it's not needed for our - modules. Unconditionally support const and pure attributes and adjust - header paths. - - - adjust header paths to "grub/libtasn1.h". - - - replace a 64 bit division with a call to grub_divmod64, preventing - creation of __udivdi3 calls on 32 bit platforms. - -Signed-off-by: Daniel Axtens ---- - grub-core/lib/libtasn1/lib/decoding.c | 11 ++++++----- - grub-core/lib/libtasn1/lib/element.c | 3 ++- - grub-core/lib/libtasn1/lib/gstr.c | 4 ++-- - grub-core/lib/libtasn1/lib/parser_aux.c | 7 ++++--- - grub-core/lib/libtasn1/lib/int.h | 4 ++-- - include/grub/libtasn1.h | 26 ++++++-------------------- - 6 files changed, 22 insertions(+), 33 deletions(-) - -diff --git a/grub-core/lib/libtasn1/lib/decoding.c b/grub-core/lib/libtasn1/lib/decoding.c -index 42f9a92b5d4..7856858b272 100644 ---- a/grub-core/lib/libtasn1/lib/decoding.c -+++ b/grub-core/lib/libtasn1/lib/decoding.c -@@ -32,7 +32,8 @@ - #include - #include - #include --#include -+ -+#define c_isdigit grub_isdigit - - #ifdef DEBUG - # define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) -@@ -2008,8 +2009,8 @@ asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, - (p2->type & CONST_ASSIGN)) - { - strcpy (name, definitions->name); -- strcat (name, "."); -- strcat (name, p2->name); -+ memcpy (name + strlen(name), ".", sizeof(" . ")); -+ memcpy (name + strlen(name), p2->name, strlen(p2->name) + 1); - - len = sizeof (value); - result = asn1_read_value (definitions, name, value, &len); -@@ -2026,8 +2027,8 @@ asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, - if (p2) - { - strcpy (name, definitions->name); -- strcat (name, "."); -- strcat (name, p2->name); -+ memcpy (name + strlen(name), ".", sizeof(" . ")); -+ memcpy (name + strlen(name), p2->name, strlen(p2->name) + 1); - - result = asn1_create_element (definitions, name, &aux); - if (result == ASN1_SUCCESS) -diff --git a/grub-core/lib/libtasn1/lib/element.c b/grub-core/lib/libtasn1/lib/element.c -index 539008d8e94..ed761ff56bd 100644 ---- a/grub-core/lib/libtasn1/lib/element.c -+++ b/grub-core/lib/libtasn1/lib/element.c -@@ -30,9 +30,10 @@ - #include "parser_aux.h" - #include - #include "structure.h" --#include "c-ctype.h" - #include "element.h" - -+#define c_isdigit grub_isdigit -+ - void - _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size) - { -diff --git a/grub-core/lib/libtasn1/lib/gstr.c b/grub-core/lib/libtasn1/lib/gstr.c -index e91a3a151c0..e33875c2c7c 100644 ---- a/grub-core/lib/libtasn1/lib/gstr.c -+++ b/grub-core/lib/libtasn1/lib/gstr.c -@@ -36,13 +36,13 @@ _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src) - - if (dest_tot_size - dest_size > str_size) - { -- strcat (dest, src); -+ memcpy (dest + dest_size, src, str_size + 1); - } - else - { - if (dest_tot_size - dest_size > 0) - { -- strncat (dest, src, (dest_tot_size - dest_size) - 1); -+ memcpy (dest + dest_size, src, (dest_tot_size - dest_size) - 1); - dest[dest_tot_size - 1] = 0; - } - } -diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c b/grub-core/lib/libtasn1/lib/parser_aux.c -index d5dbbf8765d..89c9be69dc2 100644 ---- a/grub-core/lib/libtasn1/lib/parser_aux.c -+++ b/grub-core/lib/libtasn1/lib/parser_aux.c -@@ -26,7 +26,8 @@ - #include "gstr.h" - #include "structure.h" - #include "element.h" --#include "c-ctype.h" -+ -+#define c_isdigit grub_isdigit - - char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not found */ - -@@ -40,7 +41,7 @@ char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not fou - #ifdef __clang__ - __attribute__((no_sanitize("integer"))) - #endif --_GL_ATTRIBUTE_PURE -+__attribute__((__pure__)) - static unsigned int - _asn1_hash_name (const char *x) - { -@@ -634,7 +635,7 @@ _asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]) - count = 0; - do - { -- d = val / 10; -+ d = grub_divmod64(val, 10, NULL); - r = val - d * 10; - temp[start + count] = '0' + (char) r; - count++; -diff --git a/grub-core/lib/libtasn1/lib/int.h b/grub-core/lib/libtasn1/lib/int.h -index ea1625786c1..4a568efee9c 100644 ---- a/grub-core/lib/libtasn1/lib/int.h -+++ b/grub-core/lib/libtasn1/lib/int.h -@@ -35,7 +35,7 @@ - #include - #endif - --#include -+#include "grub/libtasn1.h" - - #define ASN1_SMALL_VALUE_SIZE 16 - -@@ -115,7 +115,7 @@ extern const tag_and_class_st _asn1_tags[]; - #define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b) - #define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b) - #define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b) --#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b) -+#define _asn1_strcat(a,b) memcpy((char *)a + strlen((const char *)a), (const char *)b, strlen((const char *)b) + 1) - - #if SIZEOF_UNSIGNED_LONG_INT == 8 - # define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b) -diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h -index 785eda2ae3f..28dbf16c4e0 100644 ---- a/include/grub/libtasn1.h -+++ b/include/grub/libtasn1.h -@@ -38,29 +38,15 @@ - #ifndef LIBTASN1_H - #define LIBTASN1_H - --#ifndef ASN1_API --#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY --#define ASN1_API __attribute__((__visibility__("default"))) --#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC --#define ASN1_API __declspec(dllexport) --#elif defined _MSC_VER && ! defined ASN1_STATIC --#define ASN1_API __declspec(dllimport) --#else -+/* grub: ASN1_API is not used */ - #define ASN1_API --#endif --#endif - --#ifdef __GNUC__ --# define __LIBTASN1_CONST__ __attribute__((const)) --# define __LIBTASN1_PURE__ __attribute__((pure)) --#else --# define __LIBTASN1_CONST__ --# define __LIBTASN1_PURE__ --#endif -+/* grub: all our supported compilers support these attributes */ -+#define __LIBTASN1_CONST__ __attribute__((const)) -+#define __LIBTASN1_PURE__ __attribute__((pure)) - --#include --#include --#include /* for FILE* */ -+#include -+#include - - #ifdef __cplusplus - extern "C" diff --git a/SOURCES/0189-Print-module-name-on-license-check-failure.patch b/SOURCES/0189-Print-module-name-on-license-check-failure.patch new file mode 100644 index 0000000..5c30859 --- /dev/null +++ b/SOURCES/0189-Print-module-name-on-license-check-failure.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 12 Oct 2021 12:34:23 -0400 +Subject: [PATCH] Print module name on license check failure + +At the very least, this will make it easier to track down the problem +module - or, if something else has gone wrong, provide more information +for debugging. + +Signed-off-by: Robbie Harwood +--- + grub-core/kern/dl.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 9557254035..f304494574 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -528,14 +528,16 @@ grub_dl_find_section_index (Elf_Ehdr *e, const char *name) + Be sure to understand your license obligations. + */ + static grub_err_t +-grub_dl_check_license (Elf_Ehdr *e) ++grub_dl_check_license (grub_dl_t mod, Elf_Ehdr *e) + { + Elf_Shdr *s = grub_dl_find_section (e, ".module_license"); + if (s && (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)) + return GRUB_ERR_NONE; +- return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "incompatible license in module %s: %s", mod->name, ++ (char *) e + s->sh_offset); + } + + static grub_err_t +@@ -743,8 +745,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + constitutes linking) and GRUB core being licensed under GPLv3+. + Be sure to understand your license obligations. + */ +- if (grub_dl_check_license (e) +- || grub_dl_resolve_name (mod, e) ++ if (grub_dl_resolve_name (mod, e) ++ || grub_dl_check_license (mod, e) + || grub_dl_resolve_dependencies (mod, e) + || grub_dl_load_segments (mod, e) + || grub_dl_resolve_symbols (mod, e) diff --git a/SOURCES/0189-libtasn1-compile-into-asn1-module.patch b/SOURCES/0189-libtasn1-compile-into-asn1-module.patch deleted file mode 100644 index 67be4e8..0000000 --- a/SOURCES/0189-libtasn1-compile-into-asn1-module.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 5 Jun 2020 17:47:25 +1000 -Subject: [PATCH] libtasn1: compile into asn1 module - -Create a wrapper file that specifies the module license. -Set up the makefile so it is built. - -Signed-off-by: Daniel Axtens ---- - grub-core/Makefile.core.def | 15 +++++++++++++++ - grub-core/lib/libtasn1_wrap/wrap.c | 26 ++++++++++++++++++++++++++ - 2 files changed, 41 insertions(+) - create mode 100644 grub-core/lib/libtasn1_wrap/wrap.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 97347ae76f9..21d2c541850 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2576,3 +2576,18 @@ module = { - common = commands/i386/wrmsr.c; - enable = x86; - }; -+ -+module = { -+ name = asn1; -+ common = lib/libtasn1/lib/decoding.c; -+ common = lib/libtasn1/lib/coding.c; -+ common = lib/libtasn1/lib/element.c; -+ common = lib/libtasn1/lib/structure.c; -+ common = lib/libtasn1/lib/parser_aux.c; -+ common = lib/libtasn1/lib/gstr.c; -+ common = lib/libtasn1/lib/errors.c; -+ common = lib/libtasn1_wrap/wrap.c; -+ cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; -+ // -Wno-type-limits comes from libtasn1's configure.ac -+ cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/libtasn1/lib -Wno-type-limits'; -+}; -diff --git a/grub-core/lib/libtasn1_wrap/wrap.c b/grub-core/lib/libtasn1_wrap/wrap.c -new file mode 100644 -index 00000000000..622ba942e33 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/wrap.c -@@ -0,0 +1,26 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+ -+/* -+ * libtasn1 is provided under LGPL2.1+, which is compatible -+ * with GPL3+. As Grub as a whole is under GPL3+, this module -+ * is therefore under GPL3+ also. -+ */ -+GRUB_MOD_LICENSE ("GPLv3+"); diff --git a/SOURCES/0190-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch b/SOURCES/0190-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch new file mode 100644 index 0000000..216418b --- /dev/null +++ b/SOURCES/0190-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 22 Oct 2021 09:53:15 +1100 +Subject: [PATCH] powerpc-ieee1275: load grub at 4MB, not 2MB + +This was first reported under PFW but reproduces under SLOF. + + - The core.elf was 2126152 = 0x207148 bytes in size with the following + program headers (per readelf): + +Entry point 0x200000 +There are 4 program headers, starting at offset 52 + +Program Headers: + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + LOAD 0x000160 0x00200000 0x00200000 0x21f98 0x2971c RWE 0x8 + GNU_STACK 0x0220f8 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 + LOAD 0x0220f8 0x00232000 0x00232000 0x1e4e50 0x1e4e50 RWE 0x4 + NOTE 0x206f48 0x00000000 0x00000000 0x00200 0x00000 R 0x4 + + - SLOF places the ELF file at 0x4000 (after the reserved space for + interrupt handlers etc.) upwards. The image was 2126152 = 0x207148 + bytes in size, so it runs from 0x4000 - 0x20b148. We'll call 0x4000 the + load address. + +0x0 0x4000 0x20b148 + |----------|--------------| + | reserved | ELF contents | + + - SLOF then copies the first LOAD program header (for .text). That runs + for 0x21f98 bytes. It runs from + (load addr + 0x160) to (load addr + 0x160 + 0x21f98) + = 0x4160 to 0x260f8 + and we copy it to 0x200000 to 0x221f98. This overwrites the end of the + image: + +0x0 0x4000 0x200000 0x221f98 + |----------|------------|---------------| + | reserved | ELF cont.. | .text section | + + - SLOF zeros the bss up to PhysAddr + MemSize = 0x22971c + +0x0 0x4000 0x200000 0x221f98 0x22971c + |----------|------------|---------------|--------| + | reserved | ELF cont.. | .text section | bss 0s | + + - SLOF then goes to fulfil the next LOAD header (for mods), which is + for 0x1e4e50 bytes. We copy from + (load addr + 0x220f8) to (load addr + 0x220f8 + 0x1e4e50) + = 0x260f8 to 0x20af48 + and we copy it to 0x232000 to 0x416e50: + +0x0 0x4000 0x200000 0x221f98 0x22971c + |----------|------------|---------------|--------| + | reserved | ELF cont.. | .text section | bss 0s | + |-------------| + | copied area | + 0x260f8 0x20af48 + + This goes poorly: + +0x0 0x4000 0x200000 0x221f98 0x22971c 0x232000 0x40bf08 0x416e50 + |----------|------------|---------------|--------|-----|-----------|-------------| + | reserved | ELF cont.. | .text section | bss 0s | pad | some mods | .text start | + +This matches the observations on the running system - 0x40bf08 was where +the contents of memory no longer matched the contents of the ELF file. + +This was reported as a license verification failure on SLOF as the +last module's .module_license section fell past where the corruption +began. + +Signed-off-by: Daniel Axtens +[rharwood@redhat.com: trim very detailed commit message] +Signed-off-by: Robbie Harwood +--- + grub-core/Makefile.core.def | 2 +- + include/grub/offsets.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 4a57de975e..08ac0fb15f 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -89,7 +89,7 @@ kernel = { + i386_xen_pvh_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x100000'; + + mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; +- powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; ++ powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x400000'; + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; + mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; +diff --git a/include/grub/offsets.h b/include/grub/offsets.h +index 871e1cd4c3..69211aa798 100644 +--- a/include/grub/offsets.h ++++ b/include/grub/offsets.h +@@ -63,7 +63,7 @@ + #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 + + #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 +-#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000 ++#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x400000 + + #define GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR 0x80200000 + diff --git a/SOURCES/0190-test_asn1-test-module-for-libtasn1.patch b/SOURCES/0190-test_asn1-test-module-for-libtasn1.patch deleted file mode 100644 index 3a02b24..0000000 --- a/SOURCES/0190-test_asn1-test-module-for-libtasn1.patch +++ /dev/null @@ -1,1457 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Wed, 10 Jun 2020 17:48:42 +1000 -Subject: [PATCH] test_asn1: test module for libtasn1 - -Import tests from libtasn1 that don't use functionality we don't -import. I have put them here rather than in the libtasn1 directory -because: - - - They need much more significant changes to run in the grub - context. - - - I don't expect they will need to be changed when updating - libtasn1: I expect the old tests will usually continue to pass on - new versions. - -This doesn't test the full decoder but that will be exercised in -test suites for coming patch sets. - -Signed-off-by: Daniel Axtens ---- - Makefile.util.def | 6 + - grub-core/Makefile.core.def | 13 ++ - .../lib/libtasn1_wrap/tests/CVE-2018-1000654.c | 61 ++++++ - grub-core/lib/libtasn1_wrap/tests/Test_overflow.c | 138 ++++++++++++++ - grub-core/lib/libtasn1_wrap/tests/Test_simple.c | 207 ++++++++++++++++++++ - grub-core/lib/libtasn1_wrap/tests/Test_strings.c | 150 +++++++++++++++ - .../lib/libtasn1_wrap/tests/object-id-decoding.c | 116 +++++++++++ - .../lib/libtasn1_wrap/tests/object-id-encoding.c | 120 ++++++++++++ - grub-core/lib/libtasn1_wrap/tests/octet-string.c | 211 +++++++++++++++++++++ - grub-core/lib/libtasn1_wrap/tests/reproducers.c | 81 ++++++++ - grub-core/lib/libtasn1_wrap/wrap_tests.c | 75 ++++++++ - .../tests/CVE-2018-1000654-1_asn1_tab.h | 32 ++++ - .../tests/CVE-2018-1000654-2_asn1_tab.h | 36 ++++ - grub-core/lib/libtasn1_wrap/wrap_tests.h | 38 ++++ - .gitignore | 1 + - tests/test_asn1.in | 12 ++ - 16 files changed, 1297 insertions(+) - create mode 100644 grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/Test_overflow.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/Test_simple.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/Test_strings.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/octet-string.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/reproducers.c - create mode 100644 grub-core/lib/libtasn1_wrap/wrap_tests.c - create mode 100644 grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h - create mode 100644 grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h - create mode 100644 grub-core/lib/libtasn1_wrap/wrap_tests.h - create mode 100644 tests/test_asn1.in - -diff --git a/Makefile.util.def b/Makefile.util.def -index e1242f54022..8cfbe69a76e 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -1305,6 +1305,12 @@ script = { - common = tests/syslinux_test.in; - }; - -+script = { -+ testcase; -+ name = test_asn1; -+ common = tests/test_asn1.in; -+}; -+ - program = { - testcase; - name = example_unit_test; -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 21d2c541850..b4aaccf7b57 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2591,3 +2591,16 @@ module = { - // -Wno-type-limits comes from libtasn1's configure.ac - cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/libtasn1/lib -Wno-type-limits'; - }; -+ -+module = { -+ name = test_asn1; -+ common = lib/libtasn1_wrap/tests/CVE-2018-1000654.c; -+ common = lib/libtasn1_wrap/tests/object-id-decoding.c; -+ common = lib/libtasn1_wrap/tests/object-id-encoding.c; -+ common = lib/libtasn1_wrap/tests/octet-string.c; -+ common = lib/libtasn1_wrap/tests/reproducers.c; -+ common = lib/libtasn1_wrap/tests/Test_overflow.c; -+ common = lib/libtasn1_wrap/tests/Test_simple.c; -+ common = lib/libtasn1_wrap/tests/Test_strings.c; -+ common = lib/libtasn1_wrap/wrap_tests.c; -+}; -diff --git a/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c -new file mode 100644 -index 00000000000..534e304521e ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654.c -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2002-2018 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+/****************************************************************/ -+/* Description: reproducer for CVE-2018-1000654 */ -+/****************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+#include "CVE-2018-1000654-1_asn1_tab.h" -+#include "CVE-2018-1000654-2_asn1_tab.h" -+ -+void -+test_CVE_2018_1000654 (void) -+{ -+ int result; -+ asn1_node definitions = NULL; -+ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; -+ -+ result = asn1_array2tree (CVE_2018_1000654_1_asn1_tab, &definitions, errorDescription); -+ if (result != ASN1_RECURSION) -+ { -+ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", -+ asn1_strerror (result), errorDescription); -+ return; -+ } -+ -+ asn1_delete_structure (&definitions); -+ -+ result = asn1_array2tree (CVE_2018_1000654_2_asn1_tab, &definitions, errorDescription); -+ if (result != ASN1_RECURSION) -+ { -+ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", -+ asn1_strerror (result), errorDescription); -+ return; -+ } -+ -+ asn1_delete_structure (&definitions); -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/Test_overflow.c b/grub-core/lib/libtasn1_wrap/tests/Test_overflow.c -new file mode 100644 -index 00000000000..f48aea0ef8b ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/Test_overflow.c -@@ -0,0 +1,138 @@ -+/* -+ * Copyright (C) 2012-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+/* Written by Simon Josefsson */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+void -+test_overflow(void) -+{ -+ /* Test that values larger than long are rejected. This has worked -+ fine with all versions of libtasn1. */ -+ -+ { -+ unsigned char der[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; -+ long l; -+ int len; -+ -+ l = asn1_get_length_der (der, sizeof der, &len); -+ -+ if (l != -2L) -+ { -+ grub_fatal ("ERROR: asn1_get_length_der bignum (l %ld len %d)\n", l, len); -+ return; -+ } -+ } -+ -+ /* Test that values larger than int but smaller than long are -+ rejected. This limitation was introduced with libtasn1 2.12. */ -+#if (GRUB_LONG_MAX > GRUB_INT_MAX) -+ { -+ unsigned long num = ((long) GRUB_UINT_MAX) << 2; -+ unsigned char der[20]; -+ int der_len; -+ long l; -+ int len; -+ -+ asn1_length_der (num, der, &der_len); -+ -+ l = asn1_get_length_der (der, der_len, &len); -+ -+ if (l != -2L) -+ { -+ grub_fatal ("ERROR: asn1_get_length_der intnum (l %ld len %d)\n", l, -+ len); -+ return; -+ } -+ } -+#endif -+ -+ /* Test that values larger than would fit in the input string are -+ rejected. This problem was fixed in libtasn1 2.12. */ -+ { -+ unsigned long num = 64; -+ unsigned char der[20]; -+ int der_len; -+ long l; -+ int len; -+ -+ asn1_length_der (num, der, &der_len); -+ -+ der_len = sizeof (der); -+ l = asn1_get_length_der (der, der_len, &len); -+ -+ if (l != -4L) -+ { -+ grub_fatal ("ERROR: asn1_get_length_der overflow-small (l %ld len %d)\n", -+ l, len); -+ return; -+ } -+ } -+ -+ /* Test that values larger than would fit in the input string are -+ rejected. This problem was fixed in libtasn1 2.12. */ -+ { -+ unsigned long num = 1073741824; -+ unsigned char der[20]; -+ int der_len; -+ long l; -+ int len; -+ -+ asn1_length_der (num, der, &der_len); -+ -+ der_len = sizeof (der); -+ l = asn1_get_length_der (der, der_len, &len); -+ -+ if (l != -4L) -+ { -+ grub_fatal ("ERROR: asn1_get_length_der overflow-large1 (l %ld len %d)\n", -+ l, len); -+ return; -+ } -+ } -+ -+ /* Test that values larger than would fit in the input string are -+ rejected. This problem was fixed in libtasn1 2.12. */ -+ { -+ unsigned long num = 2147483649; -+ unsigned char der[20]; -+ int der_len; -+ long l; -+ int len; -+ -+ asn1_length_der (num, der, &der_len); -+ -+ der_len = sizeof (der); -+ l = asn1_get_length_der (der, der_len, &len); -+ -+ if (l != -2L) -+ { -+ grub_fatal ("ERROR: asn1_get_length_der overflow-large2 (l %ld len %d)\n", -+ l, len); -+ return; -+ } -+ } -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/Test_simple.c b/grub-core/lib/libtasn1_wrap/tests/Test_simple.c -new file mode 100644 -index 00000000000..9f01006ddf4 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/Test_simple.c -@@ -0,0 +1,207 @@ -+/* -+ * Copyright (C) 2011-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Written by Simon Josefsson -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+struct tv -+{ -+ int bitlen; -+ const char *bitstr; -+ int derlen; -+ const char *der; -+}; -+ -+static const struct tv tv[] = { -+ {0, "", 2, "\x01\x00"}, -+ {1, "\x00", 3, "\x02\x07\x00"}, -+ {2, "\x00", 3, "\x02\x06\x00"}, -+ {3, "\x00", 3, "\x02\x05\x00"}, -+ {4, "\x00", 3, "\x02\x04\x00"}, -+ {5, "\x00", 3, "\x02\x03\x00"}, -+ {6, "\x00", 3, "\x02\x02\x00"}, -+ {7, "\x00", 3, "\x02\x01\x00"}, -+ {8, "\x00\x00", 3, "\x02\x00\x00"}, -+ {9, "\x00\x00", 4, "\x03\x07\x00\x00"}, -+ {10, "\x00\x00", 4, "\x03\x06\x00\x00"}, -+ {11, "\x00\x00", 4, "\x03\x05\x00\x00"}, -+ {12, "\x00\x00", 4, "\x03\x04\x00\x00"}, -+ {13, "\x00\x00", 4, "\x03\x03\x00\x00"}, -+ {14, "\x00\x00", 4, "\x03\x02\x00\x00"}, -+ {15, "\x00\x00", 4, "\x03\x01\x00\x00"}, -+ {16, "\x00\x00", 4, "\x03\x00\x00\x00"}, -+ {17, "\x00\x00\x00", 5, "\x04\x07\x00\x00\x00"}, -+ {18, "\x00\x00\x00", 5, "\x04\x06\x00\x00\x00"}, -+ {19, "\x00\x00\x00", 5, "\x04\x05\x00\x00\x00"}, -+ {1, "\xFF", 3, "\x02\x07\x80"}, -+ {2, "\xFF", 3, "\x02\x06\xc0"}, -+ {3, "\xFF", 3, "\x02\x05\xe0"}, -+ {4, "\xFF", 3, "\x02\x04\xf0"}, -+ {5, "\xFF", 3, "\x02\x03\xf8"}, -+ {6, "\xFF", 3, "\x02\x02\xfc"}, -+ {7, "\xFF", 3, "\x02\x01\xfe"}, -+ {8, "\xFF\xFF", 3, "\x02\x00\xff"}, -+ {9, "\xFF\xFF", 4, "\x03\x07\xff\x80"}, -+ {10, "\xFF\xFF", 4, "\x03\x06\xff\xc0"}, -+ {11, "\xFF\xFF", 4, "\x03\x05\xff\xe0"}, -+ {12, "\xFF\xFF", 4, "\x03\x04\xff\xf0"}, -+ {13, "\xFF\xFF", 4, "\x03\x03\xff\xf8"}, -+ {14, "\xFF\xFF", 4, "\x03\x02\xff\xfc"}, -+ {15, "\xFF\xFF", 4, "\x03\x01\xff\xfe"}, -+ {16, "\xFF\xFF", 4, "\x03\x00\xff\xff"}, -+ {17, "\xFF\xFF\xFF", 5, "\x04\x07\xff\xff\x80"}, -+ {18, "\xFF\xFF\xFF", 5, "\x04\x06\xff\xff\xc0"}, -+ {19, "\xFF\xFF\xFF", 5, "\x04\x05\xff\xff\xe0"}, -+}; -+ -+void -+test_simple (void) -+{ -+ int result; -+ unsigned char der[100]; -+ unsigned char str[100]; -+ int der_len = sizeof (der); -+ int str_size = sizeof (str); -+ int ret_len, bit_len; -+ grub_size_t i; -+ -+ /* Dummy test */ -+ -+ asn1_bit_der (NULL, 0, der, &der_len); -+ result = asn1_get_bit_der (der, 0, &ret_len, str, str_size, &bit_len); -+ if (result != ASN1_GENERIC_ERROR) -+ { -+ grub_fatal ("asn1_get_bit_der zero\n"); -+ return; -+ } -+ -+ /* Encode short strings with increasing bit lengths */ -+ -+ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) -+ { -+ /* Encode */ -+ -+ asn1_bit_der ((const unsigned char *) tv[i].bitstr, tv[i].bitlen, -+ der, &der_len); -+ -+#if 0 -+ { -+ size_t j; -+ for (j = 0; j < der_len; j++) -+ printf ("\\x%02x", der[j]); -+ printf ("\n"); -+ } -+#endif -+ -+ if (der_len != tv[i].derlen || grub_memcmp (der, tv[i].der, der_len) != 0) -+ { -+ grub_fatal ("asn1_bit_der iter %lu\n", (unsigned long) i); -+ return; -+ } -+ -+ /* Decode it */ -+ -+ result = asn1_get_bit_der (der, der_len, &ret_len, str, -+ str_size, &bit_len); -+ if (result != ASN1_SUCCESS || ret_len != tv[i].derlen -+ || bit_len != tv[i].bitlen) -+ { -+ grub_fatal ("asn1_get_bit_der iter %lu, err: %d\n", (unsigned long) i, result); -+ return; -+ } -+ } -+ -+ -+ /* Decode sample from "A Layman's Guide to a Subset of ASN.1, BER, -+ and DER" section 5.4 "BIT STRING": "The BER encoding of the BIT -+ STRING value "011011100101110111" can be any of the following, -+ among others, depending on the choice of padding bits, the form -+ of length octets [...]". -+ */ -+ -+ /* 03 04 06 6e 5d c0 DER encoding */ -+ -+ grub_memcpy (der, "\x04\x06\x6e\x5d\xc0", 5); -+ der_len = 5; -+ -+ result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len); -+ if (result != ASN1_SUCCESS || ret_len != 5 -+ || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xc0", 3) != 0) -+ { -+ grub_fatal ("asn1_get_bit_der example\n"); -+ return; -+ } -+ -+ der_len = sizeof (der); -+ asn1_bit_der (str, bit_len, der, &der_len); -+ if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0) -+ { -+ grub_fatal ("asn1_bit_der example roundtrip\n"); -+ return; -+ } -+ -+ /* 03 04 06 6e 5d e0 padded with "100000" */ -+ -+ grub_memcpy (der, "\x04\x06\x6e\x5d\xe0", 5); -+ der_len = 5; -+ -+ result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len); -+ if (result != ASN1_SUCCESS || ret_len != 5 -+ || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xe0", 3) != 0) -+ { -+ grub_fatal ("asn1_get_bit_der example padded\n"); -+ return; -+ } -+ -+ der_len = sizeof (der); -+ asn1_bit_der (str, bit_len, der, &der_len); -+ if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0) -+ { -+ grub_fatal ("asn1_bit_der example roundtrip\n"); -+ return; -+ } -+ -+ /* 03 81 04 06 6e 5d c0 long form of length octets */ -+ -+ grub_memcpy (der, "\x81\x04\x06\x6e\x5d\xc0", 6); -+ der_len = 6; -+ -+ result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len); -+ -+ if (result != ASN1_SUCCESS || ret_len != 6 -+ || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xc0", 3) != 0) -+ { -+ grub_fatal ("asn1_get_bit_der example long form\n"); -+ return; -+ } -+ -+ der_len = sizeof (der); -+ asn1_bit_der (str, bit_len, der, &der_len); -+ if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0) -+ { -+ grub_fatal ("asn1_bit_der example roundtrip\n"); -+ return; -+ } -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/Test_strings.c b/grub-core/lib/libtasn1_wrap/tests/Test_strings.c -new file mode 100644 -index 00000000000..dbe1474b204 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/Test_strings.c -@@ -0,0 +1,150 @@ -+/* -+ * Copyright (C) 2012-2014 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Written by Simon Josefsson -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+struct tv -+{ -+ unsigned int etype; -+ unsigned int str_len; -+ const void *str; -+ unsigned int der_len; -+ const void *der; -+}; -+ -+static const struct tv tv[] = { -+ {ASN1_ETYPE_IA5_STRING, 20, -+ "\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72", -+ 22, -+ "\x16\x14\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72"}, -+ {ASN1_ETYPE_PRINTABLE_STRING, 5, "\x4e\x69\x6b\x6f\x73", -+ 7, "\x13\x05\x4e\x69\x6b\x6f\x73"}, -+ {ASN1_ETYPE_UTF8_STRING, 12, "Αττική", -+ 14, "\x0c\x0c\xce\x91\xcf\x84\xcf\x84\xce\xb9\xce\xba\xce\xae"}, -+ {ASN1_ETYPE_TELETEX_STRING, 15, -+ "\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e", -+ 17, -+ "\x14\x0f\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e"}, -+ {ASN1_ETYPE_OCTET_STRING, 36, -+ "\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A", -+ 38, -+ "\x04\x24\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A"} -+}; -+ -+#define SSTR(x) sizeof(x)-1,x -+static const struct tv ber[] = { -+ {ASN1_ETYPE_OCTET_STRING, -+ SSTR("\xa0\xa0"), -+ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x00\x00")}, -+ {ASN1_ETYPE_OCTET_STRING, -+ SSTR("\xa0\xa0\xb0\xb0\xb0"), -+ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x00\x00")}, -+ {ASN1_ETYPE_OCTET_STRING, -+ SSTR("\xa0\xa0\xb0\xb0\xb0\xa1\xa1"), -+ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x24\x80\x04\x82\x00\x02\xa1\xa1\x00\x00\x00\x00")}, -+ {ASN1_ETYPE_OCTET_STRING, -+ SSTR("\xa0\xa0\xb0\xb0\xb0\xa1\xa1\xc1"), -+ SSTR("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x24\x80\x04\x82\x00\x02\xa1\xa1\x04\x82\x00\x01\xc1\x00\x00\x00\x00")}, -+}; -+ -+void -+test_strings () -+{ -+ int ret; -+ unsigned char tl[ASN1_MAX_TL_SIZE]; -+ unsigned int tl_len, der_len, str_len; -+ const unsigned char *str; -+ unsigned char *b; -+ unsigned int i; -+ -+ /* Dummy test */ -+ -+ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) -+ { -+ /* Encode */ -+ tl_len = sizeof (tl); -+ ret = asn1_encode_simple_der (tv[i].etype, tv[i].str, tv[i].str_len, -+ tl, &tl_len); -+ if (ret != ASN1_SUCCESS) -+ { -+ grub_fatal ("Encoding error in %u: %s\n", i, -+ asn1_strerror (ret)); -+ return; -+ } -+ der_len = tl_len + tv[i].str_len; -+ -+ if (der_len != tv[i].der_len || grub_memcmp (tl, tv[i].der, tl_len) != 0) -+ { -+ grub_fatal ( -+ "DER encoding differs in %u! (size: %u, expected: %u)\n", -+ i, der_len, tv[i].der_len); -+ return; -+ } -+ -+ /* decoding */ -+ ret = -+ asn1_decode_simple_der (tv[i].etype, tv[i].der, tv[i].der_len, &str, -+ &str_len); -+ if (ret != ASN1_SUCCESS) -+ { -+ grub_fatal ("Decoding error in %u: %s\n", i, -+ asn1_strerror (ret)); -+ return; -+ } -+ -+ if (str_len != tv[i].str_len || grub_memcmp (str, tv[i].str, str_len) != 0) -+ { -+ grub_fatal ( -+ "DER decoded data differ in %u! (size: %u, expected: %u)\n", -+ i, der_len, tv[i].str_len); -+ return; -+ } -+ } -+ -+ /* BER decoding */ -+ for (i = 0; i < sizeof (ber) / sizeof (ber[0]); i++) -+ { -+ /* decoding */ -+ ret = -+ asn1_decode_simple_ber (ber[i].etype, ber[i].der, ber[i].der_len, &b, -+ &str_len, NULL); -+ if (ret != ASN1_SUCCESS) -+ { -+ grub_fatal ("BER decoding error in %u: %s\n", i, -+ asn1_strerror (ret)); -+ return; -+ } -+ -+ if (str_len != ber[i].str_len || grub_memcmp (b, ber[i].str, str_len) != 0) -+ { -+ grub_fatal ( -+ "BER decoded data differ in %u! (size: %u, expected: %u)\n", -+ i, str_len, ber[i].str_len); -+ return; -+ } -+ grub_free(b); -+ } -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c b/grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c -new file mode 100644 -index 00000000000..d367bbfb5a7 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/object-id-decoding.c -@@ -0,0 +1,116 @@ -+/* -+ * Copyright (C) 2016 Red Hat, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+struct tv -+{ -+ int der_len; -+ const unsigned char *der; -+ const char *oid; -+ int expected_error; -+}; -+ -+static const struct tv tv[] = { -+ {.der_len = 5, -+ .der = (void *) "\x06\x03\x80\x37\x03", -+ .oid = "2.999.3", -+ .expected_error = ASN1_DER_ERROR /* leading 0x80 */ -+ }, -+ {.der_len = 12, -+ .der = (void *) "\x06\x0a\x2b\x06\x01\x80\x01\x92\x08\x09\x05\x01", -+ .oid = "1.3.6.1.4.1.2312.9.5.1", -+ .expected_error = ASN1_DER_ERROR /* leading 0x80 */ -+ }, -+ {.der_len = 6, -+ .der = (void *) "\x06\x04\x01\x02\x03\x04", -+ .oid = "0.1.2.3.4", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 5, -+ .der = (void *) "\x06\x03\x51\x02\x03", -+ .oid = "2.1.2.3", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 5, -+ .der = (void *) "\x06\x03\x88\x37\x03", -+ .oid = "2.999.3", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 12, -+ .der = (void *) "\x06\x0a\x2b\x06\x01\x04\x01\x92\x08\x09\x05\x01", -+ .oid = "1.3.6.1.4.1.2312.9.5.1", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 19, -+ .der = (void *) "\x06\x11\xfa\x80\x00\x00\x00\x0e\x01\x0e\xfa\x80\x00\x00\x00\x0e\x63\x6f\x6d", -+ .oid = "2.1998768.0.0.14.1.14.1998848.0.0.14.99.111.109", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 19, -+ .der = -+ (void *) -+ "\x06\x11\x2b\x06\x01\x04\x01\x92\x08\x09\x02\xaa\xda\xbe\xbe\xfa\x72\x01\x07", -+ .oid = "1.3.6.1.4.1.2312.9.2.1467399257458.1.7", -+ .expected_error = ASN1_SUCCESS}, -+}; -+ -+void -+test_object_id_decoding (void) -+{ -+ char str[128]; -+ int ret, ret_len; -+ grub_size_t i; -+ -+ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) -+ { -+ /* decode */ -+ ret = -+ asn1_get_object_id_der (tv[i].der+1, -+ tv[i].der_len-1, &ret_len, str, -+ sizeof (str)); -+ if (ret != tv[i].expected_error) -+ { -+ grub_fatal ( -+ "%d: asn1_get_object_id_der iter %lu: got '%s' expected %d\n", -+ __LINE__, (unsigned long) i, asn1_strerror(ret), tv[i].expected_error); -+ return; -+ } -+ -+ if (tv[i].expected_error != ASN1_SUCCESS) -+ continue; -+ -+ if (ret_len != tv[i].der_len-1) -+ { -+ grub_fatal ( -+ "%d: iter %lu: error in DER, length returned is %d, had %d\n", -+ __LINE__, (unsigned long)i, ret_len, tv[i].der_len-1); -+ return; -+ } -+ -+ if (grub_strcmp (tv[i].oid, str) != 0) -+ { -+ grub_fatal ( -+ "%d: strcmp iter %lu: got invalid OID: %s, expected: %s\n", -+ __LINE__, (unsigned long) i, str, tv[i].oid); -+ return; -+ } -+ -+ } -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c b/grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c -new file mode 100644 -index 00000000000..3a83b58c59f ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/object-id-encoding.c -@@ -0,0 +1,120 @@ -+/* -+ * Copyright (C) 2019 Nikos Mavrogiannopoulos -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+struct tv -+{ -+ int der_len; -+ const unsigned char *der; -+ const char *oid; -+ int expected_error; -+}; -+ -+static const struct tv tv[] = { -+ {.der_len = 0, -+ .der = (void *) "", -+ .oid = "5.999.3", -+ .expected_error = ASN1_VALUE_NOT_VALID /* cannot start with 5 */ -+ }, -+ {.der_len = 0, -+ .der = (void *) "", -+ .oid = "0.48.9", -+ .expected_error = ASN1_VALUE_NOT_VALID /* second field cannot be 48 */ -+ }, -+ {.der_len = 0, -+ .der = (void *) "", -+ .oid = "1.40.9", -+ .expected_error = ASN1_VALUE_NOT_VALID /* second field cannot be 40 */ -+ }, -+ {.der_len = 4, -+ .der = (void *) "\x06\x02\x4f\x63", -+ .oid = "1.39.99", -+ .expected_error = ASN1_SUCCESS, -+ }, -+ {.der_len = 6, -+ .der = (void *) "\x06\x04\x01\x02\x03\x04", -+ .oid = "0.1.2.3.4", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 5, -+ .der = (void *) "\x06\x03\x51\x02\x03", -+ .oid = "2.1.2.3", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 5, -+ .der = (void *) "\x06\x03\x88\x37\x03", -+ .oid = "2.999.3", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 12, -+ .der = (void *) "\x06\x0a\x2b\x06\x01\x04\x01\x92\x08\x09\x05\x01", -+ .oid = "1.3.6.1.4.1.2312.9.5.1", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 19, -+ .der = (void *) "\x06\x11\xfa\x80\x00\x00\x00\x0e\x01\x0e\xfa\x80\x00\x00\x00\x0e\x63\x6f\x6d", -+ .oid = "2.1998768.0.0.14.1.14.1998848.0.0.14.99.111.109", -+ .expected_error = ASN1_SUCCESS}, -+ {.der_len = 19, -+ .der = -+ (void *) -+ "\x06\x11\x2b\x06\x01\x04\x01\x92\x08\x09\x02\xaa\xda\xbe\xbe\xfa\x72\x01\x07", -+ .oid = "1.3.6.1.4.1.2312.9.2.1467399257458.1.7", -+ .expected_error = ASN1_SUCCESS}, -+}; -+ -+void -+test_object_id_encoding(void) -+{ -+ unsigned char der[128]; -+ int ret, der_len, i; -+ -+ for (i = 0; i < (int)(sizeof (tv) / sizeof (tv[0])); i++) -+ { -+ der_len = sizeof(der); -+ ret = asn1_object_id_der(tv[i].oid, der, &der_len, 0); -+ if (ret != ASN1_SUCCESS) -+ { -+ if (ret == tv[i].expected_error) -+ continue; -+ grub_fatal ( -+ "%d: iter %lu, encoding of OID failed: %s\n", -+ __LINE__, (unsigned long) i, asn1_strerror(ret)); -+ return; -+ } -+ else if (ret != tv[i].expected_error) -+ { -+ grub_fatal ( -+ "%d: iter %lu, encoding of OID %s succeeded when expecting failure\n", -+ __LINE__, (unsigned long) i, tv[i].oid); -+ return; -+ } -+ -+ if (der_len != tv[i].der_len || grub_memcmp(der, tv[i].der, der_len) != 0) -+ { -+ grub_fatal ( -+ "%d: iter %lu, re-encoding of OID %s resulted to different string (%d vs %d bytes)\n", -+ __LINE__, (unsigned long) i, tv[i].oid, der_len, tv[i].der_len); -+ -+ return; -+ } -+ } -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/octet-string.c b/grub-core/lib/libtasn1_wrap/tests/octet-string.c -new file mode 100644 -index 00000000000..d8a049e8df0 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/octet-string.c -@@ -0,0 +1,211 @@ -+/* -+ * Copyright (C) 2011-2020 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Written by Simon Josefsson and Nikos Mavrogiannopoulos -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+ -+struct tv -+{ -+ const char *name; -+ int der_len; -+ const unsigned char *der_str; -+ int len; -+ const unsigned char *string; -+ int expected_error; -+ int ber; -+}; -+ -+static const struct tv tv[] = { -+ {.name = "primitive octet strings", -+ .der_len = 10, -+ .der_str = -+ (void*)"\x04\x08\x01\x23\x45\x67\x89\xab\xcd\xef", -+ .len = 8, -+ .string = -+ (void*)"\x01\x23\x45\x67\x89\xab\xcd\xef", -+ .ber = 0}, -+ {.der_len = 22, -+ .der_str = -+ (void*)"\x04\x14\x13\x00\xd9\xa8\x47\xf7\xf2\x1c\xf4\xb0\xec\x5f\xc1\x73\xe5\x1b\x25\xc2\x62\x27", -+ .len = 20, -+ .string = -+ (void*)"\x13\x00\xD9\xA8\x47\xF7\xF2\x1C\xF4\xB0\xEC\x5F\xC1\x73\xE5\x1B\x25\xC2\x62\x27"}, -+ -+ {.name = "long type of length", -+ .der_len = 23, -+ .der_str = -+ (void*)"\x04\x81\x14\x13\x00\xd9\xa8\x47\xf7\xf2\x1c\xf4\xb0\xec\x5f\xc1\x73\xe5\x1b\x25\xc2\x62\x27", -+ .len = 20, -+ .string = -+ (void*)"\x13\x00\xD9\xA8\x47\xF7\xF2\x1C\xF4\xB0\xEC\x5F\xC1\x73\xE5\x1B\x25\xC2\x62\x27", -+ .ber = 1}, -+ {.der_len = 11, -+ .der_str = -+ (void*)"\x04\x81\x08\x01\x23\x45\x67\x89\xab\xcd\xef", -+ .len = 8, -+ .string = -+ (void*)"\x01\x23\x45\x67\x89\xab\xcd\xef", -+ .ber = 1}, -+ -+ {.name = "constructed - indefinite", -+ .der_len = 11, -+ .der_str = (void*)"\x24\x80\x04\x05\x01\x02\x03\x04\x05\x00\x00", -+ .len = 5, -+ .string = (void*)"\x01\x02\x03\x04\x05", -+ .ber = 1, -+ }, -+ -+ {.name = "constructed - definite - concat", -+ .der_len = 12, -+ .der_str = (void*)"\x24\x0a\x04\x04\x0a\x0b\x0c\x0d\x04\x02\x0e\x0f", -+ .len = 6, -+ .string = (void*)"\x0a\x0b\x0c\x0d\x0e\x0f", -+ .ber = 1, -+ }, -+ {.name = "constructed - definite - recursive", -+ .der_len = 15, -+ .der_str = (void*)"\x24\x0d\x04\x04\x0a\x0b\x0c\x0d\x24\x05\x04\x00\x04\x01\x0f", -+ .len = 5, -+ .string = (void*)"\x0a\x0b\x0c\x0d\x0f", -+ .ber = 1, -+ }, -+ {.name = "constructed - definite - single", -+ .der_len = 7, -+ .der_str = (void*)"\x24\x05\x04\x03\x01\x02\x03", -+ .len = 3, -+ .string = (void*)"\x01\x02\x03", -+ .ber = 1, -+ }, -+ -+ /* a large amount of recursive indefinite encoding */ -+ {.name = "a large amount of recursive indefinite encoding", -+ .der_len = 29325, -+ .der_str = (void*)"\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80", -+ .len = 0, -+ .ber = 1, -+ .expected_error = ASN1_DER_ERROR -+ } -+}; -+ -+void -+test_octet_string (void) -+{ -+ unsigned char str[100]; -+ unsigned char der[100]; -+ int der_len = sizeof (der); -+ int str_size = sizeof (str); -+ unsigned char *tmp = NULL; -+ int ret, ret_len; -+ grub_size_t i; -+ -+ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) -+ { -+ /* Decode */ -+ -+ if (tv[i].ber == 0) -+ { -+ str_size = sizeof (str); -+ ret = -+ asn1_get_octet_der (tv[i].der_str + 1, -+ tv[i].der_len - 1, &ret_len, str, -+ sizeof (str), &str_size); -+ if (ret != tv[i].expected_error) -+ { -+ grub_fatal ( -+ "%d: asn1_get_octet_der: %s: got %d expected %d\n", -+ __LINE__, tv[i].name, ret, -+ tv[i].expected_error); -+ return; -+ } -+ if (tv[i].expected_error) -+ continue; -+ -+ if (ret_len != tv[i].der_len - 1) -+ { -+ grub_fatal ( -+ "%d: error in DER, length returned is %d, had %d\n", -+ __LINE__, ret_len, tv[i].der_len - 1); -+ return; -+ } -+ -+ if (str_size != tv[i].len -+ || grub_memcmp (tv[i].string, str, tv[i].len) != 0) -+ { -+ grub_fatal ( -+ "%d: memcmp: %s: got invalid decoding\n", -+ __LINE__, tv[i].name); -+ -+ return; -+ } -+ -+ /* Encode */ -+ der_len = sizeof (der); -+ asn1_octet_der (str, str_size, der, &der_len); -+ -+ if (der_len != tv[i].der_len - 1 -+ || grub_memcmp (tv[i].der_str + 1, der, tv[i].der_len - 1) != 0) -+ { -+ grub_fatal ( -+ "encoding: %s: got invalid encoding\n", -+ tv[i].name); -+ return; -+ } -+ } -+ -+ ret = -+ asn1_decode_simple_ber (ASN1_ETYPE_OCTET_STRING, -+ tv[i].der_str, tv[i].der_len, -+ &tmp, (unsigned int*)&str_size, (unsigned int*)&der_len); -+ if (ret != tv[i].expected_error) -+ { -+ grub_fatal ( -+ "%d: asn1_decode_simple_ber: %s: got %s expected %s\n", -+ __LINE__, tv[i].name, asn1_strerror(ret), asn1_strerror(tv[i].expected_error)); -+ return; -+ } -+ if (tv[i].expected_error) -+ continue; -+ -+ if (der_len != tv[i].der_len) -+ { -+ grub_fatal ( -+ "%d: error: %s: DER, length returned is %d, had %d\n", -+ __LINE__, tv[i].name, der_len, tv[i].der_len); -+ return; -+ } -+ -+ if (str_size != tv[i].len || grub_memcmp (tv[i].string, tmp, tv[i].len) != 0) -+ { -+ grub_fatal ( -+ "%d: memcmp: %s: got invalid decoding\n", -+ __LINE__, tv[i].name); -+ return; -+ } -+ grub_free (tmp); -+ tmp = NULL; -+ -+ } -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/reproducers.c b/grub-core/lib/libtasn1_wrap/tests/reproducers.c -new file mode 100644 -index 00000000000..dc7268d4c6c ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/reproducers.c -@@ -0,0 +1,81 @@ -+/* -+ * Copyright (C) 2019 Free Software Foundation, Inc. -+ * -+ * This file is part of LIBTASN1. -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ */ -+ -+/****************************************************************/ -+/* Description: run reproducers for several fixed issues */ -+/****************************************************************/ -+ -+#include -+#include -+#include -+#include "../wrap_tests.h" -+ -+#define CONST_DOWN (1U<<29) -+ -+/* produces endless loop (fixed by d4b624b2): -+ * The following translates into a single node with all pointers -+ * (right,left,down) set to NULL. */ -+const asn1_static_node endless_asn1_tab[] = { -+ { "TEST_TREE", 536875024, NULL }, -+ { NULL, 0, NULL } -+}; -+ -+/* produces memory leak (fixed by f16d1ff9): -+ * 152 bytes in 1 blocks are definitely lost in loss record 1 of 1 -+ * at 0x4837B65: calloc (vg_replace_malloc.c:762) -+ * by 0x4851C0D: _asn1_add_static_node (parser_aux.c:71) -+ * by 0x4853AAC: asn1_array2tree (structure.c:200) -+ * by 0x10923B: main (single_node.c:67) -+ */ -+const asn1_static_node tab[] = { -+{ "a", CONST_DOWN, "" }, -+{ "b", 0, "" }, -+{ "c", 0, "" }, -+{ NULL, 0, NULL } -+}; -+ -+void -+test_reproducers (void) -+{ -+ int result; -+ asn1_node definitions = NULL; -+ char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; -+ -+ result = asn1_array2tree (endless_asn1_tab, &definitions, errorDescription); -+ if (result != ASN1_SUCCESS) -+ { -+ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", -+ asn1_strerror (result), errorDescription); -+ return; -+ } -+ -+ asn1_delete_structure (&definitions); -+ -+ definitions = NULL; -+ result = asn1_array2tree (tab, &definitions, errorDescription); -+ if (result != ASN1_SUCCESS) -+ { -+ grub_fatal ("Error: %s\nErrorDescription = %s\n\n", -+ asn1_strerror (result), errorDescription); -+ return; -+ } -+ -+ asn1_delete_structure (&definitions); -+} -diff --git a/grub-core/lib/libtasn1_wrap/wrap_tests.c b/grub-core/lib/libtasn1_wrap/wrap_tests.c -new file mode 100644 -index 00000000000..75fcd21f0d5 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/wrap_tests.c -@@ -0,0 +1,75 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include "wrap_tests.h" -+ -+/* -+ * libtasn1 tests - from which this is derived - are provided under GPL3+. -+ */ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static grub_command_t cmd; -+ -+static grub_err_t -+grub_cmd_asn1test (grub_command_t cmdd __attribute__((unused)), -+ int argc __attribute__((unused)), -+ char **args __attribute__((unused))) -+{ -+ grub_printf ("test_CVE_2018_1000654\n"); -+ test_CVE_2018_1000654 (); -+ -+ grub_printf ("test_object_id_decoding\n"); -+ test_object_id_decoding (); -+ -+ grub_printf ("test_object_id_encoding\n"); -+ test_object_id_encoding (); -+ -+ grub_printf ("test_octet_string\n"); -+ test_octet_string (); -+ -+ grub_printf ("test_overflow\n"); -+ test_overflow (); -+ -+ grub_printf ("test_reproducers\n"); -+ test_overflow (); -+ -+ grub_printf ("test_simple\n"); -+ test_simple (); -+ -+ grub_printf ("test_strings\n"); -+ test_strings (); -+ -+ grub_printf ("ASN.1 self-tests passed\n"); -+ -+ return GRUB_ERR_NONE; -+} -+ -+ -+GRUB_MOD_INIT(test_asn1) -+{ -+ cmd = grub_register_command ("test_asn1", grub_cmd_asn1test, NULL, -+ "Run self-tests for the ASN.1 parser."); -+} -+ -+GRUB_MOD_FINI(test_asn1) -+{ -+ grub_unregister_command (cmd); -+} -diff --git a/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h -new file mode 100644 -index 00000000000..1e7d3d64f55 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-1_asn1_tab.h -@@ -0,0 +1,32 @@ -+#if HAVE_CONFIG_H -+# include "config.h" -+#endif -+ -+#include -+ -+const asn1_static_node CVE_2018_1000654_1_asn1_tab[] = { -+ { "TEST_TREE", 536875024, NULL }, -+ { NULL, 1610612748, NULL }, -+ { "iso", 1073741825, "1"}, -+ { "identified-organization", 1073741825, "3"}, -+ { "dod", 1073741825, "6"}, -+ { "internet", 1073741825, "1"}, -+ { "security", 1073741825, "5"}, -+ { "mechanisms", 1073741825, "5"}, -+ { "pkix", 1073741825, "7"}, -+ { "id-mod", 1073741825, "0"}, -+ { "id-pkix1-implicit-88", 1, "2"}, -+ { "id-xnyTest", 1879048204, NULL }, -+ { NULL, 1073741825, "id-ix"}, -+ { NULL, 1073741825, "29"}, -+ { NULL, 1, "1"}, -+ { "id-ix", 1880096780, "OBJECR"}, -+ { NULL, 1073741825, "id-ix"}, -+ { NULL, 1073741825, "29"}, -+ { NULL, 1, "2"}, -+ { "id-xnyTest", 805306380, NULL }, -+ { NULL, 1073741825, "id-ix"}, -+ { NULL, 1073741825, "29"}, -+ { NULL, 1, "1"}, -+ { NULL, 0, NULL } -+}; -diff --git a/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h -new file mode 100644 -index 00000000000..e2561e5ec6d ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/tests/CVE-2018-1000654-2_asn1_tab.h -@@ -0,0 +1,36 @@ -+#if HAVE_CONFIG_H -+# include "config.h" -+#endif -+ -+#include -+ -+const asn1_static_node CVE_2018_1000654_2_asn1_tab[] = { -+ { "TEST_TREE", 536875024, NULL }, -+ { NULL, 1610612748, NULL }, -+ { "iso", 1073741825, "1"}, -+ { "identified-organization", 1073741825, "3"}, -+ { "dod", 1073741825, "6"}, -+ { "internet", 1073741825, "1"}, -+ { "security", 1073741825, "5"}, -+ { "mechanisms", 1073741825, "5"}, -+ { "pkix", 1073741825, "7"}, -+ { "id-mod", 1073741825, "0"}, -+ { "id-pkix1-implicit-88", 1, "2"}, -+ { "id-oneTest", 1879048204, NULL }, -+ { NULL, 1073741825, "id-two"}, -+ { NULL, 1073741825, "9"}, -+ { NULL, 1, "1"}, -+ { "id-two", 1879048204, NULL }, -+ { NULL, 1073741825, "id-three"}, -+ { NULL, 1073741825, "2"}, -+ { NULL, 1, "2"}, -+ { "id-three", 1879048204, NULL }, -+ { NULL, 1073741825, "id-four"}, -+ { NULL, 1073741825, "3"}, -+ { NULL, 1, "3"}, -+ { "id-four", 805306380, NULL }, -+ { NULL, 1073741825, "id-two"}, -+ { NULL, 1073741825, "3"}, -+ { NULL, 1, "3"}, -+ { NULL, 0, NULL } -+}; -diff --git a/grub-core/lib/libtasn1_wrap/wrap_tests.h b/grub-core/lib/libtasn1_wrap/wrap_tests.h -new file mode 100644 -index 00000000000..555e56dd202 ---- /dev/null -+++ b/grub-core/lib/libtasn1_wrap/wrap_tests.h -@@ -0,0 +1,38 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef LIBTASN1_WRAP_TESTS_H -+#define LIBTASN1_WRAP_TESTS_H -+ -+void test_CVE_2018_1000654 (void); -+ -+void test_object_id_encoding (void); -+ -+void test_object_id_decoding (void); -+ -+void test_octet_string (void); -+ -+void test_overflow (void); -+ -+void test_reproducers (void); -+ -+void test_simple (void); -+ -+void test_strings (void); -+ -+#endif -diff --git a/.gitignore b/.gitignore -index 594d0134d33..856e69bc5c1 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -264,6 +264,7 @@ widthspec.bin - /stamp-h1 - /syslinux_test - /tar_test -+/test_asn1 - /test_sha512sum - /test_unset - /tests/syslinux/ubuntu10.04_grub.cfg -diff --git a/tests/test_asn1.in b/tests/test_asn1.in -new file mode 100644 -index 00000000000..8173c5c270e ---- /dev/null -+++ b/tests/test_asn1.in -@@ -0,0 +1,12 @@ -+#! @BUILD_SHEBANG@ -+set -e -+ -+. "@builddir@/grub-core/modinfo.sh" -+ -+out=`echo test_asn1 | @builddir@/grub-shell` -+ -+if [ "$(echo "$out" | tail -n 1)" != "ASN.1 self-tests passed" ]; then -+ echo "ASN.1 test failure: $out" -+ exit 1 -+fi -+ diff --git a/SOURCES/0191-grub-install-support-embedding-x509-certificates.patch b/SOURCES/0191-grub-install-support-embedding-x509-certificates.patch deleted file mode 100644 index bd02e6d..0000000 --- a/SOURCES/0191-grub-install-support-embedding-x509-certificates.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alastair D'Silva -Date: Mon, 6 Jul 2020 13:33:04 +1000 -Subject: [PATCH] grub-install: support embedding x509 certificates - -To support verification of appended signatures, we need a way to -embed the necessary public keys. Existing appended signature schemes -in the Linux kernel use X.509 certificates, so allow certificates to -be embedded in the grub core image in the same way as PGP keys. - -Signed-off-by: Alastair D'Silva -Signed-off-by: Daniel Axtens ---- - grub-core/commands/pgp.c | 2 +- - util/grub-install-common.c | 22 +++++++++++++++++++++- - util/grub-mkimage.c | 15 +++++++++++++-- - util/mkimage.c | 38 ++++++++++++++++++++++++++++++++++++-- - include/grub/kernel.h | 4 +++- - include/grub/util/install.h | 7 +++++-- - 6 files changed, 79 insertions(+), 9 deletions(-) - -diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c -index 355a43844ac..b81ac0ae46c 100644 ---- a/grub-core/commands/pgp.c -+++ b/grub-core/commands/pgp.c -@@ -944,7 +944,7 @@ GRUB_MOD_INIT(pgp) - grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); - - /* Not an ELF module, skip. */ -- if (header->type != OBJ_TYPE_PUBKEY) -+ if (header->type != OBJ_TYPE_GPG_PUBKEY) - continue; - - pseudo_file.fs = &pseudo_fs; -diff --git a/util/grub-install-common.c b/util/grub-install-common.c -index aab2a941f85..422f82362c7 100644 ---- a/util/grub-install-common.c -+++ b/util/grub-install-common.c -@@ -460,6 +460,8 @@ static char **pubkeys; - static size_t npubkeys; - static char *sbat; - static int disable_shim_lock; -+static char **x509keys; -+static size_t nx509keys; - static grub_compression_t compression; - static size_t appsig_size; - -@@ -500,6 +502,11 @@ grub_install_parse (int key, char *arg) - return 1; - case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK: - disable_shim_lock = 1; -+ case 'x': -+ x509keys = xrealloc (x509keys, -+ sizeof (x509keys[0]) -+ * (nx509keys + 1)); -+ x509keys[nx509keys++] = xstrdup (arg); - return 1; - - case GRUB_INSTALL_OPTIONS_VERBOSITY: -@@ -627,6 +634,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, - for (pk = pubkeys; pk < pubkeys + npubkeys; pk++) - slen += 20 + grub_strlen (*pk); - -+ for (pk = x509keys; pk < x509keys + nx509keys; pk++) -+ slen += 10 + grub_strlen (*pk); -+ - for (md = modules.entries; *md; md++) - { - slen += 10 + grub_strlen (*md); -@@ -655,6 +665,14 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, - *p++ = ' '; - } - -+ for (pk = x509keys; pk < x509keys + nx509keys; pk++) -+ { -+ p = grub_stpcpy (p, "--x509 '"); -+ p = grub_stpcpy (p, *pk); -+ *p++ = '\''; -+ *p++ = ' '; -+ } -+ - for (md = modules.entries; *md; md++) - { - *p++ = '\''; -@@ -688,7 +706,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, - - grub_install_generate_image (dir, prefix, fp, outname, - modules.entries, memdisk_path, -- pubkeys, npubkeys, config_path, tgt, -+ pubkeys, npubkeys, -+ x509keys, nx509keys, -+ config_path, tgt, - note, appsig_size, compression, dtb, sbat, - disable_shim_lock); - while (dc--) -diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c -index 8a53310548b..e1f1112784a 100644 ---- a/util/grub-mkimage.c -+++ b/util/grub-mkimage.c -@@ -75,7 +75,8 @@ static struct argp_option options[] = { - /* TRANSLATORS: "embed" is a verb (command description). "*/ - {"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0}, - /* TRANSLATORS: "embed" is a verb (command description). "*/ -- {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for signature checking"), 0}, -+ {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for PGP signature checking"), 0}, -+ {"x509", 'x', N_("FILE"), 0, N_("embed FILE as an x509 certificate for appended signature checking"), 0}, - /* TRANSLATORS: NOTE is a name of segment. */ - {"note", 'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0}, - {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, -@@ -124,6 +125,8 @@ struct arguments - char *dtb; - char **pubkeys; - size_t npubkeys; -+ char **x509keys; -+ size_t nx509keys; - char *font; - char *config; - char *sbat; -@@ -206,6 +209,13 @@ argp_parser (int key, char *arg, struct argp_state *state) - arguments->pubkeys[arguments->npubkeys++] = xstrdup (arg); - break; - -+ case 'x': -+ arguments->x509keys = xrealloc (arguments->x509keys, -+ sizeof (arguments->x509keys[0]) -+ * (arguments->nx509keys + 1)); -+ arguments->x509keys[arguments->nx509keys++] = xstrdup (arg); -+ break; -+ - case 'c': - if (arguments->config) - free (arguments->config); -@@ -332,7 +342,8 @@ main (int argc, char *argv[]) - grub_install_generate_image (arguments.dir, arguments.prefix, fp, - arguments.output, arguments.modules, - arguments.memdisk, arguments.pubkeys, -- arguments.npubkeys, arguments.config, -+ arguments.npubkeys, arguments.x509keys, -+ arguments.nx509keys, arguments.config, - arguments.image_target, arguments.note, - arguments.appsig_size, arguments.comp, - arguments.dtb, arguments.sbat, -diff --git a/util/mkimage.c b/util/mkimage.c -index bab12276010..8319e8dfbde 100644 ---- a/util/mkimage.c -+++ b/util/mkimage.c -@@ -867,7 +867,8 @@ void - grub_install_generate_image (const char *dir, const char *prefix, - FILE *out, const char *outname, char *mods[], - char *memdisk_path, char **pubkey_paths, -- size_t npubkeys, char *config_path, -+ size_t npubkeys, char **x509key_paths, -+ size_t nx509keys, char *config_path, - const struct grub_install_image_target_desc *image_target, - int note, size_t appsig_size, grub_compression_t comp, - const char *dtb_path, const char *sbat_path, -@@ -913,6 +914,19 @@ grub_install_generate_image (const char *dir, const char *prefix, - } - } - -+ { -+ size_t i; -+ for (i = 0; i < nx509keys; i++) -+ { -+ size_t curs; -+ curs = ALIGN_ADDR (grub_util_get_image_size (x509key_paths[i])); -+ grub_util_info ("the size of x509 public key %u is 0x%" -+ GRUB_HOST_PRIxLONG_LONG, -+ (unsigned) i, (unsigned long long) curs); -+ total_module_size += curs + sizeof (struct grub_module_header); -+ } -+ } -+ - if (memdisk_path) - { - memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512); -@@ -1034,7 +1048,7 @@ grub_install_generate_image (const char *dir, const char *prefix, - curs = grub_util_get_image_size (pubkey_paths[i]); - - header = (struct grub_module_header *) (kernel_img + offset); -- header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY); -+ header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY); - header->size = grub_host_to_target32 (curs + sizeof (*header)); - offset += sizeof (*header); - -@@ -1043,6 +1057,26 @@ grub_install_generate_image (const char *dir, const char *prefix, - } - } - -+ { -+ size_t i; -+ for (i = 0; i < nx509keys; i++) -+ { -+ size_t curs; -+ struct grub_module_header *header; -+ -+ curs = grub_util_get_image_size (x509key_paths[i]); -+ -+ header = (struct grub_module_header *) (kernel_img + offset); -+ header->type = grub_host_to_target32 (OBJ_TYPE_X509_PUBKEY); -+ header->size = grub_host_to_target32 (curs + sizeof (*header)); -+ offset += sizeof (*header); -+ -+ grub_util_load_image (x509key_paths[i], kernel_img + offset); -+ offset += ALIGN_ADDR (curs); -+ } -+ } -+ -+ - if (memdisk_path) - { - struct grub_module_header *header; -diff --git a/include/grub/kernel.h b/include/grub/kernel.h -index 55849777eaa..98edc0863f6 100644 ---- a/include/grub/kernel.h -+++ b/include/grub/kernel.h -@@ -30,7 +30,9 @@ enum - OBJ_TYPE_PREFIX, - OBJ_TYPE_PUBKEY, - OBJ_TYPE_DTB, -- OBJ_TYPE_DISABLE_SHIM_LOCK -+ OBJ_TYPE_DISABLE_SHIM_LOCK, -+ OBJ_TYPE_GPG_PUBKEY, -+ OBJ_TYPE_X509_PUBKEY, - }; - - /* The module header. */ -diff --git a/include/grub/util/install.h b/include/grub/util/install.h -index cf4531e02b6..51f3b13ac13 100644 ---- a/include/grub/util/install.h -+++ b/include/grub/util/install.h -@@ -67,6 +67,8 @@ - N_("SBAT metadata"), 0 }, \ - { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \ - N_("disable shim_lock verifier"), 0 }, \ -+ { "x509key", 'x', N_("FILE"), 0, \ -+ N_("embed FILE as an x509 certificate for signature checking"), 0}, \ - { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\ - "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \ - 1}, \ -@@ -188,8 +190,9 @@ void - grub_install_generate_image (const char *dir, const char *prefix, - FILE *out, - const char *outname, char *mods[], -- char *memdisk_path, char **pubkey_paths, -- size_t npubkeys, -+ char *memdisk_path, -+ char **pubkey_paths, size_t npubkeys, -+ char **x509key_paths, size_t nx509keys, - char *config_path, - const struct grub_install_image_target_desc *image_target, - int note, size_t appsig_size, diff --git a/SOURCES/0191-grub-mkconfig-restore-umask-for-grub.cfg.patch b/SOURCES/0191-grub-mkconfig-restore-umask-for-grub.cfg.patch new file mode 100644 index 0000000..76b73f5 --- /dev/null +++ b/SOURCES/0191-grub-mkconfig-restore-umask-for-grub.cfg.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang via Grub-devel +Date: Fri, 3 Dec 2021 16:13:28 +0800 +Subject: [PATCH] grub-mkconfig: restore umask for grub.cfg + +Since commit: + + ab2e53c8a grub-mkconfig: Honor a symlink when generating configuration +by grub-mkconfig + +has inadvertently discarded umask for creating grub.cfg in the process +of grub-mkconfig. The resulting wrong permission (0644) would allow +unprivileged users to read grub's configuration file content. This +presents a low confidentiality risk as grub.cfg may contain non-secured +plain-text passwords. + +This patch restores the missing umask and set the file mode of creation +to 0600 preventing unprivileged access. + +Fixes: CVE-2021-3981 + +Signed-off-by: Michael Chang +--- + util/grub-mkconfig.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index f55339a3f6..520a672cd2 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -311,7 +311,9 @@ and /etc/grub.d/* files or please file a bug report with + exit 1 + else + # none of the children aborted with error, install the new grub.cfg ++ oldumask=$(umask); umask 077 + cat ${grub_cfg}.new > ${grub_cfg} ++ umask $oldumask + rm -f ${grub_cfg}.new + fi + fi diff --git a/SOURCES/0192-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch b/SOURCES/0192-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch deleted file mode 100644 index 7b7d70c..0000000 --- a/SOURCES/0192-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch +++ /dev/null @@ -1,639 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 30 Jul 2020 01:35:10 +1000 -Subject: [PATCH] appended signatures: import GNUTLS's ASN.1 description files - -In order to parse PKCS#7 messages and X.509 certificates with libtasn1, -we need some information about how they are encoded. - -We get these from GNUTLS, which has the benefit that they support the -features we need and are well tested. - -The GNUTLS license is LGPLv2.1+, which is GPLv3 compatible, allowing -us to import it without issue. - -Signed-off-by: Daniel Axtens ---- - grub-core/commands/appendedsig/gnutls_asn1_tab.c | 121 ++++++ - grub-core/commands/appendedsig/pkix_asn1_tab.c | 484 +++++++++++++++++++++++ - 2 files changed, 605 insertions(+) - create mode 100644 grub-core/commands/appendedsig/gnutls_asn1_tab.c - create mode 100644 grub-core/commands/appendedsig/pkix_asn1_tab.c - -diff --git a/grub-core/commands/appendedsig/gnutls_asn1_tab.c b/grub-core/commands/appendedsig/gnutls_asn1_tab.c -new file mode 100644 -index 00000000000..ddd1314e63b ---- /dev/null -+++ b/grub-core/commands/appendedsig/gnutls_asn1_tab.c -@@ -0,0 +1,121 @@ -+#include -+#include -+ -+const asn1_static_node gnutls_asn1_tab[] = { -+ { "GNUTLS", 536872976, NULL }, -+ { NULL, 1073741836, NULL }, -+ { "RSAPublicKey", 1610612741, NULL }, -+ { "modulus", 1073741827, NULL }, -+ { "publicExponent", 3, NULL }, -+ { "RSAPrivateKey", 1610612741, NULL }, -+ { "version", 1073741827, NULL }, -+ { "modulus", 1073741827, NULL }, -+ { "publicExponent", 1073741827, NULL }, -+ { "privateExponent", 1073741827, NULL }, -+ { "prime1", 1073741827, NULL }, -+ { "prime2", 1073741827, NULL }, -+ { "exponent1", 1073741827, NULL }, -+ { "exponent2", 1073741827, NULL }, -+ { "coefficient", 1073741827, NULL }, -+ { "otherPrimeInfos", 16386, "OtherPrimeInfos"}, -+ { "ProvableSeed", 1610612741, NULL }, -+ { "algorithm", 1073741836, NULL }, -+ { "seed", 7, NULL }, -+ { "OtherPrimeInfos", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "OtherPrimeInfo"}, -+ { "OtherPrimeInfo", 1610612741, NULL }, -+ { "prime", 1073741827, NULL }, -+ { "exponent", 1073741827, NULL }, -+ { "coefficient", 3, NULL }, -+ { "AlgorithmIdentifier", 1610612741, NULL }, -+ { "algorithm", 1073741836, NULL }, -+ { "parameters", 541081613, NULL }, -+ { "algorithm", 1, NULL }, -+ { "DigestInfo", 1610612741, NULL }, -+ { "digestAlgorithm", 1073741826, "DigestAlgorithmIdentifier"}, -+ { "digest", 7, NULL }, -+ { "DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"}, -+ { "DSAPublicKey", 1073741827, NULL }, -+ { "DSAParameters", 1610612741, NULL }, -+ { "p", 1073741827, NULL }, -+ { "q", 1073741827, NULL }, -+ { "g", 3, NULL }, -+ { "DSASignatureValue", 1610612741, NULL }, -+ { "r", 1073741827, NULL }, -+ { "s", 3, NULL }, -+ { "DSAPrivateKey", 1610612741, NULL }, -+ { "version", 1073741827, NULL }, -+ { "p", 1073741827, NULL }, -+ { "q", 1073741827, NULL }, -+ { "g", 1073741827, NULL }, -+ { "Y", 1073741827, NULL }, -+ { "priv", 3, NULL }, -+ { "DHParameter", 1610612741, NULL }, -+ { "prime", 1073741827, NULL }, -+ { "base", 1073741827, NULL }, -+ { "privateValueLength", 16387, NULL }, -+ { "ECParameters", 1610612754, NULL }, -+ { "namedCurve", 12, NULL }, -+ { "ECPrivateKey", 1610612741, NULL }, -+ { "Version", 1073741827, NULL }, -+ { "privateKey", 1073741831, NULL }, -+ { "parameters", 1610637314, "ECParameters"}, -+ { NULL, 2056, "0"}, -+ { "publicKey", 536895494, NULL }, -+ { NULL, 2056, "1"}, -+ { "PrincipalName", 1610612741, NULL }, -+ { "name-type", 1610620931, NULL }, -+ { NULL, 2056, "0"}, -+ { "name-string", 536879115, NULL }, -+ { NULL, 1073743880, "1"}, -+ { NULL, 27, NULL }, -+ { "KRB5PrincipalName", 1610612741, NULL }, -+ { "realm", 1610620955, NULL }, -+ { NULL, 2056, "0"}, -+ { "principalName", 536879106, "PrincipalName"}, -+ { NULL, 2056, "1"}, -+ { "RSAPSSParameters", 1610612741, NULL }, -+ { "hashAlgorithm", 1610637314, "AlgorithmIdentifier"}, -+ { NULL, 2056, "0"}, -+ { "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"}, -+ { NULL, 2056, "1"}, -+ { "saltLength", 1610653699, NULL }, -+ { NULL, 1073741833, "20"}, -+ { NULL, 2056, "2"}, -+ { "trailerField", 536911875, NULL }, -+ { NULL, 1073741833, "1"}, -+ { NULL, 2056, "3"}, -+ { "GOSTParameters", 1610612741, NULL }, -+ { "publicKeyParamSet", 1073741836, NULL }, -+ { "digestParamSet", 16396, NULL }, -+ { "GOSTParametersOld", 1610612741, NULL }, -+ { "publicKeyParamSet", 1073741836, NULL }, -+ { "digestParamSet", 1073741836, NULL }, -+ { "encryptionParamSet", 16396, NULL }, -+ { "GOSTPrivateKey", 1073741831, NULL }, -+ { "GOSTPrivateKeyOld", 1073741827, NULL }, -+ { "IssuerSignTool", 1610612741, NULL }, -+ { "signTool", 1073741858, NULL }, -+ { "cATool", 1073741858, NULL }, -+ { "signToolCert", 1073741858, NULL }, -+ { "cAToolCert", 34, NULL }, -+ { "Gost28147-89-EncryptedKey", 1610612741, NULL }, -+ { "encryptedKey", 1073741831, NULL }, -+ { "maskKey", 1610637319, NULL }, -+ { NULL, 4104, "0"}, -+ { "macKey", 7, NULL }, -+ { "SubjectPublicKeyInfo", 1610612741, NULL }, -+ { "algorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "subjectPublicKey", 6, NULL }, -+ { "GostR3410-TransportParameters", 1610612741, NULL }, -+ { "encryptionParamSet", 1073741836, NULL }, -+ { "ephemeralPublicKey", 1610637314, "SubjectPublicKeyInfo"}, -+ { NULL, 4104, "0"}, -+ { "ukm", 7, NULL }, -+ { "GostR3410-KeyTransport", 536870917, NULL }, -+ { "sessionEncryptedKey", 1073741826, "Gost28147-89-EncryptedKey"}, -+ { "transportParameters", 536895490, "GostR3410-TransportParameters"}, -+ { NULL, 4104, "0"}, -+ { NULL, 0, NULL } -+}; -diff --git a/grub-core/commands/appendedsig/pkix_asn1_tab.c b/grub-core/commands/appendedsig/pkix_asn1_tab.c -new file mode 100644 -index 00000000000..adef69d95ce ---- /dev/null -+++ b/grub-core/commands/appendedsig/pkix_asn1_tab.c -@@ -0,0 +1,484 @@ -+#include -+#include -+ -+const asn1_static_node pkix_asn1_tab[] = { -+ { "PKIX1", 536875024, NULL }, -+ { NULL, 1073741836, NULL }, -+ { "PrivateKeyUsagePeriod", 1610612741, NULL }, -+ { "notBefore", 1610637349, NULL }, -+ { NULL, 4104, "0"}, -+ { "notAfter", 536895525, NULL }, -+ { NULL, 4104, "1"}, -+ { "AuthorityKeyIdentifier", 1610612741, NULL }, -+ { "keyIdentifier", 1610637319, NULL }, -+ { NULL, 4104, "0"}, -+ { "authorityCertIssuer", 1610637314, "GeneralNames"}, -+ { NULL, 4104, "1"}, -+ { "authorityCertSerialNumber", 536895490, "CertificateSerialNumber"}, -+ { NULL, 4104, "2"}, -+ { "SubjectKeyIdentifier", 1073741831, NULL }, -+ { "KeyUsage", 1073741830, NULL }, -+ { "DirectoryString", 1610612754, NULL }, -+ { "teletexString", 1612709918, NULL }, -+ { "MAX", 524298, "1"}, -+ { "printableString", 1612709919, NULL }, -+ { "MAX", 524298, "1"}, -+ { "universalString", 1612709920, NULL }, -+ { "MAX", 524298, "1"}, -+ { "utf8String", 1612709922, NULL }, -+ { "MAX", 524298, "1"}, -+ { "bmpString", 1612709921, NULL }, -+ { "MAX", 524298, "1"}, -+ { "ia5String", 538968093, NULL }, -+ { "MAX", 524298, "1"}, -+ { "SubjectAltName", 1073741826, "GeneralNames"}, -+ { "GeneralNames", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "GeneralName"}, -+ { "GeneralName", 1610612754, NULL }, -+ { "otherName", 1610620930, "AnotherName"}, -+ { NULL, 4104, "0"}, -+ { "rfc822Name", 1610620957, NULL }, -+ { NULL, 4104, "1"}, -+ { "dNSName", 1610620957, NULL }, -+ { NULL, 4104, "2"}, -+ { "x400Address", 1610620941, NULL }, -+ { NULL, 4104, "3"}, -+ { "directoryName", 1610620939, NULL }, -+ { NULL, 1073743880, "4"}, -+ { NULL, 2, "RelativeDistinguishedName"}, -+ { "ediPartyName", 1610620941, NULL }, -+ { NULL, 4104, "5"}, -+ { "uniformResourceIdentifier", 1610620957, NULL }, -+ { NULL, 4104, "6"}, -+ { "iPAddress", 1610620935, NULL }, -+ { NULL, 4104, "7"}, -+ { "registeredID", 536879116, NULL }, -+ { NULL, 4104, "8"}, -+ { "AnotherName", 1610612741, NULL }, -+ { "type-id", 1073741836, NULL }, -+ { "value", 541073421, NULL }, -+ { NULL, 1073743880, "0"}, -+ { "type-id", 1, NULL }, -+ { "IssuerAltName", 1073741826, "GeneralNames"}, -+ { "BasicConstraints", 1610612741, NULL }, -+ { "cA", 1610645508, NULL }, -+ { NULL, 131081, NULL }, -+ { "pathLenConstraint", 537411587, NULL }, -+ { "0", 10, "MAX"}, -+ { "CRLDistributionPoints", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "DistributionPoint"}, -+ { "DistributionPoint", 1610612741, NULL }, -+ { "distributionPoint", 1610637314, "DistributionPointName"}, -+ { NULL, 2056, "0"}, -+ { "reasons", 1610637314, "ReasonFlags"}, -+ { NULL, 4104, "1"}, -+ { "cRLIssuer", 536895490, "GeneralNames"}, -+ { NULL, 4104, "2"}, -+ { "DistributionPointName", 1610612754, NULL }, -+ { "fullName", 1610620930, "GeneralNames"}, -+ { NULL, 4104, "0"}, -+ { "nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"}, -+ { NULL, 4104, "1"}, -+ { "ReasonFlags", 1073741830, NULL }, -+ { "ExtKeyUsageSyntax", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 12, NULL }, -+ { "AuthorityInfoAccessSyntax", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "AccessDescription"}, -+ { "AccessDescription", 1610612741, NULL }, -+ { "accessMethod", 1073741836, NULL }, -+ { "accessLocation", 2, "GeneralName"}, -+ { "Attribute", 1610612741, NULL }, -+ { "type", 1073741836, NULL }, -+ { "values", 536870927, NULL }, -+ { NULL, 13, NULL }, -+ { "AttributeTypeAndValue", 1610612741, NULL }, -+ { "type", 1073741836, NULL }, -+ { "value", 13, NULL }, -+ { "Name", 1610612754, NULL }, -+ { "rdnSequence", 536870923, NULL }, -+ { NULL, 2, "RelativeDistinguishedName"}, -+ { "DistinguishedName", 1610612747, NULL }, -+ { NULL, 2, "RelativeDistinguishedName"}, -+ { "RelativeDistinguishedName", 1612709903, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "AttributeTypeAndValue"}, -+ { "Certificate", 1610612741, NULL }, -+ { "tbsCertificate", 1073741826, "TBSCertificate"}, -+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "signature", 6, NULL }, -+ { "TBSCertificate", 1610612741, NULL }, -+ { "version", 1610653699, NULL }, -+ { NULL, 1073741833, "0"}, -+ { NULL, 2056, "0"}, -+ { "serialNumber", 1073741826, "CertificateSerialNumber"}, -+ { "signature", 1073741826, "AlgorithmIdentifier"}, -+ { "issuer", 1073741826, "Name"}, -+ { "validity", 1073741826, "Validity"}, -+ { "subject", 1073741826, "Name"}, -+ { "subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"}, -+ { "issuerUniqueID", 1610637314, "UniqueIdentifier"}, -+ { NULL, 4104, "1"}, -+ { "subjectUniqueID", 1610637314, "UniqueIdentifier"}, -+ { NULL, 4104, "2"}, -+ { "extensions", 536895490, "Extensions"}, -+ { NULL, 2056, "3"}, -+ { "CertificateSerialNumber", 1073741827, NULL }, -+ { "Validity", 1610612741, NULL }, -+ { "notBefore", 1073741826, "Time"}, -+ { "notAfter", 2, "Time"}, -+ { "Time", 1610612754, NULL }, -+ { "utcTime", 1073741860, NULL }, -+ { "generalTime", 37, NULL }, -+ { "UniqueIdentifier", 1073741830, NULL }, -+ { "SubjectPublicKeyInfo", 1610612741, NULL }, -+ { "algorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "subjectPublicKey", 6, NULL }, -+ { "Extensions", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "Extension"}, -+ { "Extension", 1610612741, NULL }, -+ { "extnID", 1073741836, NULL }, -+ { "critical", 1610645508, NULL }, -+ { NULL, 131081, NULL }, -+ { "extnValue", 7, NULL }, -+ { "CertificateList", 1610612741, NULL }, -+ { "tbsCertList", 1073741826, "TBSCertList"}, -+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "signature", 6, NULL }, -+ { "TBSCertList", 1610612741, NULL }, -+ { "version", 1073758211, NULL }, -+ { "signature", 1073741826, "AlgorithmIdentifier"}, -+ { "issuer", 1073741826, "Name"}, -+ { "thisUpdate", 1073741826, "Time"}, -+ { "nextUpdate", 1073758210, "Time"}, -+ { "revokedCertificates", 1610629131, NULL }, -+ { NULL, 536870917, NULL }, -+ { "userCertificate", 1073741826, "CertificateSerialNumber"}, -+ { "revocationDate", 1073741826, "Time"}, -+ { "crlEntryExtensions", 16386, "Extensions"}, -+ { "crlExtensions", 536895490, "Extensions"}, -+ { NULL, 2056, "0"}, -+ { "AlgorithmIdentifier", 1610612741, NULL }, -+ { "algorithm", 1073741836, NULL }, -+ { "parameters", 541081613, NULL }, -+ { "algorithm", 1, NULL }, -+ { "Dss-Sig-Value", 1610612741, NULL }, -+ { "r", 1073741827, NULL }, -+ { "s", 3, NULL }, -+ { "Dss-Parms", 1610612741, NULL }, -+ { "p", 1073741827, NULL }, -+ { "q", 1073741827, NULL }, -+ { "g", 3, NULL }, -+ { "pkcs-7-ContentInfo", 1610612741, NULL }, -+ { "contentType", 1073741836, NULL }, -+ { "content", 541073421, NULL }, -+ { NULL, 1073743880, "0"}, -+ { "contentType", 1, NULL }, -+ { "pkcs-7-DigestInfo", 1610612741, NULL }, -+ { "digestAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "digest", 7, NULL }, -+ { "pkcs-7-SignedData", 1610612741, NULL }, -+ { "version", 1073741827, NULL }, -+ { "digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"}, -+ { "encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"}, -+ { "certificates", 1610637314, "pkcs-7-CertificateSet"}, -+ { NULL, 4104, "0"}, -+ { "crls", 1610637314, "pkcs-7-CertificateRevocationLists"}, -+ { NULL, 4104, "1"}, -+ { "signerInfos", 2, "pkcs-7-SignerInfos"}, -+ { "pkcs-7-DigestAlgorithmIdentifiers", 1610612751, NULL }, -+ { NULL, 2, "AlgorithmIdentifier"}, -+ { "pkcs-7-EncapsulatedContentInfo", 1610612741, NULL }, -+ { "eContentType", 1073741836, NULL }, -+ { "eContent", 536895501, NULL }, -+ { NULL, 2056, "0"}, -+ { "pkcs-7-CertificateRevocationLists", 1610612751, NULL }, -+ { NULL, 13, NULL }, -+ { "pkcs-7-CertificateChoices", 1610612754, NULL }, -+ { "certificate", 13, NULL }, -+ { "pkcs-7-CertificateSet", 1610612751, NULL }, -+ { NULL, 2, "pkcs-7-CertificateChoices"}, -+ { "IssuerAndSerialNumber", 1610612741, NULL }, -+ { "issuer", 1073741826, "Name"}, -+ { "serialNumber", 2, "CertificateSerialNumber"}, -+ { "pkcs-7-SignerInfo", 1610612741, NULL }, -+ { "version", 1073741827, NULL }, -+ { "sid", 1073741826, "SignerIdentifier"}, -+ { "digestAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "signedAttrs", 1610637314, "SignedAttributes"}, -+ { NULL, 4104, "0"}, -+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "signature", 1073741831, NULL }, -+ { "unsignedAttrs", 536895490, "SignedAttributes"}, -+ { NULL, 4104, "1"}, -+ { "SignedAttributes", 1612709903, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "Attribute"}, -+ { "SignerIdentifier", 1610612754, NULL }, -+ { "issuerAndSerialNumber", 1073741826, "IssuerAndSerialNumber"}, -+ { "subjectKeyIdentifier", 536879111, NULL }, -+ { NULL, 4104, "0"}, -+ { "pkcs-7-SignerInfos", 1610612751, NULL }, -+ { NULL, 2, "pkcs-7-SignerInfo"}, -+ { "pkcs-10-CertificationRequestInfo", 1610612741, NULL }, -+ { "version", 1073741827, NULL }, -+ { "subject", 1073741826, "Name"}, -+ { "subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"}, -+ { "attributes", 536879106, "Attributes"}, -+ { NULL, 4104, "0"}, -+ { "Attributes", 1610612751, NULL }, -+ { NULL, 2, "Attribute"}, -+ { "pkcs-10-CertificationRequest", 1610612741, NULL }, -+ { "certificationRequestInfo", 1073741826, "pkcs-10-CertificationRequestInfo"}, -+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "signature", 6, NULL }, -+ { "pkcs-9-at-challengePassword", 1879048204, NULL }, -+ { "iso", 1073741825, "1"}, -+ { "member-body", 1073741825, "2"}, -+ { "us", 1073741825, "840"}, -+ { "rsadsi", 1073741825, "113549"}, -+ { "pkcs", 1073741825, "1"}, -+ { NULL, 1073741825, "9"}, -+ { NULL, 1, "7"}, -+ { "pkcs-9-challengePassword", 1610612754, NULL }, -+ { "printableString", 1073741855, NULL }, -+ { "utf8String", 34, NULL }, -+ { "pkcs-9-localKeyId", 1073741831, NULL }, -+ { "pkcs-8-PrivateKeyInfo", 1610612741, NULL }, -+ { "version", 1073741827, NULL }, -+ { "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "privateKey", 1073741831, NULL }, -+ { "attributes", 536895490, "Attributes"}, -+ { NULL, 4104, "0"}, -+ { "pkcs-8-EncryptedPrivateKeyInfo", 1610612741, NULL }, -+ { "encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "encryptedData", 2, "pkcs-8-EncryptedData"}, -+ { "pkcs-8-EncryptedData", 1073741831, NULL }, -+ { "pkcs-5-des-CBC-params", 1612709895, NULL }, -+ { NULL, 1048586, "8"}, -+ { "pkcs-5-des-EDE3-CBC-params", 1612709895, NULL }, -+ { NULL, 1048586, "8"}, -+ { "pkcs-5-aes128-CBC-params", 1612709895, NULL }, -+ { NULL, 1048586, "16"}, -+ { "pkcs-5-aes192-CBC-params", 1612709895, NULL }, -+ { NULL, 1048586, "16"}, -+ { "pkcs-5-aes256-CBC-params", 1612709895, NULL }, -+ { NULL, 1048586, "16"}, -+ { "Gost28147-89-Parameters", 1610612741, NULL }, -+ { "iv", 1073741831, NULL }, -+ { "encryptionParamSet", 12, NULL }, -+ { "pkcs-5-PBE-params", 1610612741, NULL }, -+ { "salt", 1073741831, NULL }, -+ { "iterationCount", 3, NULL }, -+ { "pkcs-5-PBES2-params", 1610612741, NULL }, -+ { "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"}, -+ { "encryptionScheme", 2, "AlgorithmIdentifier"}, -+ { "pkcs-5-PBKDF2-params", 1610612741, NULL }, -+ { "salt", 1610612754, NULL }, -+ { "specified", 1073741831, NULL }, -+ { "otherSource", 2, "AlgorithmIdentifier"}, -+ { "iterationCount", 1611137027, NULL }, -+ { "1", 10, "MAX"}, -+ { "keyLength", 1611153411, NULL }, -+ { "1", 10, "MAX"}, -+ { "prf", 16386, "AlgorithmIdentifier"}, -+ { "pkcs-12-PFX", 1610612741, NULL }, -+ { "version", 1610874883, NULL }, -+ { "v3", 1, "3"}, -+ { "authSafe", 1073741826, "pkcs-7-ContentInfo"}, -+ { "macData", 16386, "pkcs-12-MacData"}, -+ { "pkcs-12-PbeParams", 1610612741, NULL }, -+ { "salt", 1073741831, NULL }, -+ { "iterations", 3, NULL }, -+ { "pkcs-12-MacData", 1610612741, NULL }, -+ { "mac", 1073741826, "pkcs-7-DigestInfo"}, -+ { "macSalt", 1073741831, NULL }, -+ { "iterations", 536903683, NULL }, -+ { NULL, 9, "1"}, -+ { "pkcs-12-AuthenticatedSafe", 1610612747, NULL }, -+ { NULL, 2, "pkcs-7-ContentInfo"}, -+ { "pkcs-12-SafeContents", 1610612747, NULL }, -+ { NULL, 2, "pkcs-12-SafeBag"}, -+ { "pkcs-12-SafeBag", 1610612741, NULL }, -+ { "bagId", 1073741836, NULL }, -+ { "bagValue", 1614815245, NULL }, -+ { NULL, 1073743880, "0"}, -+ { "badId", 1, NULL }, -+ { "bagAttributes", 536887311, NULL }, -+ { NULL, 2, "Attribute"}, -+ { "pkcs-12-CertBag", 1610612741, NULL }, -+ { "certId", 1073741836, NULL }, -+ { "certValue", 541073421, NULL }, -+ { NULL, 1073743880, "0"}, -+ { "certId", 1, NULL }, -+ { "pkcs-12-CRLBag", 1610612741, NULL }, -+ { "crlId", 1073741836, NULL }, -+ { "crlValue", 541073421, NULL }, -+ { NULL, 1073743880, "0"}, -+ { "crlId", 1, NULL }, -+ { "pkcs-12-SecretBag", 1610612741, NULL }, -+ { "secretTypeId", 1073741836, NULL }, -+ { "secretValue", 541073421, NULL }, -+ { NULL, 1073743880, "0"}, -+ { "secretTypeId", 1, NULL }, -+ { "pkcs-7-Data", 1073741831, NULL }, -+ { "pkcs-7-EncryptedData", 1610612741, NULL }, -+ { "version", 1073741827, NULL }, -+ { "encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"}, -+ { "unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"}, -+ { NULL, 4104, "1"}, -+ { "pkcs-7-EncryptedContentInfo", 1610612741, NULL }, -+ { "contentType", 1073741836, NULL }, -+ { "contentEncryptionAlgorithm", 1073741826, "pkcs-7-ContentEncryptionAlgorithmIdentifier"}, -+ { "encryptedContent", 536895495, NULL }, -+ { NULL, 4104, "0"}, -+ { "pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"}, -+ { "pkcs-7-UnprotectedAttributes", 1612709903, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "Attribute"}, -+ { "ProxyCertInfo", 1610612741, NULL }, -+ { "pCPathLenConstraint", 1611153411, NULL }, -+ { "0", 10, "MAX"}, -+ { "proxyPolicy", 2, "ProxyPolicy"}, -+ { "ProxyPolicy", 1610612741, NULL }, -+ { "policyLanguage", 1073741836, NULL }, -+ { "policy", 16391, NULL }, -+ { "certificatePolicies", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "PolicyInformation"}, -+ { "PolicyInformation", 1610612741, NULL }, -+ { "policyIdentifier", 1073741836, NULL }, -+ { "policyQualifiers", 538984459, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "PolicyQualifierInfo"}, -+ { "PolicyQualifierInfo", 1610612741, NULL }, -+ { "policyQualifierId", 1073741836, NULL }, -+ { "qualifier", 541065229, NULL }, -+ { "policyQualifierId", 1, NULL }, -+ { "CPSuri", 1073741853, NULL }, -+ { "UserNotice", 1610612741, NULL }, -+ { "noticeRef", 1073758210, "NoticeReference"}, -+ { "explicitText", 16386, "DisplayText"}, -+ { "NoticeReference", 1610612741, NULL }, -+ { "organization", 1073741826, "DisplayText"}, -+ { "noticeNumbers", 536870923, NULL }, -+ { NULL, 3, NULL }, -+ { "DisplayText", 1610612754, NULL }, -+ { "ia5String", 1612709917, NULL }, -+ { "200", 524298, "1"}, -+ { "visibleString", 1612709923, NULL }, -+ { "200", 524298, "1"}, -+ { "bmpString", 1612709921, NULL }, -+ { "200", 524298, "1"}, -+ { "utf8String", 538968098, NULL }, -+ { "200", 524298, "1"}, -+ { "OCSPRequest", 1610612741, NULL }, -+ { "tbsRequest", 1073741826, "TBSRequest"}, -+ { "optionalSignature", 536895490, "Signature"}, -+ { NULL, 2056, "0"}, -+ { "TBSRequest", 1610612741, NULL }, -+ { "version", 1610653699, NULL }, -+ { NULL, 1073741833, "0"}, -+ { NULL, 2056, "0"}, -+ { "requestorName", 1610637314, "GeneralName"}, -+ { NULL, 2056, "1"}, -+ { "requestList", 1610612747, NULL }, -+ { NULL, 2, "Request"}, -+ { "requestExtensions", 536895490, "Extensions"}, -+ { NULL, 2056, "2"}, -+ { "Signature", 1610612741, NULL }, -+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "signature", 1073741830, NULL }, -+ { "certs", 536895499, NULL }, -+ { NULL, 1073743880, "0"}, -+ { NULL, 2, "Certificate"}, -+ { "Request", 1610612741, NULL }, -+ { "reqCert", 1073741826, "CertID"}, -+ { "singleRequestExtensions", 536895490, "Extensions"}, -+ { NULL, 2056, "0"}, -+ { "CertID", 1610612741, NULL }, -+ { "hashAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "issuerNameHash", 1073741831, NULL }, -+ { "issuerKeyHash", 1073741831, NULL }, -+ { "serialNumber", 2, "CertificateSerialNumber"}, -+ { "OCSPResponse", 1610612741, NULL }, -+ { "responseStatus", 1073741826, "OCSPResponseStatus"}, -+ { "responseBytes", 536895490, "ResponseBytes"}, -+ { NULL, 2056, "0"}, -+ { "OCSPResponseStatus", 1610874901, NULL }, -+ { "successful", 1073741825, "0"}, -+ { "malformedRequest", 1073741825, "1"}, -+ { "internalError", 1073741825, "2"}, -+ { "tryLater", 1073741825, "3"}, -+ { "sigRequired", 1073741825, "5"}, -+ { "unauthorized", 1, "6"}, -+ { "ResponseBytes", 1610612741, NULL }, -+ { "responseType", 1073741836, NULL }, -+ { "response", 7, NULL }, -+ { "BasicOCSPResponse", 1610612741, NULL }, -+ { "tbsResponseData", 1073741826, "ResponseData"}, -+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, -+ { "signature", 1073741830, NULL }, -+ { "certs", 536895499, NULL }, -+ { NULL, 1073743880, "0"}, -+ { NULL, 2, "Certificate"}, -+ { "ResponseData", 1610612741, NULL }, -+ { "version", 1610653699, NULL }, -+ { NULL, 1073741833, "0"}, -+ { NULL, 2056, "0"}, -+ { "responderID", 1073741826, "ResponderID"}, -+ { "producedAt", 1073741861, NULL }, -+ { "responses", 1610612747, NULL }, -+ { NULL, 2, "SingleResponse"}, -+ { "responseExtensions", 536895490, "Extensions"}, -+ { NULL, 2056, "1"}, -+ { "ResponderID", 1610612754, NULL }, -+ { "byName", 1610620939, NULL }, -+ { NULL, 1073743880, "1"}, -+ { NULL, 2, "RelativeDistinguishedName"}, -+ { "byKey", 536879111, NULL }, -+ { NULL, 2056, "2"}, -+ { "SingleResponse", 1610612741, NULL }, -+ { "certID", 1073741826, "CertID"}, -+ { "certStatus", 1073741826, "CertStatus"}, -+ { "thisUpdate", 1073741861, NULL }, -+ { "nextUpdate", 1610637349, NULL }, -+ { NULL, 2056, "0"}, -+ { "singleExtensions", 536895490, "Extensions"}, -+ { NULL, 2056, "1"}, -+ { "CertStatus", 1610612754, NULL }, -+ { "good", 1610620948, NULL }, -+ { NULL, 4104, "0"}, -+ { "revoked", 1610620930, "RevokedInfo"}, -+ { NULL, 4104, "1"}, -+ { "unknown", 536879106, "UnknownInfo"}, -+ { NULL, 4104, "2"}, -+ { "RevokedInfo", 1610612741, NULL }, -+ { "revocationTime", 1073741861, NULL }, -+ { "revocationReason", 537157653, NULL }, -+ { NULL, 1073743880, "0"}, -+ { "unspecified", 1, "0"}, -+ { "UnknownInfo", 1073741844, NULL }, -+ { "NameConstraints", 1610612741, NULL }, -+ { "permittedSubtrees", 1610637314, "GeneralSubtrees"}, -+ { NULL, 4104, "0"}, -+ { "excludedSubtrees", 536895490, "GeneralSubtrees"}, -+ { NULL, 4104, "1"}, -+ { "GeneralSubtrees", 1612709899, NULL }, -+ { "MAX", 1074266122, "1"}, -+ { NULL, 2, "GeneralSubtree"}, -+ { "GeneralSubtree", 1610612741, NULL }, -+ { "base", 1073741826, "GeneralName"}, -+ { "minimum", 1610653699, NULL }, -+ { NULL, 1073741833, "0"}, -+ { NULL, 4104, "0"}, -+ { "maximum", 536895491, NULL }, -+ { NULL, 4104, "1"}, -+ { "TlsFeatures", 536870923, NULL }, -+ { NULL, 3, NULL }, -+ { NULL, 0, NULL } -+}; diff --git a/SOURCES/0192-fs-btrfs-Use-full-btrfs-bootloader-area.patch b/SOURCES/0192-fs-btrfs-Use-full-btrfs-bootloader-area.patch new file mode 100644 index 0000000..3f7198f --- /dev/null +++ b/SOURCES/0192-fs-btrfs-Use-full-btrfs-bootloader-area.patch @@ -0,0 +1,160 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 13 Dec 2021 14:25:49 +0800 +Subject: [PATCH] fs/btrfs: Use full btrfs bootloader area + +Up to now GRUB can only embed to the first 64 KiB before primary +superblock of btrfs, effectively limiting the GRUB core size. That +could consequently pose restrictions to feature enablement like +advanced zstd compression. + +This patch attempts to utilize full unused area reserved by btrfs for +the bootloader outlined in the document [1]: + + The first 1MiB on each device is unused with the exception of primary + superblock that is on the offset 64KiB and spans 4KiB. + +Apart from that, adjacent sectors to superblock and first block group +are not used for embedding in case of overflow and logged access to +adjacent sectors could be useful for tracing it up. + +This patch has been tested to provide out of the box support for btrfs +zstd compression with which GRUB has been installed to the partition. + +[1] https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT + +Signed-off-by: Michael Chang +Reviewed-by: Daniel Kiper +(cherry picked from commit b0f06a81c6f31b6fa20be67a96b6683bba8210c9) +--- + grub-core/fs/btrfs.c | 90 ++++++++++++++++++++++++++++++++++++++++++++-------- + include/grub/disk.h | 2 ++ + 2 files changed, 79 insertions(+), 13 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 4cc86e9b79..07c0ff874b 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -2476,6 +2476,33 @@ grub_btrfs_label (grub_device_t device, char **label) + } + + #ifdef GRUB_UTIL ++ ++struct embed_region { ++ unsigned int start; ++ unsigned int secs; ++}; ++ ++/* ++ * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT ++ * The first 1 MiB on each device is unused with the exception of primary ++ * superblock that is on the offset 64 KiB and spans 4 KiB. ++ */ ++ ++static const struct { ++ struct embed_region available; ++ struct embed_region used[6]; ++} btrfs_head = { ++ .available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */ ++ .used = { ++ {0, 1}, /* boot.S. */ ++ {GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */ ++ {GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */ ++ {GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */ ++ {GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */ ++ {0, 0} /* Array terminator. */ ++ } ++}; ++ + static grub_err_t + grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), + unsigned int *nsectors, +@@ -2483,25 +2510,62 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) + { +- unsigned i; ++ unsigned int i, j, n = 0; ++ const struct embed_region *u; ++ grub_disk_addr_t *map; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "BtrFS currently supports only PC-BIOS embedding"); + +- if (64 * 2 - 1 < *nsectors) +- return grub_error (GRUB_ERR_OUT_OF_RANGE, +- N_("your core.img is unusually large. " +- "It won't fit in the embedding area")); +- +- *nsectors = 64 * 2 - 1; +- if (*nsectors > max_nsectors) +- *nsectors = max_nsectors; +- *sectors = grub_calloc (*nsectors, sizeof (**sectors)); +- if (!*sectors) ++ map = grub_calloc (btrfs_head.available.secs, sizeof (*map)); ++ if (map == NULL) + return grub_errno; +- for (i = 0; i < *nsectors; i++) +- (*sectors)[i] = i + 1; ++ ++ /* ++ * Populating the map array so that it can be used to index if a disk ++ * address is available to embed: ++ * - 0: available, ++ * - 1: unavailable. ++ */ ++ for (u = btrfs_head.used; u->secs; ++u) ++ { ++ unsigned int end = u->start + u->secs; ++ ++ if (end > btrfs_head.available.secs) ++ end = btrfs_head.available.secs; ++ for (i = u->start; i < end; ++i) ++ map[i] = 1; ++ } ++ ++ /* Adding up n until it matches total size of available embedding area. */ ++ for (i = 0; i < btrfs_head.available.secs; ++i) ++ if (map[i] == 0) ++ n++; ++ ++ if (n < *nsectors) ++ { ++ grub_free (map); ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("your core.img is unusually large. " ++ "It won't fit in the embedding area")); ++ } ++ ++ if (n > max_nsectors) ++ n = max_nsectors; ++ ++ /* ++ * Populating the array so that it can used to index disk block address for ++ * an image file's offset to be embedded on disk (the unit is in sectors): ++ * - i: The disk block address relative to btrfs_head.available.start, ++ * - j: The offset in image file. ++ */ ++ for (i = 0, j = 0; i < btrfs_head.available.secs && j < n; ++i) ++ if (map[i] == 0) ++ map[j++] = btrfs_head.available.start + i; ++ ++ *nsectors = n; ++ *sectors = map; + + return GRUB_ERR_NONE; + } +diff --git a/include/grub/disk.h b/include/grub/disk.h +index f95aca929a..06210a7049 100644 +--- a/include/grub/disk.h ++++ b/include/grub/disk.h +@@ -182,6 +182,8 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t; + /* Return value of grub_disk_native_sectors() in case disk size is unknown. */ + #define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL + ++#define GRUB_DISK_KiB_TO_SECTORS(x) ((x) << (10 - GRUB_DISK_SECTOR_BITS)) ++ + /* Convert sector number from one sector size to another. */ + static inline grub_disk_addr_t + grub_convert_sector (grub_disk_addr_t sector, diff --git a/SOURCES/0193-Add-Fedora-location-of-DejaVu-SANS-font.patch b/SOURCES/0193-Add-Fedora-location-of-DejaVu-SANS-font.patch new file mode 100644 index 0000000..070fc24 --- /dev/null +++ b/SOURCES/0193-Add-Fedora-location-of-DejaVu-SANS-font.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: fluteze +Date: Sat, 27 Nov 2021 10:54:44 -0600 +Subject: [PATCH] Add Fedora location of DejaVu SANS font + +In Fedora 35, and possibly earlier, grub would fail to configure with a +complaint about DejaVu being "not found" even though it was installed. +The DejaVu sans font search path is updated to reflect the +distribution's current install path. + +Signed-off-by: Erik Edwards +[rharwood@redhat.com: slight commit message edits] +Signed-off-by: Robbie Harwood +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index ab0d326f00..40c4338bce 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1784,7 +1784,7 @@ fi + + if test x"$starfield_excuse" = x; then + for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do +- for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do ++ for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/share/fonts/dejavu-sans-fonts; do + if test -f "$dir/DejaVuSans.$ext"; then + DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext" + break 2 diff --git a/SOURCES/0193-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch b/SOURCES/0193-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch deleted file mode 100644 index 04bf1df..0000000 --- a/SOURCES/0193-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch +++ /dev/null @@ -1,1528 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 30 Jul 2020 01:33:46 +1000 -Subject: [PATCH] appended signatures: parse PKCS#7 signedData and X.509 - certificates - -This code allows us to parse: - - - PKCS#7 signedData messages. Only a single signerInfo is supported, - which is all that the Linux sign-file utility supports creating - out-of-the-box. Only RSA, SHA-256 and SHA-512 are supported. - Any certificate embedded in the PKCS#7 message will be ignored. - - - X.509 certificates: at least enough to verify the signatures on the - PKCS#7 messages. We expect that the certificates embedded in grub will - be leaf certificates, not CA certificates. The parser enforces this. - -Signed-off-by: Daniel Axtens ---- - grub-core/commands/appendedsig/asn1util.c | 102 +++ - grub-core/commands/appendedsig/pkcs7.c | 305 +++++++++ - grub-core/commands/appendedsig/x509.c | 958 +++++++++++++++++++++++++++ - grub-core/commands/appendedsig/appendedsig.h | 110 +++ - 4 files changed, 1475 insertions(+) - create mode 100644 grub-core/commands/appendedsig/asn1util.c - create mode 100644 grub-core/commands/appendedsig/pkcs7.c - create mode 100644 grub-core/commands/appendedsig/x509.c - create mode 100644 grub-core/commands/appendedsig/appendedsig.h - -diff --git a/grub-core/commands/appendedsig/asn1util.c b/grub-core/commands/appendedsig/asn1util.c -new file mode 100644 -index 00000000000..eff095a9df2 ---- /dev/null -+++ b/grub-core/commands/appendedsig/asn1util.c -@@ -0,0 +1,102 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "appendedsig.h" -+ -+asn1_node _gnutls_gnutls_asn = ASN1_TYPE_EMPTY; -+asn1_node _gnutls_pkix_asn = ASN1_TYPE_EMPTY; -+ -+extern const ASN1_ARRAY_TYPE gnutls_asn1_tab[]; -+extern const ASN1_ARRAY_TYPE pkix_asn1_tab[]; -+ -+/* -+ * Read a value from an ASN1 node, allocating memory to store it. -+ * -+ * It will work for anything where the size libtasn1 returns is right: -+ * - Integers -+ * - Octet strings -+ * - DER encoding of other structures -+ * It will _not_ work for things where libtasn1 size requires adjustment: -+ * - Strings that require an extra NULL byte at the end -+ * - Bit strings because libtasn1 returns the length in bits, not bytes. -+ * -+ * If the function returns a non-NULL value, the caller must free it. -+ */ -+void * -+grub_asn1_allocate_and_read (asn1_node node, const char *name, -+ const char *friendly_name, int *content_size) -+{ -+ int result; -+ grub_uint8_t *tmpstr = NULL; -+ int tmpstr_size = 0; -+ -+ result = asn1_read_value (node, name, NULL, &tmpstr_size); -+ if (result != ASN1_MEM_ERROR) -+ { -+ grub_snprintf (grub_errmsg, sizeof (grub_errmsg), -+ _ -+ ("Reading size of %s did not return expected status: %s"), -+ friendly_name, asn1_strerror (result)); -+ grub_errno = GRUB_ERR_BAD_FILE_TYPE; -+ return NULL; -+ } -+ -+ tmpstr = grub_malloc (tmpstr_size); -+ if (tmpstr == NULL) -+ { -+ grub_snprintf (grub_errmsg, sizeof (grub_errmsg), -+ "Could not allocate memory to store %s", friendly_name); -+ grub_errno = GRUB_ERR_OUT_OF_MEMORY; -+ return NULL; -+ } -+ -+ result = asn1_read_value (node, name, tmpstr, &tmpstr_size); -+ if (result != ASN1_SUCCESS) -+ { -+ grub_free (tmpstr); -+ grub_snprintf (grub_errmsg, sizeof (grub_errmsg), -+ "Error reading %s: %s", -+ friendly_name, asn1_strerror (result)); -+ grub_errno = GRUB_ERR_BAD_FILE_TYPE; -+ return NULL; -+ } -+ -+ *content_size = tmpstr_size; -+ -+ return tmpstr; -+} -+ -+int -+asn1_init (void) -+{ -+ int res; -+ res = asn1_array2tree (gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL); -+ if (res != ASN1_SUCCESS) -+ { -+ return res; -+ } -+ res = asn1_array2tree (pkix_asn1_tab, &_gnutls_pkix_asn, NULL); -+ return res; -+} -diff --git a/grub-core/commands/appendedsig/pkcs7.c b/grub-core/commands/appendedsig/pkcs7.c -new file mode 100644 -index 00000000000..dc6afe203f7 ---- /dev/null -+++ b/grub-core/commands/appendedsig/pkcs7.c -@@ -0,0 +1,305 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include "appendedsig.h" -+#include -+#include -+#include -+ -+ -+static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; -+ -+/* -+ * RFC 5652 s 5.1 -+ */ -+const char *signedData_oid = "1.2.840.113549.1.7.2"; -+ -+/* -+ * RFC 4055 s 2.1 -+ */ -+const char *sha256_oid = "2.16.840.1.101.3.4.2.1"; -+const char *sha512_oid = "2.16.840.1.101.3.4.2.3"; -+ -+static grub_err_t -+process_content (grub_uint8_t * content, int size, -+ struct pkcs7_signedData *msg) -+{ -+ int res; -+ asn1_node signed_part; -+ grub_err_t err = GRUB_ERR_NONE; -+ char algo_oid[MAX_OID_LEN]; -+ int algo_oid_size = sizeof (algo_oid); -+ int algo_count; -+ char version; -+ int version_size = sizeof (version); -+ grub_uint8_t *result_buf; -+ int result_size = 0; -+ int crls_size = 0; -+ gcry_error_t gcry_err; -+ -+ res = asn1_create_element (_gnutls_pkix_asn, "PKIX1.pkcs-7-SignedData", -+ &signed_part); -+ if (res != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for PKCS#7 signed part."); -+ } -+ -+ res = asn1_der_decoding2 (&signed_part, content, &size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (res != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Error reading PKCS#7 signed data: %s", asn1_error); -+ goto cleanup_signed_part; -+ } -+ -+ /* SignedData ::= SEQUENCE { -+ * version CMSVersion, -+ * digestAlgorithms DigestAlgorithmIdentifiers, -+ * encapContentInfo EncapsulatedContentInfo, -+ * certificates [0] IMPLICIT CertificateSet OPTIONAL, -+ * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL, -+ * signerInfos SignerInfos } -+ */ -+ -+ /* version per the algo in 5.1, must be 1 */ -+ res = asn1_read_value (signed_part, "version", &version, &version_size); -+ if (res != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Error reading signedData version: %s", -+ asn1_strerror (res)); -+ goto cleanup_signed_part; -+ } -+ -+ if (version != 1) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Unexpected signature version v%d, only v1 supported", -+ version); -+ goto cleanup_signed_part; -+ } -+ -+ /* -+ * digestAlgorithms DigestAlgorithmIdentifiers -+ * -+ * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier -+ * DigestAlgorithmIdentifer is an X.509 AlgorithmIdentifier (10.1.1) -+ * -+ * RFC 4055 s 2.1: -+ * sha256Identifier AlgorithmIdentifier ::= { id-sha256, NULL } -+ * sha512Identifier AlgorithmIdentifier ::= { id-sha512, NULL } -+ * -+ * We only support 1 element in the set, and we do not check parameters atm. -+ */ -+ res = -+ asn1_number_of_elements (signed_part, "digestAlgorithms", &algo_count); -+ if (res != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Error counting number of digest algorithms: %s", -+ asn1_strerror (res)); -+ goto cleanup_signed_part; -+ } -+ -+ if (algo_count != 1) -+ { -+ err = -+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ "Only 1 digest algorithm is supported"); -+ goto cleanup_signed_part; -+ } -+ -+ res = -+ asn1_read_value (signed_part, "digestAlgorithms.?1.algorithm", algo_oid, -+ &algo_oid_size); -+ if (res != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Error reading digest algorithm: %s", -+ asn1_strerror (res)); -+ goto cleanup_signed_part; -+ } -+ -+ if (grub_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0) -+ { -+ msg->hash = grub_crypto_lookup_md_by_name ("sha512"); -+ } -+ else if (grub_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0) -+ { -+ msg->hash = grub_crypto_lookup_md_by_name ("sha256"); -+ } -+ else -+ { -+ err = -+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ "Only SHA-256 and SHA-512 hashes are supported, found OID %s", -+ algo_oid); -+ goto cleanup_signed_part; -+ } -+ -+ if (!msg->hash) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Hash algorithm for OID %s not loaded", algo_oid); -+ goto cleanup_signed_part; -+ } -+ -+ /* -+ * We ignore the certificates, but we don't permit CRLs. -+ * A CRL entry might be revoking the certificate we're using, and we have -+ * no way of dealing with that at the moment. -+ */ -+ res = asn1_read_value (signed_part, "crls", NULL, &crls_size); -+ if (res != ASN1_ELEMENT_NOT_FOUND) -+ { -+ err = -+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ "PKCS#7 messages with embedded CRLs are not supported"); -+ goto cleanup_signed_part; -+ } -+ -+ /* read the signature */ -+ result_buf = -+ grub_asn1_allocate_and_read (signed_part, "signerInfos.?1.signature", -+ "signature data", &result_size); -+ if (!result_buf) -+ { -+ err = grub_errno; -+ goto cleanup_signed_part; -+ } -+ -+ gcry_err = -+ gcry_mpi_scan (&(msg->sig_mpi), GCRYMPI_FMT_USG, result_buf, result_size, -+ NULL); -+ if (gcry_err != GPG_ERR_NO_ERROR) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Error loading signature into MPI structure: %d", -+ gcry_err); -+ goto cleanup_result; -+ } -+ -+cleanup_result: -+ grub_free (result_buf); -+cleanup_signed_part: -+ asn1_delete_structure (&signed_part); -+ -+ return err; -+} -+ -+grub_err_t -+parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size, -+ struct pkcs7_signedData *msg) -+{ -+ int res; -+ asn1_node content_info; -+ grub_err_t err = GRUB_ERR_NONE; -+ char content_oid[MAX_OID_LEN]; -+ grub_uint8_t *content; -+ int content_size; -+ int content_oid_size = sizeof (content_oid); -+ int size; -+ -+ if (data_size > GRUB_INT_MAX) -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ "Cannot parse a PKCS#7 message where data size > INT_MAX"); -+ size = (int) data_size; -+ -+ res = asn1_create_element (_gnutls_pkix_asn, -+ "PKIX1.pkcs-7-ContentInfo", &content_info); -+ if (res != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for PKCS#7 data: %s", -+ asn1_strerror (res)); -+ } -+ -+ res = asn1_der_decoding2 (&content_info, sigbuf, &size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (res != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Error decoding PKCS#7 message DER: %s", asn1_error); -+ goto cleanup; -+ } -+ -+ /* -+ * ContentInfo ::= SEQUENCE { -+ * contentType ContentType, -+ * content [0] EXPLICIT ANY DEFINED BY contentType } -+ * -+ * ContentType ::= OBJECT IDENTIFIER -+ */ -+ res = -+ asn1_read_value (content_info, "contentType", content_oid, -+ &content_oid_size); -+ if (res != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Error reading PKCS#7 content type: %s", -+ asn1_strerror (res)); -+ goto cleanup; -+ } -+ -+ /* OID for SignedData defined in 5.1 */ -+ if (grub_strncmp (signedData_oid, content_oid, content_oid_size) != 0) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_SIGNATURE, -+ "Unexpected content type in PKCS#7 message: OID %s", -+ content_oid); -+ goto cleanup; -+ } -+ -+ content = -+ grub_asn1_allocate_and_read (content_info, "content", -+ "PKCS#7 message content", &content_size); -+ if (!content) -+ { -+ err = grub_errno; -+ goto cleanup; -+ } -+ -+ err = process_content (content, content_size, msg); -+ grub_free (content); -+ -+cleanup: -+ asn1_delete_structure (&content_info); -+ return err; -+} -+ -+/* -+ * Release all the storage associated with the PKCS#7 message. -+ * If the caller dynamically allocated the message, it must free it. -+ */ -+void -+pkcs7_signedData_release (struct pkcs7_signedData *msg) -+{ -+ gcry_mpi_release (msg->sig_mpi); -+} -diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c -new file mode 100644 -index 00000000000..2b38b3670a2 ---- /dev/null -+++ b/grub-core/commands/appendedsig/x509.c -@@ -0,0 +1,958 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "appendedsig.h" -+ -+static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; -+ -+/* -+ * RFC 3279 2.3.1 RSA Keys -+ */ -+const char *rsaEncryption_oid = "1.2.840.113549.1.1.1"; -+ -+/* -+ * RFC 5280 Appendix A -+ */ -+const char *commonName_oid = "2.5.4.3"; -+ -+/* -+ * RFC 5280 4.2.1.3 Key Usage -+ */ -+const char *keyUsage_oid = "2.5.29.15"; -+ -+/* -+ * RFC 5280 4.2.1.9 Basic Constraints -+ */ -+const char *basicConstraints_oid = "2.5.29.19"; -+ -+/* -+ * RFC 3279 2.3.1 -+ * -+ * The RSA public key MUST be encoded using the ASN.1 type RSAPublicKey: -+ * -+ * RSAPublicKey ::= SEQUENCE { -+ * modulus INTEGER, -- n -+ * publicExponent INTEGER } -- e -+ * -+ * where modulus is the modulus n, and publicExponent is the public -+ * exponent e. -+ */ -+static grub_err_t -+grub_parse_rsa_pubkey (grub_uint8_t * der, int dersize, -+ struct x509_certificate *certificate) -+{ -+ int result; -+ asn1_node spk = ASN1_TYPE_EMPTY; -+ grub_uint8_t *m_data, *e_data; -+ int m_size, e_size; -+ grub_err_t err = GRUB_ERR_NONE; -+ gcry_error_t gcry_err; -+ -+ result = -+ asn1_create_element (_gnutls_gnutls_asn, "GNUTLS.RSAPublicKey", &spk); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Cannot create storage for public key ASN.1 data"); -+ } -+ -+ result = asn1_der_decoding2 (&spk, der, &dersize, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Cannot decode certificate public key DER: %s", -+ asn1_error); -+ goto cleanup; -+ } -+ -+ m_data = -+ grub_asn1_allocate_and_read (spk, "modulus", "RSA modulus", &m_size); -+ if (!m_data) -+ { -+ err = grub_errno; -+ goto cleanup; -+ } -+ -+ e_data = -+ grub_asn1_allocate_and_read (spk, "publicExponent", "RSA public exponent", -+ &e_size); -+ if (!e_data) -+ { -+ err = grub_errno; -+ goto cleanup_m_data; -+ } -+ -+ /* -+ * convert m, e to mpi -+ * -+ * nscanned is not set for FMT_USG, it's only set for FMT_PGP, -+ * so we can't verify it -+ */ -+ gcry_err = -+ gcry_mpi_scan (&certificate->mpis[0], GCRYMPI_FMT_USG, m_data, m_size, -+ NULL); -+ if (gcry_err != GPG_ERR_NO_ERROR) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error loading RSA modulus into MPI structure: %d", -+ gcry_err); -+ goto cleanup_e_data; -+ } -+ -+ gcry_err = -+ gcry_mpi_scan (&certificate->mpis[1], GCRYMPI_FMT_USG, e_data, e_size, -+ NULL); -+ if (gcry_err != GPG_ERR_NO_ERROR) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error loading RSA exponent into MPI structure: %d", -+ gcry_err); -+ goto cleanup_m_mpi; -+ } -+ -+ grub_free (e_data); -+ grub_free (m_data); -+ asn1_delete_structure (&spk); -+ return GRUB_ERR_NONE; -+ -+cleanup_m_mpi: -+ gcry_mpi_release (certificate->mpis[0]); -+cleanup_e_data: -+ grub_free (e_data); -+cleanup_m_data: -+ grub_free (m_data); -+cleanup: -+ asn1_delete_structure (&spk); -+ return err; -+} -+ -+ -+/* -+ * RFC 5280: -+ * SubjectPublicKeyInfo ::= SEQUENCE { -+ * algorithm AlgorithmIdentifier, -+ * subjectPublicKey BIT STRING } -+ * -+ * AlgorithmIdentifiers come from RFC 3279, we are not strictly compilant as we -+ * only support RSA Encryption. -+ */ -+ -+static grub_err_t -+grub_x509_read_subject_public_key (asn1_node asn, -+ struct x509_certificate *results) -+{ -+ int result; -+ grub_err_t err; -+ const char *algo_name = -+ "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm"; -+ const char *params_name = -+ "tbsCertificate.subjectPublicKeyInfo.algorithm.parameters"; -+ const char *pk_name = -+ "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey"; -+ char algo_oid[MAX_OID_LEN]; -+ int algo_size = sizeof (algo_oid); -+ char params_value[2]; -+ int params_size = sizeof (params_value); -+ grub_uint8_t *key_data = NULL; -+ int key_size = 0; -+ unsigned int key_type; -+ -+ /* algorithm: see notes for rsaEncryption_oid */ -+ result = asn1_read_value (asn, algo_name, algo_oid, &algo_size); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading x509 public key algorithm: %s", -+ asn1_strerror (result)); -+ } -+ -+ if (grub_strncmp (algo_oid, rsaEncryption_oid, sizeof (rsaEncryption_oid)) -+ != 0) -+ { -+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ "Unsupported x509 public key algorithm: %s", -+ algo_oid); -+ } -+ -+ /* -+ * RFC 3279 2.3.1 -+ * The rsaEncryption OID is intended to be used in the algorithm field -+ * of a value of type AlgorithmIdentifier. The parameters field MUST -+ * have ASN.1 type NULL for this algorithm identifier. -+ */ -+ result = asn1_read_value (asn, params_name, params_value, ¶ms_size); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading x509 public key parameters: %s", -+ asn1_strerror (result)); -+ } -+ -+ if (params_value[0] != ASN1_TAG_NULL) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Invalid x509 public key parameters: expected NULL"); -+ } -+ -+ /* -+ * RFC 3279 2.3.1: The DER encoded RSAPublicKey is the value of the BIT -+ * STRING subjectPublicKey. -+ */ -+ result = asn1_read_value_type (asn, pk_name, NULL, &key_size, &key_type); -+ if (result != ASN1_MEM_ERROR) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading size of x509 public key: %s", -+ asn1_strerror (result)); -+ } -+ if (key_type != ASN1_ETYPE_BIT_STRING) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unexpected ASN.1 type when reading x509 public key: %x", -+ key_type); -+ } -+ -+ /* length is in bits */ -+ key_size = (key_size + 7) / 8; -+ -+ key_data = grub_malloc (key_size); -+ if (!key_data) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Out of memory for x509 public key"); -+ } -+ -+ result = asn1_read_value (asn, pk_name, key_data, &key_size); -+ if (result != ASN1_SUCCESS) -+ { -+ grub_free (key_data); -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading public key data"); -+ } -+ key_size = (key_size + 7) / 8; -+ -+ err = grub_parse_rsa_pubkey (key_data, key_size, results); -+ grub_free (key_data); -+ -+ return err; -+} -+ -+/* Decode a string as defined in Appendix A */ -+static grub_err_t -+decode_string (char *der, int der_size, char **string, -+ grub_size_t * string_size) -+{ -+ asn1_node strasn; -+ int result; -+ char *choice; -+ int choice_size = 0; -+ int tmp_size = 0; -+ grub_err_t err = GRUB_ERR_NONE; -+ -+ result = -+ asn1_create_element (_gnutls_pkix_asn, "PKIX1.DirectoryString", &strasn); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for certificate: %s", -+ asn1_strerror (result)); -+ } -+ -+ result = asn1_der_decoding2 (&strasn, der, &der_size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Could not parse DER for DirectoryString: %s", -+ asn1_error); -+ goto cleanup; -+ } -+ -+ choice = -+ grub_asn1_allocate_and_read (strasn, "", "DirectoryString choice", -+ &choice_size); -+ if (!choice) -+ { -+ err = grub_errno; -+ goto cleanup; -+ } -+ -+ if (grub_strncmp ("utf8String", choice, choice_size)) -+ { -+ err = -+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ "Only UTF-8 DirectoryStrings are supported, got %s", -+ choice); -+ goto cleanup_choice; -+ } -+ -+ result = asn1_read_value (strasn, "utf8String", NULL, &tmp_size); -+ if (result != ASN1_MEM_ERROR) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading size of UTF-8 string: %s", -+ asn1_strerror (result)); -+ goto cleanup_choice; -+ } -+ -+ /* read size does not include trailing null */ -+ tmp_size++; -+ -+ *string = grub_malloc (tmp_size); -+ if (!*string) -+ { -+ err = -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Cannot allocate memory for DirectoryString contents"); -+ goto cleanup_choice; -+ } -+ -+ result = asn1_read_value (strasn, "utf8String", *string, &tmp_size); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading out UTF-8 string in DirectoryString: %s", -+ asn1_strerror (result)); -+ grub_free (*string); -+ goto cleanup_choice; -+ } -+ *string_size = tmp_size + 1; -+ (*string)[tmp_size] = '\0'; -+ -+cleanup_choice: -+ grub_free (choice); -+cleanup: -+ asn1_delete_structure (&strasn); -+ return err; -+} -+ -+/* -+ * TBSCertificate ::= SEQUENCE { -+ * version [0] EXPLICIT Version DEFAULT v1, -+ * ... -+ * -+ * Version ::= INTEGER { v1(0), v2(1), v3(2) } -+ */ -+static grub_err_t -+check_version (asn1_node certificate) -+{ -+ int rc; -+ const char *name = "tbsCertificate.version"; -+ grub_uint8_t version; -+ int len = 1; -+ -+ rc = asn1_read_value (certificate, name, &version, &len); -+ -+ /* require version 3 */ -+ if (rc != ASN1_SUCCESS || len != 1) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading certificate version"); -+ -+ if (version != 0x02) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Invalid x509 certificate version, expected v3 (0x02), got 0x%02x", -+ version); -+ -+ return GRUB_ERR_NONE; -+} -+ -+/* -+ * This is an X.501 Name, which is complex. -+ * -+ * For simplicity, we extract only the CN. -+ */ -+static grub_err_t -+read_name (asn1_node asn, const char *name_path, char **name, -+ grub_size_t * name_size) -+{ -+ int seq_components, set_components; -+ int result; -+ int i, j; -+ char *top_path, *set_path, *type_path, *val_path; -+ char type[MAX_OID_LEN]; -+ int type_len = sizeof (type); -+ int string_size = 0; -+ char *string_der; -+ grub_err_t err; -+ -+ *name = NULL; -+ -+ top_path = grub_xasprintf ("%s.rdnSequence", name_path); -+ if (!top_path) -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not allocate memory for %s name parsing path", -+ name_path); -+ -+ result = asn1_number_of_elements (asn, top_path, &seq_components); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error counting name components: %s", -+ asn1_strerror (result)); -+ goto cleanup; -+ } -+ -+ for (i = 1; i <= seq_components; i++) -+ { -+ set_path = grub_xasprintf ("%s.?%d", top_path, i); -+ if (!set_path) -+ { -+ err = -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not allocate memory for %s name set parsing path", -+ name_path); -+ goto cleanup_set; -+ } -+ /* this brings us, hopefully, to a set */ -+ result = asn1_number_of_elements (asn, set_path, &set_components); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error counting name sub-components components (element %d): %s", -+ i, asn1_strerror (result)); -+ goto cleanup_set; -+ } -+ for (j = 1; j <= set_components; j++) -+ { -+ type_path = grub_xasprintf ("%s.?%d.?%d.type", top_path, i, j); -+ if (!type_path) -+ { -+ err = -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not allocate memory for %s name component type path", -+ name_path); -+ goto cleanup_set; -+ } -+ type_len = sizeof (type); -+ result = asn1_read_value (asn, type_path, type, &type_len); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading %s name component type: %s", -+ name_path, asn1_strerror (result)); -+ goto cleanup_type; -+ } -+ -+ if (grub_strncmp (type, commonName_oid, type_len) != 0) -+ { -+ grub_free (type_path); -+ continue; -+ } -+ -+ val_path = grub_xasprintf ("%s.?%d.?%d.value", top_path, i, j); -+ if (!val_path) -+ { -+ err = -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not allocate memory for %s name component value path", -+ name_path); -+ goto cleanup_set; -+ } -+ -+ string_der = -+ grub_asn1_allocate_and_read (asn, val_path, name_path, -+ &string_size); -+ if (!string_der) -+ { -+ err = grub_errno; -+ goto cleanup_val_path; -+ } -+ -+ err = decode_string (string_der, string_size, name, name_size); -+ if (err) -+ goto cleanup_string; -+ -+ grub_free (string_der); -+ grub_free (type_path); -+ grub_free (val_path); -+ break; -+ } -+ grub_free (set_path); -+ -+ if (*name) -+ break; -+ } -+ -+ return GRUB_ERR_NONE; -+ -+cleanup_string: -+ grub_free (string_der); -+cleanup_val_path: -+ grub_free (val_path); -+cleanup_type: -+ grub_free (type_path); -+cleanup_set: -+ grub_free (set_path); -+cleanup: -+ grub_free (top_path); -+ return err; -+} -+ -+/* -+ * details here -+ */ -+static grub_err_t -+verify_key_usage (grub_uint8_t * value, int value_size) -+{ -+ asn1_node usageasn; -+ int result; -+ grub_err_t err = GRUB_ERR_NONE; -+ grub_uint8_t usage = 0xff; -+ int usage_size = 1; -+ -+ result = -+ asn1_create_element (_gnutls_pkix_asn, "PKIX1.KeyUsage", &usageasn); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for key usage"); -+ } -+ -+ result = asn1_der_decoding2 (&usageasn, value, &value_size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error parsing DER for Key Usage: %s", asn1_error); -+ goto cleanup; -+ } -+ -+ result = asn1_read_value (usageasn, "", &usage, &usage_size); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading Key Usage value: %s", -+ asn1_strerror (result)); -+ goto cleanup; -+ } -+ -+ /* Only the first bit is permitted to be set */ -+ if (usage != 0x80) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unexpected Key Usage value: %x", -+ usage); -+ goto cleanup; -+ } -+ -+cleanup: -+ asn1_delete_structure (&usageasn); -+ return err; -+} -+ -+/* -+ * BasicConstraints ::= SEQUENCE { -+ * cA BOOLEAN DEFAULT FALSE, -+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL } -+ */ -+static grub_err_t -+verify_basic_constraints (grub_uint8_t * value, int value_size) -+{ -+ asn1_node basicasn; -+ int result; -+ grub_err_t err = GRUB_ERR_NONE; -+ char cA[6]; /* FALSE or TRUE */ -+ int cA_size = sizeof (cA); -+ -+ result = -+ asn1_create_element (_gnutls_pkix_asn, "PKIX1.BasicConstraints", -+ &basicasn); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for Basic Constraints"); -+ } -+ -+ result = asn1_der_decoding2 (&basicasn, value, &value_size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error parsing DER for Basic Constraints: %s", -+ asn1_error); -+ goto cleanup; -+ } -+ -+ result = asn1_read_value (basicasn, "cA", cA, &cA_size); -+ if (result == ASN1_ELEMENT_NOT_FOUND) -+ { -+ /* Not present, default is False, so this is OK */ -+ err = GRUB_ERR_NONE; -+ goto cleanup; -+ } -+ else if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading Basic Constraints cA value: %s", -+ asn1_strerror (result)); -+ goto cleanup; -+ } -+ -+ /* The certificate must not be a CA certificate */ -+ if (grub_strncmp ("FALSE", cA, cA_size) != 0) -+ { -+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unexpected CA value: %s", -+ cA); -+ goto cleanup; -+ } -+ -+cleanup: -+ asn1_delete_structure (&basicasn); -+ return err; -+} -+ -+ -+/* -+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension -+ * -+ * Extension ::= SEQUENCE { -+ * extnID OBJECT IDENTIFIER, -+ * critical BOOLEAN DEFAULT FALSE, -+ * extnValue OCTET STRING -+ * -- contains the DER encoding of an ASN.1 value -+ * -- corresponding to the extension type identified -+ * -- by extnID -+ * } -+ * -+ * We require that a certificate: -+ * - contain the Digital Signature usage only -+ * - not be a CA -+ * - MUST not contain any other critical extensions (RFC 5280 s 4.2) -+ */ -+static grub_err_t -+verify_extensions (asn1_node cert) -+{ -+ int result; -+ int ext, num_extensions = 0; -+ int usage_present = 0, constraints_present = 0; -+ char *oid_path, *critical_path, *value_path; -+ char extnID[MAX_OID_LEN]; -+ int extnID_size; -+ grub_err_t err; -+ char critical[6]; /* we get either "TRUE" or "FALSE" */ -+ int critical_size; -+ grub_uint8_t *value; -+ int value_size; -+ -+ result = -+ asn1_number_of_elements (cert, "tbsCertificate.extensions", -+ &num_extensions); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error counting number of extensions: %s", -+ asn1_strerror (result)); -+ } -+ -+ if (num_extensions < 2) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Insufficient number of extensions for certificate, need at least 2, got %d", -+ num_extensions); -+ } -+ -+ for (ext = 1; ext <= num_extensions; ext++) -+ { -+ oid_path = grub_xasprintf ("tbsCertificate.extensions.?%d.extnID", ext); -+ -+ extnID_size = sizeof (extnID); -+ result = asn1_read_value (cert, oid_path, extnID, &extnID_size); -+ if (result != GRUB_ERR_NONE) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading extension OID: %s", -+ asn1_strerror (result)); -+ goto cleanup_oid_path; -+ } -+ -+ critical_path = -+ grub_xasprintf ("tbsCertificate.extensions.?%d.critical", ext); -+ critical_size = sizeof (critical); -+ result = -+ asn1_read_value (cert, critical_path, critical, &critical_size); -+ if (result == ASN1_ELEMENT_NOT_FOUND) -+ { -+ critical[0] = '\0'; -+ } -+ else if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading extension criticality: %s", -+ asn1_strerror (result)); -+ goto cleanup_critical_path; -+ } -+ -+ value_path = -+ grub_xasprintf ("tbsCertificate.extensions.?%d.extnValue", ext); -+ value = -+ grub_asn1_allocate_and_read (cert, value_path, -+ "certificate extension value", -+ &value_size); -+ if (!value) -+ { -+ err = grub_errno; -+ goto cleanup_value_path; -+ } -+ -+ /* -+ * Now we must see if we recognise the OID. -+ * If we have an unrecognised critical extension we MUST bail. -+ */ -+ if (grub_strncmp (keyUsage_oid, extnID, extnID_size) == 0) -+ { -+ err = verify_key_usage (value, value_size); -+ if (err != GRUB_ERR_NONE) -+ { -+ goto cleanup_value; -+ } -+ usage_present++; -+ } -+ else if (grub_strncmp (basicConstraints_oid, extnID, extnID_size) == 0) -+ { -+ err = verify_basic_constraints (value, value_size); -+ if (err != GRUB_ERR_NONE) -+ { -+ goto cleanup_value; -+ } -+ constraints_present++; -+ } -+ else if (grub_strncmp ("TRUE", critical, critical_size) == 0) -+ { -+ /* -+ * per the RFC, we must not process a certificate with -+ * a critical extension we do not understand. -+ */ -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unhandled critical x509 extension with OID %s", -+ extnID); -+ goto cleanup_value; -+ } -+ -+ grub_free (value); -+ grub_free (value_path); -+ grub_free (critical_path); -+ grub_free (oid_path); -+ } -+ -+ if (usage_present != 1) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unexpected number of Key Usage extensions - expected 1, got %d", -+ usage_present); -+ } -+ if (constraints_present != 1) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unexpected number of basic constraints extensions - expected 1, got %d", -+ constraints_present); -+ } -+ return GRUB_ERR_NONE; -+ -+cleanup_value: -+ grub_free (value); -+cleanup_value_path: -+ grub_free (value_path); -+cleanup_critical_path: -+ grub_free (critical_path); -+cleanup_oid_path: -+ grub_free (oid_path); -+ return err; -+} -+ -+/* -+ * Parse a certificate whose DER-encoded form is in @data, of size @data_size. -+ * Return the results in @results, which must point to an allocated x509 certificate. -+ */ -+grub_err_t -+certificate_import (void *data, grub_size_t data_size, -+ struct x509_certificate *results) -+{ -+ int result = 0; -+ asn1_node cert; -+ grub_err_t err; -+ int size; -+ int tmp_size; -+ -+ if (data_size > GRUB_INT_MAX) -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ "Cannot parse a certificate where data size > INT_MAX"); -+ size = (int) data_size; -+ -+ result = asn1_create_element (_gnutls_pkix_asn, "PKIX1.Certificate", &cert); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for certificate: %s", -+ asn1_strerror (result)); -+ } -+ -+ result = asn1_der_decoding2 (&cert, data, &size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Could not parse DER for certificate: %s", asn1_error); -+ goto cleanup; -+ } -+ -+ /* -+ * TBSCertificate ::= SEQUENCE { -+ * version [0] EXPLICIT Version DEFAULT v1 -+ */ -+ err = check_version (cert); -+ if (err != GRUB_ERR_NONE) -+ { -+ goto cleanup; -+ } -+ -+ /* -+ * serialNumber CertificateSerialNumber, -+ * -+ * CertificateSerialNumber ::= INTEGER -+ */ -+ results->serial = -+ grub_asn1_allocate_and_read (cert, "tbsCertificate.serialNumber", -+ "certificate serial number", &tmp_size); -+ if (!results->serial) -+ { -+ err = grub_errno; -+ goto cleanup; -+ } -+ /* -+ * It's safe to cast the signed int to an unsigned here, we know -+ * length is non-negative -+ */ -+ results->serial_len = tmp_size; -+ -+ /* -+ * signature AlgorithmIdentifier, -+ * -+ * We don't load the signature or issuer at the moment, -+ * as we don't attempt x509 verification. -+ */ -+ -+ /* -+ * issuer Name, -+ * -+ * The RFC only requires the serial number to be unique within -+ * issuers, so to avoid ambiguity we _technically_ ought to make -+ * this available. -+ */ -+ -+ /* -+ * validity Validity, -+ * -+ * Validity ::= SEQUENCE { -+ * notBefore Time, -+ * notAfter Time } -+ * -+ * We can't validate this reasonably, we have no true time source on several -+ * platforms. For now we do not parse them. -+ */ -+ -+ /* -+ * subject Name, -+ * -+ * This is an X501 name, we parse out just the CN. -+ */ -+ err = -+ read_name (cert, "tbsCertificate.subject", &results->subject, -+ &results->subject_len); -+ if (err != GRUB_ERR_NONE) -+ goto cleanup_serial; -+ -+ /* -+ * TBSCertificate ::= SEQUENCE { -+ * ... -+ * subjectPublicKeyInfo SubjectPublicKeyInfo, -+ * ... -+ */ -+ err = grub_x509_read_subject_public_key (cert, results); -+ if (err != GRUB_ERR_NONE) -+ goto cleanup_name; -+ -+ /* -+ * TBSCertificate ::= SEQUENCE { -+ * ... -+ * extensions [3] EXPLICIT Extensions OPTIONAL -+ * -- If present, version MUST be v3 -+ * } -+ */ -+ -+ err = verify_extensions (cert); -+ if (err != GRUB_ERR_NONE) -+ goto cleanup_name; -+ -+ -+ /* -+ * We do not read or check the signature on the certificate: -+ * as discussed we do not try to validate the certificate but trust -+ * it implictly. -+ */ -+ -+ asn1_delete_structure (&cert); -+ return GRUB_ERR_NONE; -+ -+ -+cleanup_name: -+ grub_free (results->subject); -+cleanup_serial: -+ grub_free (results->serial); -+cleanup: -+ asn1_delete_structure (&cert); -+ return err; -+} -+ -+/* -+ * Release all the storage associated with the x509 certificate. -+ * If the caller dynamically allocated the certificate, it must free it. -+ * The caller is also responsible for maintenance of the linked list. -+ */ -+void -+certificate_release (struct x509_certificate *cert) -+{ -+ grub_free (cert->subject); -+ grub_free (cert->serial); -+ gcry_mpi_release (cert->mpis[0]); -+ gcry_mpi_release (cert->mpis[1]); -+} -diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h -new file mode 100644 -index 00000000000..9792ef3901e ---- /dev/null -+++ b/grub-core/commands/appendedsig/appendedsig.h -@@ -0,0 +1,110 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+ -+extern asn1_node _gnutls_gnutls_asn; -+extern asn1_node _gnutls_pkix_asn; -+ -+#define MAX_OID_LEN 32 -+ -+/* -+ * One or more x509 certificates. -+ * -+ * We do limited parsing: extracting only the serial, CN and RSA public key. -+ */ -+struct x509_certificate -+{ -+ struct x509_certificate *next; -+ -+ grub_uint8_t *serial; -+ grub_size_t serial_len; -+ -+ char *subject; -+ grub_size_t subject_len; -+ -+ /* We only support RSA public keys. This encodes [modulus, publicExponent] */ -+ gcry_mpi_t mpis[2]; -+}; -+ -+/* -+ * A PKCS#7 signedData message. -+ * -+ * We make no attempt to match intelligently, so we don't save any info about -+ * the signer. We also support only 1 signerInfo, so we only store a single -+ * MPI for the signature. -+ */ -+struct pkcs7_signedData -+{ -+ const gcry_md_spec_t *hash; -+ gcry_mpi_t sig_mpi; -+}; -+ -+ -+/* Do libtasn1 init */ -+int asn1_init (void); -+ -+/* -+ * Import a DER-encoded certificate at 'data', of size 'size'. -+ * -+ * Place the results into 'results', which must be already allocated. -+ */ -+grub_err_t -+certificate_import (void *data, grub_size_t size, -+ struct x509_certificate *results); -+ -+/* -+ * Release all the storage associated with the x509 certificate. -+ * If the caller dynamically allocated the certificate, it must free it. -+ * The caller is also responsible for maintenance of the linked list. -+ */ -+void certificate_release (struct x509_certificate *cert); -+ -+/* -+ * Parse a PKCS#7 message, which must be a signedData message. -+ * -+ * The message must be in 'sigbuf' and of size 'data_size'. The result is -+ * placed in 'msg', which must already be allocated. -+ */ -+grub_err_t -+parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size, -+ struct pkcs7_signedData *msg); -+ -+/* -+ * Release all the storage associated with the PKCS#7 message. -+ * If the caller dynamically allocated the message, it must free it. -+ */ -+void pkcs7_signedData_release (struct pkcs7_signedData *msg); -+ -+/* -+ * Read a value from an ASN1 node, allocating memory to store it. -+ * -+ * It will work for anything where the size libtasn1 returns is right: -+ * - Integers -+ * - Octet strings -+ * - DER encoding of other structures -+ * It will _not_ work for things where libtasn1 size requires adjustment: -+ * - Strings that require an extra NULL byte at the end -+ * - Bit strings because libtasn1 returns the length in bits, not bytes. -+ * -+ * If the function returns a non-NULL value, the caller must free it. -+ */ -+void *grub_asn1_allocate_and_read (asn1_node node, const char *name, -+ const char *friendly_name, -+ int *content_size); diff --git a/SOURCES/0194-appended-signatures-support-verifying-appended-signa.patch b/SOURCES/0194-appended-signatures-support-verifying-appended-signa.patch deleted file mode 100644 index 262efc0..0000000 --- a/SOURCES/0194-appended-signatures-support-verifying-appended-signa.patch +++ /dev/null @@ -1,716 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 30 Jul 2020 01:35:43 +1000 -Subject: [PATCH] appended signatures: support verifying appended signatures - -Building on the parsers and the ability to embed x509 certificates, as -well as the existing gcrypt functionality, add a module for verifying -appended signatures. - -This includes a verifier that requires that Linux kernels and grub modules -have appended signatures, and commands to manage the list of trusted -certificates for verification. - -Verification must be enabled by setting check_appended_signatures. If -GRUB is locked down when the module is loaded, verification will be -enabled and locked automatically. - -As with the PGP verifier, it is not a complete secure-boot solution: -other mechanisms, such as a password or lockdown, must be used to ensure -that a user cannot drop to the grub shell and disable verification. - -Signed-off-by: Daniel Axtens ---- - grub-core/Makefile.core.def | 12 + - grub-core/commands/appendedsig/appendedsig.c | 645 +++++++++++++++++++++++++++ - include/grub/file.h | 2 + - 3 files changed, 659 insertions(+) - create mode 100644 grub-core/commands/appendedsig/appendedsig.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index b4aaccf7b57..77321d218c8 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -980,6 +980,18 @@ module = { - cppflags = '-I$(srcdir)/lib/posix_wrap'; - }; - -+module = { -+ name = appendedsig; -+ common = commands/appendedsig/appendedsig.c; -+ common = commands/appendedsig/x509.c; -+ common = commands/appendedsig/pkcs7.c; -+ common = commands/appendedsig/asn1util.c; -+ common = commands/appendedsig/gnutls_asn1_tab.c; -+ common = commands/appendedsig/pkix_asn1_tab.c; -+ cflags = '$(CFLAGS_POSIX)'; -+ cppflags = '-I$(srcdir)/lib/posix_wrap'; -+}; -+ - module = { - name = hdparm; - common = commands/hdparm.c; -diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c -new file mode 100644 -index 00000000000..dc294cd339e ---- /dev/null -+++ b/grub-core/commands/appendedsig/appendedsig.c -@@ -0,0 +1,645 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020-2021 IBM Corporation. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "appendedsig.h" -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+const char magic[] = "~Module signature appended~\n"; -+ -+/* -+ * This structure is extracted from scripts/sign-file.c in the linux kernel -+ * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible. -+ */ -+struct module_signature -+{ -+ grub_uint8_t algo; /* Public-key crypto algorithm [0] */ -+ grub_uint8_t hash; /* Digest algorithm [0] */ -+ grub_uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */ -+ grub_uint8_t signer_len; /* Length of signer's name [0] */ -+ grub_uint8_t key_id_len; /* Length of key identifier [0] */ -+ grub_uint8_t __pad[3]; -+ grub_uint32_t sig_len; /* Length of signature data */ -+} GRUB_PACKED; -+ -+ -+/* This represents an entire, parsed, appended signature */ -+struct grub_appended_signature -+{ -+ grub_size_t signature_len; /* Length of PKCS#7 data + -+ * metadata + magic */ -+ -+ struct module_signature sig_metadata; /* Module signature metadata */ -+ struct pkcs7_signedData pkcs7; /* Parsed PKCS#7 data */ -+}; -+ -+/* Trusted certificates for verifying appended signatures */ -+struct x509_certificate *grub_trusted_key; -+ -+/* -+ * Force gcry_rsa to be a module dependency. -+ * -+ * If we use grub_crypto_pk_rsa, then then the gcry_rsa module won't be built -+ * in if you add 'appendedsig' to grub-install --modules. You would need to -+ * add 'gcry_rsa' too. That's confusing and seems suboptimal, especially when -+ * we only support RSA. -+ * -+ * Dynamic loading also causes some concerns. We can't load gcry_rsa from the -+ * the filesystem after we install the verifier - we won't be able to verify -+ * it without having it already present. We also shouldn't load it before we -+ * install the verifier, because that would mean it wouldn't be verified - an -+ * attacker could insert any code they wanted into the module. -+ * -+ * So instead, reference the internal symbol from gcry_rsa. That creates a -+ * direct dependency on gcry_rsa, so it will be built in when this module -+ * is built in. Being built in (assuming the core image is itself signed!) -+ * also resolves our concerns about loading from the filesystem. -+ */ -+extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; -+ -+static int check_sigs = 0; -+ -+static const char * -+grub_env_read_sec (struct grub_env_var *var __attribute__ ((unused)), -+ const char *val __attribute__ ((unused))) -+{ -+ if (check_sigs == 2) -+ return "forced"; -+ else if (check_sigs == 1) -+ return "enforce"; -+ else -+ return "no"; -+} -+ -+static char * -+grub_env_write_sec (struct grub_env_var *var __attribute__((unused)), -+ const char *val) -+{ -+ /* Do not allow the value to be changed if set to forced */ -+ if (check_sigs == 2) -+ return grub_strdup ("forced"); -+ -+ if ((*val == '2') || (*val == 'f')) -+ check_sigs = 2; -+ else if ((*val == '1') || (*val == 'e')) -+ check_sigs = 1; -+ else if ((*val == '0') || (*val == 'n')) -+ check_sigs = 0; -+ -+ return grub_strdup (grub_env_read_sec (NULL, NULL)); -+} -+ -+static grub_err_t -+read_cert_from_file (grub_file_t f, struct x509_certificate *certificate) -+{ -+ grub_err_t err; -+ grub_uint8_t *buf = NULL; -+ grub_ssize_t read_size; -+ grub_off_t total_read_size = 0; -+ grub_off_t file_size = grub_file_size (f); -+ -+ -+ if (file_size == GRUB_FILE_SIZE_UNKNOWN) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("Cannot parse a certificate file of unknown size")); -+ -+ buf = grub_zalloc (file_size); -+ if (!buf) -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ N_("Could not allocate buffer for certificate file contents")); -+ -+ while (total_read_size < file_size) -+ { -+ read_size = -+ grub_file_read (f, &buf[total_read_size], -+ file_size - total_read_size); -+ if (read_size < 0) -+ { -+ err = grub_error (GRUB_ERR_READ_ERROR, -+ N_("Error reading certificate file")); -+ goto cleanup_buf; -+ } -+ total_read_size += read_size; -+ } -+ -+ err = certificate_import (buf, total_read_size, certificate); -+ if (err != GRUB_ERR_NONE) -+ goto cleanup_buf; -+ -+ return GRUB_ERR_NONE; -+ -+cleanup_buf: -+ grub_free (buf); -+ return err; -+} -+ -+static grub_err_t -+extract_appended_signature (grub_uint8_t * buf, grub_size_t bufsize, -+ struct grub_appended_signature *sig) -+{ -+ grub_err_t err; -+ grub_size_t pkcs7_size; -+ grub_size_t remaining_len; -+ grub_uint8_t *appsigdata = buf + bufsize - grub_strlen (magic); -+ -+ if (bufsize < grub_strlen (magic)) -+ return grub_error (GRUB_ERR_BAD_SIGNATURE, -+ N_("File too short for signature magic")); -+ -+ if (grub_memcmp (appsigdata, (grub_uint8_t *) magic, grub_strlen (magic))) -+ return grub_error (GRUB_ERR_BAD_SIGNATURE, -+ N_("Missing or invalid signature magic")); -+ -+ remaining_len = bufsize - grub_strlen (magic); -+ -+ if (remaining_len < sizeof (struct module_signature)) -+ return grub_error (GRUB_ERR_BAD_SIGNATURE, -+ N_("File too short for signature metadata")); -+ -+ appsigdata -= sizeof (struct module_signature); -+ -+ /* extract the metadata */ -+ grub_memcpy (&(sig->sig_metadata), appsigdata, -+ sizeof (struct module_signature)); -+ -+ remaining_len -= sizeof (struct module_signature); -+ -+ if (sig->sig_metadata.id_type != 2) -+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("Wrong signature type")); -+ -+#ifdef GRUB_TARGET_WORDS_BIGENDIAN -+ pkcs7_size = sig->sig_metadata.sig_len; -+#else -+ pkcs7_size = __builtin_bswap32 (sig->sig_metadata.sig_len); -+#endif -+ -+ if (pkcs7_size > remaining_len) -+ return grub_error (GRUB_ERR_BAD_SIGNATURE, -+ N_("File too short for PKCS#7 message")); -+ -+ grub_dprintf ("appendedsig", "sig len %" PRIuGRUB_SIZE "\n", pkcs7_size); -+ -+ sig->signature_len = -+ grub_strlen (magic) + sizeof (struct module_signature) + pkcs7_size; -+ -+ /* rewind pointer and parse pkcs7 data */ -+ appsigdata -= pkcs7_size; -+ -+ err = parse_pkcs7_signedData (appsigdata, pkcs7_size, &sig->pkcs7); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_verify_appended_signature (grub_uint8_t * buf, grub_size_t bufsize) -+{ -+ grub_err_t err = GRUB_ERR_NONE; -+ grub_size_t datasize; -+ void *context; -+ unsigned char *hash; -+ gcry_mpi_t hashmpi; -+ gcry_err_code_t rc; -+ struct x509_certificate *pk; -+ struct grub_appended_signature sig; -+ -+ if (!grub_trusted_key) -+ return grub_error (GRUB_ERR_BAD_SIGNATURE, -+ N_("No trusted keys to verify against")); -+ -+ err = extract_appended_signature (buf, bufsize, &sig); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ -+ datasize = bufsize - sig.signature_len; -+ -+ context = grub_zalloc (sig.pkcs7.hash->contextsize); -+ if (!context) -+ return grub_errno; -+ -+ sig.pkcs7.hash->init (context); -+ sig.pkcs7.hash->write (context, buf, datasize); -+ sig.pkcs7.hash->final (context); -+ hash = sig.pkcs7.hash->read (context); -+ grub_dprintf ("appendedsig", -+ "data size %" PRIxGRUB_SIZE ", hash %02x%02x%02x%02x...\n", -+ datasize, hash[0], hash[1], hash[2], hash[3]); -+ -+ err = GRUB_ERR_BAD_SIGNATURE; -+ for (pk = grub_trusted_key; pk; pk = pk->next) -+ { -+ rc = grub_crypto_rsa_pad (&hashmpi, hash, sig.pkcs7.hash, pk->mpis[0]); -+ if (rc) -+ { -+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, -+ N_("Error padding hash for RSA verification: %d"), -+ rc); -+ goto cleanup; -+ } -+ -+ rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &sig.pkcs7.sig_mpi, -+ pk->mpis, NULL, NULL); -+ gcry_mpi_release (hashmpi); -+ -+ if (rc == 0) -+ { -+ grub_dprintf ("appendedsig", "verify with key '%s' succeeded\n", -+ pk->subject); -+ err = GRUB_ERR_NONE; -+ break; -+ } -+ -+ grub_dprintf ("appendedsig", "verify with key '%s' failed with %d\n", -+ pk->subject, rc); -+ } -+ -+ /* If we didn't verify, provide a neat message */ -+ if (err != GRUB_ERR_NONE) -+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, -+ N_("Failed to verify signature against a trusted key")); -+ -+cleanup: -+ grub_free (context); -+ pkcs7_signedData_release (&sig.pkcs7); -+ -+ return err; -+} -+ -+static grub_err_t -+grub_cmd_verify_signature (grub_command_t cmd __attribute__((unused)), -+ int argc, char **args) -+{ -+ grub_file_t f; -+ grub_err_t err = GRUB_ERR_NONE; -+ grub_uint8_t *data; -+ grub_ssize_t read_size; -+ grub_off_t file_size, total_read_size = 0; -+ -+ if (argc < 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); -+ -+ grub_dprintf ("appendedsig", "verifying %s\n", args[0]); -+ -+ f = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE); -+ if (!f) -+ { -+ err = grub_errno; -+ goto cleanup; -+ } -+ -+ file_size = grub_file_size (f); -+ if (file_size == GRUB_FILE_SIZE_UNKNOWN) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("Cannot verify the signature of a file of unknown size")); -+ -+ data = grub_malloc (file_size); -+ if (!data) -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ N_("Could not allocate data buffer size " -+ PRIuGRUB_UINT64_T " for verification"), file_size); -+ -+ while (total_read_size < file_size) -+ { -+ read_size = -+ grub_file_read (f, &data[total_read_size], -+ file_size - total_read_size); -+ if (read_size < 0) -+ { -+ err = grub_error (GRUB_ERR_READ_ERROR, -+ N_("Error reading file to verify")); -+ goto cleanup_data; -+ } -+ total_read_size += read_size; -+ } -+ -+ err = grub_verify_appended_signature (data, file_size); -+ -+cleanup_data: -+ grub_free (data); -+cleanup: -+ if (f) -+ grub_file_close (f); -+ return err; -+} -+ -+static grub_err_t -+grub_cmd_distrust (grub_command_t cmd __attribute__((unused)), -+ int argc, char **args) -+{ -+ unsigned long cert_num, i; -+ struct x509_certificate *cert, *prev; -+ -+ if (argc != 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("One argument expected")); -+ -+ grub_errno = GRUB_ERR_NONE; -+ cert_num = grub_strtoul (args[0], NULL, 10); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ -+ if (cert_num < 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("Certificate number too small - numbers start at 1")); -+ -+ if (cert_num == 1) -+ { -+ cert = grub_trusted_key; -+ grub_trusted_key = cert->next; -+ -+ certificate_release (cert); -+ grub_free (cert); -+ return GRUB_ERR_NONE; -+ } -+ i = 2; -+ prev = grub_trusted_key; -+ cert = grub_trusted_key->next; -+ while (cert) -+ { -+ if (i == cert_num) -+ { -+ prev->next = cert->next; -+ certificate_release (cert); -+ grub_free (cert); -+ return GRUB_ERR_NONE; -+ } -+ i++; -+ prev = cert; -+ cert = cert->next; -+ } -+ -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("No certificate number %d found - only %d certificates in the store"), -+ cert_num, i - 1); -+} -+ -+static grub_err_t -+grub_cmd_trust (grub_command_t cmd __attribute__((unused)), -+ int argc, char **args) -+{ -+ grub_file_t certf; -+ struct x509_certificate *cert = NULL; -+ grub_err_t err; -+ -+ if (argc != 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); -+ -+ certf = grub_file_open (args[0], -+ GRUB_FILE_TYPE_CERTIFICATE_TRUST -+ | GRUB_FILE_TYPE_NO_DECOMPRESS); -+ if (!certf) -+ return grub_errno; -+ -+ -+ cert = grub_zalloc (sizeof (struct x509_certificate)); -+ if (!cert) -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ N_("Could not allocate memory for certificate")); -+ -+ err = read_cert_from_file (certf, cert); -+ grub_file_close (certf); -+ if (err != GRUB_ERR_NONE) -+ { -+ grub_free (cert); -+ return err; -+ } -+ grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n", -+ cert->subject); -+ -+ cert->next = grub_trusted_key; -+ grub_trusted_key = cert; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_cmd_list (grub_command_t cmd __attribute__((unused)), -+ int argc __attribute__((unused)), -+ char **args __attribute__((unused))) -+{ -+ struct x509_certificate *cert; -+ int cert_num = 1; -+ grub_size_t i; -+ -+ for (cert = grub_trusted_key; cert; cert = cert->next) -+ { -+ grub_printf (N_("Certificate %d:\n"), cert_num); -+ -+ grub_printf (N_("\tSerial: ")); -+ for (i = 0; i < cert->serial_len - 1; i++) -+ { -+ grub_printf ("%02x:", cert->serial[i]); -+ } -+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]); -+ -+ grub_printf ("\tCN: %s\n\n", cert->subject); -+ cert_num++; -+ -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+appendedsig_init (grub_file_t io __attribute__((unused)), -+ enum grub_file_type type, -+ void **context __attribute__((unused)), -+ enum grub_verify_flags *flags) -+{ -+ if (!check_sigs) -+ { -+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; -+ return GRUB_ERR_NONE; -+ } -+ -+ switch (type & GRUB_FILE_TYPE_MASK) -+ { -+ case GRUB_FILE_TYPE_CERTIFICATE_TRUST: -+ /* -+ * This is a certificate to add to trusted keychain. -+ * -+ * This needs to be verified or blocked. Ideally we'd write an x509 -+ * verifier, but we lack the hubris required to take this on. Instead, -+ * require that it have an appended signature. -+ */ -+ -+ /* Fall through */ -+ -+ case GRUB_FILE_TYPE_LINUX_KERNEL: -+ case GRUB_FILE_TYPE_GRUB_MODULE: -+ /* -+ * Appended signatures are only defined for ELF binaries. -+ * Out of an abundance of caution, we only verify Linux kernels and -+ * GRUB modules at this point. -+ */ -+ *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; -+ return GRUB_ERR_NONE; -+ -+ case GRUB_FILE_TYPE_ACPI_TABLE: -+ case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: -+ /* -+ * It is possible to use appended signature verification without -+ * lockdown - like the PGP verifier. When combined with an embedded -+ * config file in a signed grub binary, this could still be a meaningful -+ * secure-boot chain - so long as it isn't subverted by something like a -+ * rouge ACPI table or DT image. Defer them explicitly. -+ */ -+ *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; -+ return GRUB_ERR_NONE; -+ -+ default: -+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; -+ return GRUB_ERR_NONE; -+ } -+} -+ -+static grub_err_t -+appendedsig_write (void *ctxt __attribute__((unused)), -+ void *buf, grub_size_t size) -+{ -+ return grub_verify_appended_signature (buf, size); -+} -+ -+struct grub_file_verifier grub_appendedsig_verifier = { -+ .name = "appendedsig", -+ .init = appendedsig_init, -+ .write = appendedsig_write, -+}; -+ -+static grub_ssize_t -+pseudo_read (struct grub_file *file, char *buf, grub_size_t len) -+{ -+ grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len); -+ return len; -+} -+ -+/* Filesystem descriptor. */ -+static struct grub_fs pseudo_fs = { -+ .name = "pseudo", -+ .fs_read = pseudo_read -+}; -+ -+static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust; -+ -+GRUB_MOD_INIT (appendedsig) -+{ -+ int rc; -+ struct grub_module_header *header; -+ -+ /* If in lockdown, immediately enter forced mode */ -+ if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) -+ check_sigs = 2; -+ -+ grub_trusted_key = NULL; -+ -+ grub_register_variable_hook ("check_appended_signatures", -+ grub_env_read_sec, -+ grub_env_write_sec); -+ grub_env_export ("check_appended_signatures"); -+ -+ rc = asn1_init (); -+ if (rc) -+ grub_fatal ("Error initing ASN.1 data structures: %d: %s\n", rc, -+ asn1_strerror (rc)); -+ -+ FOR_MODULES (header) -+ { -+ struct grub_file pseudo_file; -+ struct x509_certificate *pk = NULL; -+ grub_err_t err; -+ -+ /* Not an ELF module, skip. */ -+ if (header->type != OBJ_TYPE_X509_PUBKEY) -+ continue; -+ -+ grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); -+ pseudo_file.fs = &pseudo_fs; -+ pseudo_file.size = header->size - sizeof (struct grub_module_header); -+ pseudo_file.data = (char *) header + sizeof (struct grub_module_header); -+ -+ grub_dprintf ("appendedsig", -+ "Found an x509 key, size=%" PRIuGRUB_UINT64_T "\n", -+ pseudo_file.size); -+ -+ pk = grub_zalloc (sizeof (struct x509_certificate)); -+ if (!pk) -+ { -+ grub_fatal ("Out of memory loading initial certificates"); -+ } -+ -+ err = read_cert_from_file (&pseudo_file, pk); -+ if (err != GRUB_ERR_NONE) -+ grub_fatal ("Error loading initial key: %s", grub_errmsg); -+ -+ grub_dprintf ("appendedsig", "loaded certificate CN='%s'\n", pk->subject); -+ -+ pk->next = grub_trusted_key; -+ grub_trusted_key = pk; -+ } -+ -+ cmd_trust = -+ grub_register_command ("trust_certificate", grub_cmd_trust, -+ N_("X509_CERTIFICATE"), -+ N_("Add X509_CERTIFICATE to trusted certificates.")); -+ cmd_list = -+ grub_register_command ("list_certificates", grub_cmd_list, 0, -+ N_("Show the list of trusted x509 certificates.")); -+ cmd_verify = -+ grub_register_command ("verify_appended", grub_cmd_verify_signature, -+ N_("FILE"), -+ N_("Verify FILE against the trusted x509 certificates.")); -+ cmd_distrust = -+ grub_register_command ("distrust_certificate", grub_cmd_distrust, -+ N_("CERT_NUMBER"), -+ N_("Remove CERT_NUMBER (as listed by list_certificates) from trusted certificates.")); -+ -+ grub_verifier_register (&grub_appendedsig_verifier); -+ grub_dl_set_persistent (mod); -+} -+ -+GRUB_MOD_FINI (appendedsig) -+{ -+ /* -+ * grub_dl_set_persistent should prevent this from actually running, but -+ * it does still run under emu. -+ */ -+ -+ grub_verifier_unregister (&grub_appendedsig_verifier); -+ grub_unregister_command (cmd_verify); -+ grub_unregister_command (cmd_list); -+ grub_unregister_command (cmd_trust); -+ grub_unregister_command (cmd_distrust); -+} -diff --git a/include/grub/file.h b/include/grub/file.h -index 31567483ccf..96827a4f896 100644 ---- a/include/grub/file.h -+++ b/include/grub/file.h -@@ -80,6 +80,8 @@ enum grub_file_type - GRUB_FILE_TYPE_PUBLIC_KEY, - /* File holding public key to add to trused keys. */ - GRUB_FILE_TYPE_PUBLIC_KEY_TRUST, -+ /* File holding x509 certificiate to add to trusted keys. */ -+ GRUB_FILE_TYPE_CERTIFICATE_TRUST, - /* File of which we intend to print a blocklist to the user. */ - GRUB_FILE_TYPE_PRINT_BLOCKLIST, - /* File we intend to use for test loading or testing speed. */ diff --git a/SOURCES/0194-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch b/SOURCES/0194-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch new file mode 100644 index 0000000..200cd51 --- /dev/null +++ b/SOURCES/0194-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 11:30:32 +0100 +Subject: [PATCH] normal/menu: Don't show "Booting `%s'" msg when auto-booting + with TIMEOUT_STYLE_HIDDEN + +When the user has asked the menu code to be hidden/quiet and the current +entry is being autobooted because the timeout has expired don't show +the "Booting `%s'" msg. + +This is necessary to let flicker-free boots really be flicker free, +otherwise the "Booting `%s'" msg will kick the EFI fb into text mode +and show the msg, breaking the flicker-free experience. + +Signed-off-by: Hans de Goede +--- + grub-core/normal/menu.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index ec0c92bade..c8516a5a08 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -606,13 +606,15 @@ print_countdown (struct grub_term_coordinate *pos, int n) + entry to be executed is a result of an automatic default selection because + of the timeout. */ + static int +-run_menu (grub_menu_t menu, int nested, int *auto_boot) ++run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot) + { + grub_uint64_t saved_time; + int default_entry, current_entry; + int timeout; + enum timeout_style timeout_style; + ++ *notify_boot = 1; ++ + default_entry = get_entry_number (menu, "default"); + + /* If DEFAULT_ENTRY is not within the menu entries, fall back to +@@ -687,6 +689,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) + if (timeout == 0) + { + *auto_boot = 1; ++ *notify_boot = timeout_style != TIMEOUT_STYLE_HIDDEN; + return default_entry; + } + +@@ -840,12 +843,16 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) + + /* Callback invoked immediately before a menu entry is executed. */ + static void +-notify_booting (grub_menu_entry_t entry, +- void *userdata __attribute__((unused))) ++notify_booting (grub_menu_entry_t entry, void *userdata) + { +- grub_printf (" "); +- grub_printf_ (N_("Booting `%s'"), entry->title); +- grub_printf ("\n\n"); ++ int *notify_boot = userdata; ++ ++ if (*notify_boot) ++ { ++ grub_printf (" "); ++ grub_printf_ (N_("Booting `%s'"), entry->title); ++ grub_printf ("\n\n"); ++ } + } + + /* Callback invoked when a default menu entry executed because of a timeout +@@ -893,8 +900,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted) + int boot_entry; + grub_menu_entry_t e; + int auto_boot; ++ int notify_boot; + +- boot_entry = run_menu (menu, nested, &auto_boot); ++ boot_entry = run_menu (menu, nested, &auto_boot, ¬ify_boot); + if (boot_entry < 0) + break; + +@@ -906,7 +914,7 @@ show_menu (grub_menu_t menu, int nested, int autobooted) + + if (auto_boot) + grub_menu_execute_with_fallback (menu, e, autobooted, +- &execution_callback, 0); ++ &execution_callback, ¬ify_boot); + else + grub_menu_execute_entry (e, 0); + if (autobooted) diff --git a/SOURCES/0195-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch b/SOURCES/0195-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch new file mode 100644 index 0000000..0f99c22 --- /dev/null +++ b/SOURCES/0195-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 11:30:33 +0100 +Subject: [PATCH] EFI: suppress the "Welcome to GRUB!" message in EFI builds + +Grub EFI builds are now often used in combination with flicker-free +boot, but this breaks with upstream grub because the "Welcome to GRUB!" +message will kick the EFI fb into text mode and show the msg, +breaking the flicker-free experience. + +EFI systems are so fast, that when the menu or the countdown are enabled +the message will be immediately overwritten, so in these cases not +printing the message does not matter. + +And in case when the timeout_style is set to TIMEOUT_STYLE_HIDDEN, +the user has asked grub to be quiet (for example to allow flickfree +boot) annd thus the message should not be printed. + +Signed-off-by: Hans de Goede +--- + grub-core/kern/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 3fc3401472..993b8a8598 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -317,10 +317,13 @@ grub_main (void) + + grub_boot_time ("After machine init."); + ++ /* This breaks flicker-free boot on EFI systems, so disable it there. */ ++#ifndef GRUB_MACHINE_EFI + /* Hello. */ + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + grub_printf ("Welcome to GRUB!\n\n"); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); ++#endif + + /* Init verifiers API. */ + grub_verifiers_init (); diff --git a/SOURCES/0195-appended-signatures-verification-tests.patch b/SOURCES/0195-appended-signatures-verification-tests.patch deleted file mode 100644 index 9f6c3c6..0000000 --- a/SOURCES/0195-appended-signatures-verification-tests.patch +++ /dev/null @@ -1,897 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 30 Jul 2020 01:31:02 +1000 -Subject: [PATCH] appended signatures: verification tests - -These tests are run through all_functional_test and test a range -of commands and behaviours. - -Signed-off-by: Daniel Axtens ---- - grub-core/Makefile.core.def | 6 + - grub-core/tests/appended_signature_test.c | 281 +++++++++++++++ - grub-core/tests/lib/functional_test.c | 1 + - grub-core/tests/appended_signatures.h | 557 ++++++++++++++++++++++++++++++ - 4 files changed, 845 insertions(+) - create mode 100644 grub-core/tests/appended_signature_test.c - create mode 100644 grub-core/tests/appended_signatures.h - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 77321d218c8..6bddc841b85 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2161,6 +2161,12 @@ module = { - common = tests/setjmp_test.c; - }; - -+module = { -+ name = appended_signature_test; -+ common = tests/appended_signature_test.c; -+ common = tests/appended_signatures.h; -+}; -+ - module = { - name = signature_test; - common = tests/signature_test.c; -diff --git a/grub-core/tests/appended_signature_test.c b/grub-core/tests/appended_signature_test.c -new file mode 100644 -index 00000000000..88a485200d8 ---- /dev/null -+++ b/grub-core/tests/appended_signature_test.c -@@ -0,0 +1,281 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 IBM Corporation. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "appended_signatures.h" -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+#define DEFINE_TEST_CASE(case_name) \ -+static char * \ -+get_ ## case_name (grub_size_t *sz) \ -+{ \ -+ char *ret; \ -+ *sz = case_name ## _len; \ -+ ret = grub_malloc (*sz); \ -+ if (ret) \ -+ grub_memcpy (ret, case_name, *sz); \ -+ return ret; \ -+} \ -+\ -+static struct grub_procfs_entry case_name ## _entry = \ -+{ \ -+ .name = #case_name, \ -+ .get_contents = get_ ## case_name \ -+} -+ -+#define DO_TEST(case_name, is_valid) \ -+{ \ -+ grub_procfs_register (#case_name, &case_name ## _entry); \ -+ do_verify ("(proc)/" #case_name, is_valid); \ -+ grub_procfs_unregister (&case_name ## _entry); \ -+} -+ -+ -+DEFINE_TEST_CASE (hi_signed); -+DEFINE_TEST_CASE (hi_signed_sha256); -+DEFINE_TEST_CASE (hj_signed); -+DEFINE_TEST_CASE (short_msg); -+DEFINE_TEST_CASE (unsigned_msg); -+DEFINE_TEST_CASE (hi_signed_2nd); -+ -+static char * -+get_certificate_der (grub_size_t * sz) -+{ -+ char *ret; -+ *sz = certificate_der_len; -+ ret = grub_malloc (*sz); -+ if (ret) -+ grub_memcpy (ret, certificate_der, *sz); -+ return ret; -+} -+ -+static struct grub_procfs_entry certificate_der_entry = { -+ .name = "certificate.der", -+ .get_contents = get_certificate_der -+}; -+ -+static char * -+get_certificate2_der (grub_size_t * sz) -+{ -+ char *ret; -+ *sz = certificate2_der_len; -+ ret = grub_malloc (*sz); -+ if (ret) -+ grub_memcpy (ret, certificate2_der, *sz); -+ return ret; -+} -+ -+static struct grub_procfs_entry certificate2_der_entry = { -+ .name = "certificate2.der", -+ .get_contents = get_certificate2_der -+}; -+ -+static char * -+get_certificate_printable_der (grub_size_t * sz) -+{ -+ char *ret; -+ *sz = certificate_printable_der_len; -+ ret = grub_malloc (*sz); -+ if (ret) -+ grub_memcpy (ret, certificate_printable_der, *sz); -+ return ret; -+} -+ -+static struct grub_procfs_entry certificate_printable_der_entry = { -+ .name = "certificate_printable.der", -+ .get_contents = get_certificate_printable_der -+}; -+ -+ -+static void -+do_verify (const char *f, int is_valid) -+{ -+ grub_command_t cmd; -+ char *args[] = { (char *) f, NULL }; -+ grub_err_t err; -+ -+ cmd = grub_command_find ("verify_appended"); -+ if (!cmd) -+ { -+ grub_test_assert (0, "can't find command `%s'", "verify_appended"); -+ return; -+ } -+ err = (cmd->func) (cmd, 1, args); -+ if (is_valid) -+ { -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "verification of %s failed: %d: %s", f, grub_errno, -+ grub_errmsg); -+ } -+ else -+ { -+ grub_test_assert (err == GRUB_ERR_BAD_SIGNATURE, -+ "verification of %s unexpectedly succeeded", f); -+ } -+ grub_errno = GRUB_ERR_NONE; -+ -+} -+ -+static void -+appended_signature_test (void) -+{ -+ grub_command_t cmd_trust, cmd_distrust; -+ char *trust_args[] = { (char *) "(proc)/certificate.der", NULL }; -+ char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL }; -+ char *trust_args_printable[] = { (char *) "(proc)/certificate_printable.der", -+ NULL }; -+ char *distrust_args[] = { (char *) "1", NULL }; -+ char *distrust2_args[] = { (char *) "2", NULL }; -+ grub_err_t err; -+ -+ grub_procfs_register ("certificate.der", &certificate_der_entry); -+ grub_procfs_register ("certificate2.der", &certificate2_der_entry); -+ grub_procfs_register ("certificate_printable.der", -+ &certificate_printable_der_entry); -+ -+ cmd_trust = grub_command_find ("trust_certificate"); -+ if (!cmd_trust) -+ { -+ grub_test_assert (0, "can't find command `%s'", "trust_certificate"); -+ return; -+ } -+ err = (cmd_trust->func) (cmd_trust, 1, trust_args); -+ -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "loading certificate failed: %d: %s", grub_errno, -+ grub_errmsg); -+ -+ /* If we have no certificate the remainder of the tests are meaningless */ -+ if (err != GRUB_ERR_NONE) -+ return; -+ -+ /* -+ * Reload the command: this works around some 'interesting' behaviour in the -+ * dynamic command dispatcher. The first time you call cmd->func you get a -+ * dispatcher that loads the module, finds the real cmd, calls it, and then -+ * releases some internal storage. This means it's not safe to call a second -+ * time and we need to reload it. -+ */ -+ cmd_trust = grub_command_find ("trust_certificate"); -+ -+ DO_TEST (hi_signed, 1); -+ DO_TEST (hi_signed_sha256, 1); -+ DO_TEST (hj_signed, 0); -+ DO_TEST (short_msg, 0); -+ DO_TEST (unsigned_msg, 0); -+ -+ /* -+ * in enforcing mode, we shouldn't be able to load a certificate that isn't -+ * signed by an existing trusted key. -+ * -+ * However, procfs files automatically skip the verification test, so we can't -+ * easily test this. -+ */ -+ -+ /* -+ * verify that testing with 2 trusted certs works -+ */ -+ DO_TEST (hi_signed_2nd, 0); -+ -+ err = (cmd_trust->func) (cmd_trust, 1, trust_args2); -+ -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "loading certificate 2 failed: %d: %s", grub_errno, -+ grub_errmsg); -+ -+ if (err != GRUB_ERR_NONE) -+ return; -+ -+ DO_TEST (hi_signed_2nd, 1); -+ DO_TEST (hi_signed, 1); -+ -+ /* -+ * Check certificate removal. They're added to the _top_ of the list and -+ * removed by position in the list. Current the list looks like [#2, #1]. -+ * -+ * First test removing the second certificate in the list, which is -+ * certificate #1, giving us just [#2]. -+ */ -+ cmd_distrust = grub_command_find ("distrust_certificate"); -+ if (!cmd_distrust) -+ { -+ grub_test_assert (0, "can't find command `%s'", "distrust_certificate"); -+ return; -+ } -+ -+ err = (cmd_distrust->func) (cmd_distrust, 1, distrust2_args); -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "distrusting certificate 1 failed: %d: %s", grub_errno, -+ grub_errmsg); -+ DO_TEST (hi_signed_2nd, 1); -+ DO_TEST (hi_signed, 0); -+ -+ /* -+ * Now reload certificate #1. This will make the list look like [#1, #2] -+ */ -+ err = (cmd_trust->func) (cmd_trust, 1, trust_args); -+ -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "reloading certificate 1 failed: %d: %s", grub_errno, -+ grub_errmsg); -+ DO_TEST (hi_signed, 1); -+ -+ /* Remove the first certificate in the list, giving us just [#2] */ -+ err = (cmd_distrust->func) (cmd_distrust, 1, distrust_args); -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "distrusting certificate 1 (first time) failed: %d: %s", -+ grub_errno, grub_errmsg); -+ DO_TEST (hi_signed_2nd, 1); -+ DO_TEST (hi_signed, 0); -+ -+ /* -+ * Remove the first certificate again, giving an empty list. -+ * -+ * verify_appended should fail if there are no certificates to verify against. -+ */ -+ err = (cmd_distrust->func) (cmd_distrust, 1, distrust_args); -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "distrusting certificate 1 (second time) failed: %d: %s", -+ grub_errno, grub_errmsg); -+ DO_TEST (hi_signed_2nd, 0); -+ -+ /* -+ * Lastly, check a certificate that uses printableString rather than -+ * utf8String loads properly. -+ */ -+ err = (cmd_trust->func) (cmd_trust, 1, trust_args_printable); -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "distrusting printable certificate failed: %d: %s", -+ grub_errno, grub_errmsg); -+ -+ grub_procfs_unregister (&certificate_der_entry); -+ grub_procfs_unregister (&certificate2_der_entry); -+ grub_procfs_unregister (&certificate_printable_der_entry); -+} -+ -+GRUB_FUNCTIONAL_TEST (appended_signature_test, appended_signature_test); -diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c -index 96781fb39b5..403fa5c789a 100644 ---- a/grub-core/tests/lib/functional_test.c -+++ b/grub-core/tests/lib/functional_test.c -@@ -73,6 +73,7 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)), - grub_dl_load ("xnu_uuid_test"); - grub_dl_load ("pbkdf2_test"); - grub_dl_load ("signature_test"); -+ grub_dl_load ("appended_signature_test"); - grub_dl_load ("sleep_test"); - grub_dl_load ("bswap_test"); - grub_dl_load ("ctz_test"); -diff --git a/grub-core/tests/appended_signatures.h b/grub-core/tests/appended_signatures.h -new file mode 100644 -index 00000000000..aa3dc6278e3 ---- /dev/null -+++ b/grub-core/tests/appended_signatures.h -@@ -0,0 +1,557 @@ -+unsigned char certificate_der[] = { -+ 0x30, 0x82, 0x03, 0x88, 0x30, 0x82, 0x02, 0x70, 0xa0, 0x03, 0x02, 0x01, -+ 0x02, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, -+ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, -+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, -+ 0x05, 0x00, 0x30, 0x49, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, -+ 0x03, 0x0c, 0x1f, 0x47, 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, -+ 0x6e, 0x64, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, -+ 0x72, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, -+ 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, -+ 0x01, 0x16, 0x0e, 0x64, 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, -+ 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x30, 0x30, -+ 0x37, 0x30, 0x39, 0x30, 0x36, 0x32, 0x32, 0x30, 0x37, 0x5a, 0x18, 0x0f, -+ 0x32, 0x31, 0x32, 0x30, 0x30, 0x36, 0x31, 0x35, 0x30, 0x36, 0x32, 0x32, -+ 0x30, 0x37, 0x5a, 0x30, 0x52, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, -+ 0x04, 0x03, 0x0c, 0x28, 0x47, 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, -+ 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, -+ 0x75, 0x72, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, -+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x65, 0x79, 0x31, 0x1d, 0x30, 0x1b, -+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, -+ 0x0e, 0x64, 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, -+ 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, -+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, -+ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, -+ 0xcd, 0xe8, 0x1c, 0x08, 0x68, 0x2e, 0xcb, 0xfe, 0x8c, 0x4b, 0x3b, 0x61, -+ 0xe7, 0x8e, 0x80, 0x58, 0x85, 0x85, 0xea, 0xc8, 0x3b, 0x42, 0xba, 0x72, -+ 0x84, 0x65, 0x20, 0xbc, 0x48, 0xa2, 0x25, 0x49, 0x6e, 0x1c, 0xb9, 0x7d, -+ 0xeb, 0xc1, 0x0c, 0xa8, 0xb7, 0xcc, 0x13, 0x78, 0xba, 0x11, 0xa4, 0x98, -+ 0xd7, 0xd0, 0x7c, 0xdd, 0xf5, 0x5a, 0xb7, 0xcd, 0x31, 0x0e, 0xcd, 0x9e, -+ 0xa7, 0x19, 0xf0, 0xbd, 0x0f, 0xa6, 0xfe, 0x8a, 0x11, 0x97, 0xed, 0x8b, -+ 0xe5, 0x16, 0xa6, 0x21, 0x13, 0x36, 0xad, 0x05, 0x49, 0xec, 0x29, 0x12, -+ 0x38, 0xa7, 0x4b, 0x0f, 0xa1, 0xfb, 0x72, 0xc0, 0xc0, 0x09, 0x67, 0x78, -+ 0xa8, 0xb6, 0xd6, 0x1a, 0x39, 0xc0, 0xa8, 0xbf, 0x5f, 0x14, 0x89, 0x5c, -+ 0xbc, 0x41, 0x0c, 0x0c, 0x5d, 0x42, 0x2e, 0x1c, 0xdf, 0x1f, 0x1d, 0xc9, -+ 0x43, 0x94, 0x5b, 0x6e, 0x8f, 0x15, 0x8c, 0x8f, 0x94, 0x73, 0x4f, 0x97, -+ 0x54, 0xf1, 0x86, 0x8a, 0xbc, 0xe4, 0xe4, 0x93, 0xc1, 0x5e, 0xc2, 0x3e, -+ 0x31, 0x5e, 0xd4, 0x85, 0x57, 0x14, 0xd0, 0x11, 0x07, 0x65, 0xf4, 0x7c, -+ 0x8f, 0x07, 0x57, 0xe1, 0x22, 0xd4, 0x78, 0x47, 0x65, 0x4e, 0xa9, 0xb3, -+ 0xaa, 0xce, 0xc7, 0x36, 0xfe, 0xda, 0x66, 0x02, 0xb6, 0x8d, 0x18, 0x2f, -+ 0x3b, 0x41, 0x8d, 0x02, 0x08, 0x72, 0x4b, 0x69, 0xbd, 0x1e, 0x58, 0xfc, -+ 0x1b, 0x64, 0x04, 0x52, 0x35, 0x35, 0xe2, 0x3d, 0x3e, 0xde, 0xd6, 0x64, -+ 0xf4, 0xec, 0x57, 0x7e, 0x65, 0x59, 0x00, 0xa6, 0xd3, 0x4b, 0x09, 0x93, -+ 0x2a, 0x95, 0x0f, 0x30, 0xb6, 0xa1, 0x8c, 0xe7, 0x8b, 0x49, 0xa4, 0x1d, -+ 0x25, 0x2d, 0x65, 0x48, 0x8a, 0x0f, 0xcf, 0x2a, 0xa2, 0xe1, 0xef, 0x72, -+ 0x92, 0xc3, 0xf5, 0x21, 0x37, 0x83, 0x9b, 0x6d, 0x0b, 0x1b, 0xb3, 0xa2, -+ 0x32, 0x38, 0x11, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x5d, 0x30, -+ 0x5b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, -+ 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, -+ 0x03, 0x02, 0x07, 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, -+ 0x16, 0x04, 0x14, 0xe5, 0x2a, 0x4f, 0xf2, 0x84, 0x91, 0x57, 0x91, 0xaf, -+ 0x12, 0xd2, 0xf1, 0xa1, 0x87, 0x73, 0x0f, 0x90, 0x25, 0xa0, 0x7a, 0x30, -+ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, -+ 0x56, 0xd1, 0xfd, 0xe2, 0x1e, 0x7e, 0x1c, 0x63, 0x4f, 0x47, 0xdb, 0xe4, -+ 0xc4, 0x51, 0x04, 0x03, 0x9a, 0x48, 0x35, 0x6e, 0x30, 0x0d, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, -+ 0x82, 0x01, 0x01, 0x00, 0x65, 0x82, 0xd5, 0x88, 0x30, 0xe2, 0x2c, 0x47, -+ 0xf3, 0x31, 0x39, 0xa1, 0x75, 0x9a, 0xb0, 0x8a, 0x6c, 0x4b, 0xac, 0xdf, -+ 0x09, 0x7b, 0x90, 0xb6, 0x9e, 0x76, 0x62, 0x94, 0xc1, 0x3a, 0x99, 0x49, -+ 0x68, 0x29, 0x47, 0x42, 0xc3, 0x06, 0xcb, 0x88, 0x75, 0xe6, 0x79, 0x13, -+ 0x8c, 0x4b, 0x49, 0x6a, 0xb5, 0x56, 0x95, 0xc0, 0x42, 0x21, 0x9b, 0xd4, -+ 0x61, 0xd0, 0x02, 0x41, 0xdd, 0x20, 0x61, 0xe5, 0x91, 0xdf, 0x75, 0x00, -+ 0x25, 0x0e, 0x99, 0x65, 0x5c, 0x54, 0x49, 0x32, 0xa3, 0xe2, 0xcd, 0xa1, -+ 0x5f, 0x40, 0xf3, 0xc5, 0x81, 0xd9, 0x3c, 0xa3, 0x63, 0x5a, 0x38, 0x79, -+ 0xab, 0x77, 0x98, 0xde, 0x8f, 0x4e, 0x9e, 0x26, 0xbc, 0x4e, 0x80, 0x9e, -+ 0x8f, 0xbe, 0xf1, 0x00, 0xb3, 0x78, 0xb9, 0x4b, 0x1d, 0xc7, 0xa4, 0x83, -+ 0x59, 0x56, 0x11, 0xd1, 0x11, 0x1e, 0x50, 0x39, 0xd5, 0x78, 0x14, 0xf3, -+ 0xb9, 0x1d, 0xda, 0xe4, 0xc4, 0x63, 0x74, 0x26, 0xab, 0xa3, 0xfd, 0x9d, -+ 0x58, 0xa2, 0xee, 0x7b, 0x28, 0x34, 0xa3, 0xbe, 0x85, 0x7e, 0xaa, 0x97, -+ 0xb7, 0x5b, 0x9d, 0xa9, 0x4d, 0x96, 0xdb, 0x6b, 0x21, 0xe1, 0x96, 0x5d, -+ 0xc7, 0xad, 0x23, 0x03, 0x9a, 0x16, 0xdb, 0xa4, 0x1f, 0x63, 0xef, 0xaf, -+ 0x1e, 0x4f, 0xf8, 0x27, 0xdc, 0x4b, 0xfc, 0x2b, 0x68, 0x2e, 0xa0, 0xd3, -+ 0xae, 0xf2, 0xce, 0xf5, 0xfc, 0x97, 0x92, 0xd2, 0x29, 0x0f, 0x4f, 0x4b, -+ 0x29, 0xeb, 0x06, 0xcb, 0xf8, 0x21, 0x6e, 0xbc, 0x8b, 0x5c, 0xc5, 0xc9, -+ 0xf7, 0xe2, 0x7c, 0x47, 0xcd, 0x43, 0x98, 0xc4, 0xa3, 0x9a, 0xd7, 0x3e, -+ 0xdc, 0x01, 0x13, 0x28, 0x96, 0xc4, 0x60, 0x83, 0xe2, 0x79, 0xa1, 0x46, -+ 0xef, 0xf5, 0xa4, 0x7b, 0x00, 0xe3, 0x3d, 0x7d, 0xbc, 0xa8, 0x98, 0x49, -+ 0xa8, 0xcf, 0x3b, 0x41, 0xb6, 0x09, 0x97, 0x07 -+}; -+unsigned int certificate_der_len = 908; -+ -+unsigned char hi_signed[] = { -+ 0x68, 0x69, 0x0a, 0x30, 0x82, 0x01, 0xc0, 0x06, 0x09, 0x2a, 0x86, 0x48, -+ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x01, 0xb1, 0x30, 0x82, -+ 0x01, 0xad, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, -+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x01, -+ 0x8a, 0x30, 0x82, 0x01, 0x86, 0x02, 0x01, 0x01, 0x30, 0x61, 0x30, 0x49, -+ 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1f, 0x47, -+ 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, -+ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, -+ 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0e, 0x64, -+ 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, 0x6e, 0x65, -+ 0x74, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, -+ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, -+ 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc7, 0x69, 0x35, 0x21, 0x66, -+ 0x4d, 0x50, 0xd4, 0x73, 0xde, 0xbd, 0x3a, 0xf6, 0x45, 0xe3, 0xe4, 0xd0, -+ 0xb6, 0xa1, 0xe7, 0xc0, 0xa2, 0xc9, 0xf4, 0xf0, 0x05, 0x8c, 0xa4, 0x16, -+ 0x9e, 0x81, 0x0d, 0x21, 0x68, 0xf3, 0xfe, 0x03, 0x96, 0x77, 0x31, 0x69, -+ 0x01, 0xd8, 0x26, 0xd9, 0x48, 0x95, 0xcf, 0xd1, 0x17, 0xb1, 0x0b, 0x6b, -+ 0x2c, 0xf1, 0xb0, 0xab, 0x65, 0x65, 0x56, 0xf8, 0x0c, 0xa7, 0xf7, 0xbb, -+ 0xf6, 0x5a, 0x55, 0x98, 0x14, 0x07, 0x8d, 0x2a, 0xbc, 0x16, 0x48, 0x94, -+ 0xab, 0x2f, 0x85, 0x97, 0x90, 0x51, 0x78, 0xa0, 0xda, 0x60, 0xb5, 0x41, -+ 0x4b, 0xe8, 0x78, 0xc5, 0xa6, 0x04, 0x9d, 0x54, 0x2a, 0x85, 0xfd, 0x86, -+ 0x0b, 0x6d, 0xc2, 0xd2, 0xad, 0x07, 0xff, 0x16, 0x42, 0x82, 0xe3, 0x5c, -+ 0xaa, 0x22, 0x59, 0x78, 0x92, 0xea, 0x94, 0xc3, 0x41, 0xb7, 0xa1, 0x86, -+ 0x44, 0xea, 0xd1, 0xdb, 0xe5, 0xac, 0x30, 0x32, 0xfb, 0x7d, 0x3f, 0xf7, -+ 0x8b, 0x11, 0x7f, 0x80, 0x3b, 0xe5, 0xc7, 0x82, 0x0f, 0x92, 0x07, 0x14, -+ 0x66, 0x01, 0x6e, 0x85, 0xab, 0x3a, 0x14, 0xcf, 0x76, 0xd1, 0x7e, 0x14, -+ 0x85, 0xca, 0x01, 0x73, 0x72, 0x38, 0xdc, 0xde, 0x30, 0x5c, 0xfb, 0xc0, -+ 0x3d, 0x93, 0xef, 0x9c, 0xbc, 0xf8, 0xcc, 0xd2, 0xbf, 0x47, 0xec, 0xf8, -+ 0x88, 0x9b, 0xe1, 0x43, 0xbe, 0xa7, 0x47, 0x96, 0xb6, 0x5d, 0x46, 0x0e, -+ 0x7a, 0x78, 0x38, 0x19, 0xbc, 0xb5, 0xbc, 0x9b, 0x3c, 0x39, 0x92, 0x70, -+ 0x0d, 0x9d, 0x8a, 0x35, 0xaf, 0xb4, 0x9e, 0xf4, 0xef, 0xc1, 0xb8, 0x25, -+ 0xd0, 0x14, 0x91, 0xd6, 0xc2, 0xb6, 0xc7, 0x3c, 0x72, 0x91, 0x0f, 0xad, -+ 0xde, 0xb2, 0x36, 0xf8, 0x4e, 0x59, 0xd4, 0xa4, 0x21, 0x9f, 0x03, 0x95, -+ 0x48, 0x01, 0xb4, 0x05, 0xc3, 0x39, 0x60, 0x51, 0x08, 0xd0, 0xbe, 0x00, -+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x7e, -+ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, -+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, -+ 0x64, 0x7e, 0x0a -+}; -+unsigned int hi_signed_len = 495; -+ -+unsigned char hj_signed[] = { -+ 0x68, 0x6a, 0x0a, 0x30, 0x82, 0x01, 0xc0, 0x06, 0x09, 0x2a, 0x86, 0x48, -+ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x01, 0xb1, 0x30, 0x82, -+ 0x01, 0xad, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, -+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x01, -+ 0x8a, 0x30, 0x82, 0x01, 0x86, 0x02, 0x01, 0x01, 0x30, 0x61, 0x30, 0x49, -+ 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1f, 0x47, -+ 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, -+ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, -+ 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0e, 0x64, -+ 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, 0x6e, 0x65, -+ 0x74, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, -+ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, -+ 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc7, 0x69, 0x35, 0x21, 0x66, -+ 0x4d, 0x50, 0xd4, 0x73, 0xde, 0xbd, 0x3a, 0xf6, 0x45, 0xe3, 0xe4, 0xd0, -+ 0xb6, 0xa1, 0xe7, 0xc0, 0xa2, 0xc9, 0xf4, 0xf0, 0x05, 0x8c, 0xa4, 0x16, -+ 0x9e, 0x81, 0x0d, 0x21, 0x68, 0xf3, 0xfe, 0x03, 0x96, 0x77, 0x31, 0x69, -+ 0x01, 0xd8, 0x26, 0xd9, 0x48, 0x95, 0xcf, 0xd1, 0x17, 0xb1, 0x0b, 0x6b, -+ 0x2c, 0xf1, 0xb0, 0xab, 0x65, 0x65, 0x56, 0xf8, 0x0c, 0xa7, 0xf7, 0xbb, -+ 0xf6, 0x5a, 0x55, 0x98, 0x14, 0x07, 0x8d, 0x2a, 0xbc, 0x16, 0x48, 0x94, -+ 0xab, 0x2f, 0x85, 0x97, 0x90, 0x51, 0x78, 0xa0, 0xda, 0x60, 0xb5, 0x41, -+ 0x4b, 0xe8, 0x78, 0xc5, 0xa6, 0x04, 0x9d, 0x54, 0x2a, 0x85, 0xfd, 0x86, -+ 0x0b, 0x6d, 0xc2, 0xd2, 0xad, 0x07, 0xff, 0x16, 0x42, 0x82, 0xe3, 0x5c, -+ 0xaa, 0x22, 0x59, 0x78, 0x92, 0xea, 0x94, 0xc3, 0x41, 0xb7, 0xa1, 0x86, -+ 0x44, 0xea, 0xd1, 0xdb, 0xe5, 0xac, 0x30, 0x32, 0xfb, 0x7d, 0x3f, 0xf7, -+ 0x8b, 0x11, 0x7f, 0x80, 0x3b, 0xe5, 0xc7, 0x82, 0x0f, 0x92, 0x07, 0x14, -+ 0x66, 0x01, 0x6e, 0x85, 0xab, 0x3a, 0x14, 0xcf, 0x76, 0xd1, 0x7e, 0x14, -+ 0x85, 0xca, 0x01, 0x73, 0x72, 0x38, 0xdc, 0xde, 0x30, 0x5c, 0xfb, 0xc0, -+ 0x3d, 0x93, 0xef, 0x9c, 0xbc, 0xf8, 0xcc, 0xd2, 0xbf, 0x47, 0xec, 0xf8, -+ 0x88, 0x9b, 0xe1, 0x43, 0xbe, 0xa7, 0x47, 0x96, 0xb6, 0x5d, 0x46, 0x0e, -+ 0x7a, 0x78, 0x38, 0x19, 0xbc, 0xb5, 0xbc, 0x9b, 0x3c, 0x39, 0x92, 0x70, -+ 0x0d, 0x9d, 0x8a, 0x35, 0xaf, 0xb4, 0x9e, 0xf4, 0xef, 0xc1, 0xb8, 0x25, -+ 0xd0, 0x14, 0x91, 0xd6, 0xc2, 0xb6, 0xc7, 0x3c, 0x72, 0x91, 0x0f, 0xad, -+ 0xde, 0xb2, 0x36, 0xf8, 0x4e, 0x59, 0xd4, 0xa4, 0x21, 0x9f, 0x03, 0x95, -+ 0x48, 0x01, 0xb4, 0x05, 0xc3, 0x39, 0x60, 0x51, 0x08, 0xd0, 0xbe, 0x00, -+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x7e, -+ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, -+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, -+ 0x64, 0x7e, 0x0a -+}; -+unsigned int hj_signed_len = 495; -+ -+unsigned char hi_signed_sha256[] = { -+ 0x68, 0x69, 0x0a, 0x30, 0x82, 0x01, 0xc0, 0x06, 0x09, 0x2a, 0x86, 0x48, -+ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x01, 0xb1, 0x30, 0x82, -+ 0x01, 0xad, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, -+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x01, -+ 0x8a, 0x30, 0x82, 0x01, 0x86, 0x02, 0x01, 0x01, 0x30, 0x61, 0x30, 0x49, -+ 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1f, 0x47, -+ 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, -+ 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, -+ 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0e, 0x64, -+ 0x6a, 0x61, 0x40, 0x61, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x2e, 0x6e, 0x65, -+ 0x74, 0x02, 0x14, 0x25, 0x2e, 0xb8, 0xfd, 0x12, 0x62, 0x2e, 0xcd, 0x5d, -+ 0xa7, 0x53, 0xd2, 0x0b, 0xc2, 0x61, 0x7c, 0x14, 0xe0, 0x0f, 0x5c, 0x30, -+ 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x7b, 0x5e, 0x82, 0x1d, 0x21, -+ 0xb6, 0x40, 0xd3, 0x33, 0x79, 0xa7, 0x52, 0x2b, 0xfc, 0x46, 0x51, 0x26, -+ 0xfe, 0x0f, 0x81, 0x90, 0x81, 0xab, 0x57, 0x5e, 0xf6, 0x45, 0x41, 0xa3, -+ 0x7b, 0x48, 0xdd, 0xd6, 0x59, 0x60, 0x51, 0x31, 0x14, 0x14, 0x7b, 0xb4, -+ 0x55, 0x7b, 0x4d, 0xfe, 0x09, 0x7a, 0x5d, 0xae, 0xc4, 0x58, 0x50, 0x80, -+ 0x75, 0xf2, 0x23, 0x20, 0x62, 0xe3, 0x7c, 0x26, 0x1d, 0x2a, 0x4d, 0x9f, -+ 0x89, 0xf0, 0x4f, 0x95, 0x8a, 0x80, 0x6e, 0x1a, 0xea, 0x87, 0xdb, 0x1f, -+ 0xf3, 0xda, 0x04, 0x91, 0x37, 0xea, 0x0a, 0xfb, 0x6c, 0xc9, 0x3d, 0x73, -+ 0xf9, 0x58, 0x7c, 0x15, 0x6b, 0xa2, 0x52, 0x5a, 0x97, 0xff, 0xd6, 0xb0, -+ 0xf1, 0xbf, 0xa5, 0x04, 0x6d, 0x91, 0xc1, 0x54, 0x05, 0xdc, 0x7f, 0x5d, -+ 0x19, 0xaf, 0x55, 0xec, 0x51, 0xfb, 0x66, 0x0a, 0xa4, 0x4e, 0x96, 0x47, -+ 0x43, 0x54, 0x7c, 0x64, 0xa8, 0xaa, 0xb4, 0x90, 0x02, 0xf3, 0xa7, 0x0b, -+ 0xb7, 0xbf, 0x06, 0xdb, 0x5e, 0x9c, 0x32, 0x6d, 0x45, 0x14, 0x1c, 0xaf, -+ 0x46, 0x30, 0x08, 0x55, 0x49, 0x78, 0xfa, 0x57, 0xda, 0x3d, 0xf5, 0xa0, -+ 0xef, 0x11, 0x0a, 0x81, 0x0d, 0x82, 0xcd, 0xaf, 0xdb, 0xda, 0x0e, 0x1a, -+ 0x44, 0xd1, 0xee, 0xc4, 0xb8, 0xde, 0x97, 0xb4, 0xda, 0xb4, 0x8b, 0x4f, -+ 0x58, 0x24, 0x59, 0xc0, 0xe0, 0x08, 0x97, 0x14, 0x68, 0xbe, 0x31, 0x09, -+ 0x5e, 0x67, 0x45, 0xf0, 0xcb, 0x81, 0x4f, 0x17, 0x44, 0x61, 0xe0, 0xe2, -+ 0xf0, 0xfc, 0x1e, 0xb9, 0x73, 0xaf, 0x42, 0xff, 0x33, 0xde, 0x61, 0x6b, -+ 0x7f, 0xc2, 0x69, 0x0d, 0x66, 0x54, 0xae, 0xf6, 0xde, 0x20, 0x47, 0x44, -+ 0x9b, 0x73, 0xd1, 0x07, 0x6e, 0x77, 0x37, 0x0a, 0xbb, 0x7f, 0xa0, 0x93, -+ 0x2d, 0x8d, 0x44, 0xba, 0xe2, 0xdd, 0x34, 0x32, 0xd7, 0x56, 0x71, 0x00, -+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x7e, -+ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, -+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, -+ 0x64, 0x7e, 0x0a -+}; -+unsigned int hi_signed_sha256_len = 495; -+ -+unsigned char short_msg[] = { -+ 0x68, 0x69, 0x0a -+}; -+unsigned int short_msg_len = 3; -+ -+unsigned char unsigned_msg[] = { -+ 0x53, 0x65, 0x64, 0x20, 0x75, 0x74, 0x20, 0x70, 0x65, 0x72, 0x73, 0x70, -+ 0x69, 0x63, 0x69, 0x61, 0x74, 0x69, 0x73, 0x20, 0x75, 0x6e, 0x64, 0x65, -+ 0x20, 0x6f, 0x6d, 0x6e, 0x69, 0x73, 0x20, 0x69, 0x73, 0x74, 0x65, 0x20, -+ 0x6e, 0x61, 0x74, 0x75, 0x73, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, -+ 0x73, 0x69, 0x74, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, -+ 0x65, 0x6d, 0x20, 0x61, 0x63, 0x63, 0x75, 0x73, 0x61, 0x6e, 0x74, 0x69, -+ 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x71, 0x75, -+ 0x65, 0x20, 0x6c, 0x61, 0x75, 0x64, 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, -+ 0x2c, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x6d, 0x20, -+ 0x61, 0x70, 0x65, 0x72, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x65, 0x61, 0x71, -+ 0x75, 0x65, 0x20, 0x69, 0x70, 0x73, 0x61, 0x20, 0x71, 0x75, 0x61, 0x65, -+ 0x20, 0x61, 0x62, 0x20, 0x69, 0x6c, 0x6c, 0x6f, 0x20, 0x69, 0x6e, 0x76, -+ 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x69, 0x74, -+ 0x61, 0x74, 0x69, 0x73, 0x20, 0x65, 0x74, 0x20, 0x71, 0x75, 0x61, 0x73, -+ 0x69, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x6f, -+ 0x20, 0x62, 0x65, 0x61, 0x74, 0x61, 0x65, 0x20, 0x76, 0x69, 0x74, 0x61, -+ 0x65, 0x20, 0x64, 0x69, 0x63, 0x74, 0x61, 0x20, 0x73, 0x75, 0x6e, 0x74, -+ 0x20, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6f, 0x2e, 0x20, -+ 0x4e, 0x65, 0x6d, 0x6f, 0x20, 0x65, 0x6e, 0x69, 0x6d, 0x20, 0x69, 0x70, -+ 0x73, 0x61, 0x6d, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, -+ 0x65, 0x6d, 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, -+ 0x70, 0x74, 0x61, 0x73, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x73, 0x70, -+ 0x65, 0x72, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x20, 0x61, 0x75, 0x74, 0x20, -+ 0x6f, 0x64, 0x69, 0x74, 0x20, 0x61, 0x75, 0x74, 0x20, 0x66, 0x75, 0x67, -+ 0x69, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x64, 0x20, 0x71, 0x75, 0x69, 0x61, -+ 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x75, 0x6e, 0x74, 0x75, -+ 0x72, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, -+ 0x72, 0x65, 0x73, 0x20, 0x65, 0x6f, 0x73, 0x20, 0x71, 0x75, 0x69, 0x20, -+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x6c, 0x75, -+ 0x70, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x20, 0x73, 0x65, 0x71, 0x75, 0x69, -+ 0x20, 0x6e, 0x65, 0x73, 0x63, 0x69, 0x75, 0x6e, 0x74, 0x2e, 0x20, 0x4e, -+ 0x65, 0x71, 0x75, 0x65, 0x20, 0x70, 0x6f, 0x72, 0x72, 0x6f, 0x20, 0x71, -+ 0x75, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x65, 0x73, 0x74, 0x2c, -+ 0x20, 0x71, 0x75, 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, -+ 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, -+ 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, -+ 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, -+ 0x74, 0x75, 0x72, 0x2c, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, -+ 0x69, 0x20, 0x76, 0x65, 0x6c, 0x69, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x64, -+ 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, 0x6e, 0x6f, 0x6e, 0x20, 0x6e, 0x75, -+ 0x6d, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x65, 0x69, 0x75, 0x73, 0x20, 0x6d, -+ 0x6f, 0x64, 0x69, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x20, -+ 0x69, 0x6e, 0x63, 0x69, 0x64, 0x75, 0x6e, 0x74, 0x20, 0x75, 0x74, 0x20, -+ 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x65, 0x20, 0x65, 0x74, 0x20, 0x64, 0x6f, -+ 0x6c, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x61, 0x6d, 0x20, -+ 0x61, 0x6c, 0x69, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x71, 0x75, 0x61, 0x65, -+ 0x72, 0x61, 0x74, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, -+ 0x65, 0x6d, 0x2e, 0x20, 0x55, 0x74, 0x20, 0x65, 0x6e, 0x69, 0x6d, 0x20, -+ 0x61, 0x64, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x20, 0x76, 0x65, -+ 0x6e, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x71, 0x75, 0x69, 0x73, 0x20, 0x6e, -+ 0x6f, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x20, 0x65, 0x78, 0x65, 0x72, 0x63, -+ 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x6d, 0x20, 0x75, 0x6c, -+ 0x6c, 0x61, 0x6d, 0x20, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x69, 0x73, -+ 0x20, 0x73, 0x75, 0x73, 0x63, 0x69, 0x70, 0x69, 0x74, 0x20, 0x6c, 0x61, -+ 0x62, 0x6f, 0x72, 0x69, 0x6f, 0x73, 0x61, 0x6d, 0x2c, 0x20, 0x6e, 0x69, -+ 0x73, 0x69, 0x20, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x71, 0x75, 0x69, -+ 0x64, 0x20, 0x65, 0x78, 0x20, 0x65, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, -+ 0x6f, 0x64, 0x69, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x61, -+ 0x74, 0x75, 0x72, 0x3f, 0x20, 0x51, 0x75, 0x69, 0x73, 0x20, 0x61, 0x75, -+ 0x74, 0x65, 0x6d, 0x20, 0x76, 0x65, 0x6c, 0x20, 0x65, 0x75, 0x6d, 0x20, -+ 0x69, 0x75, 0x72, 0x65, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x68, 0x65, -+ 0x6e, 0x64, 0x65, 0x72, 0x69, 0x74, 0x20, 0x71, 0x75, 0x69, 0x20, 0x69, -+ 0x6e, 0x20, 0x65, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, -+ 0x74, 0x65, 0x20, 0x76, 0x65, 0x6c, 0x69, 0x74, 0x20, 0x65, 0x73, 0x73, -+ 0x65, 0x20, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x6e, 0x69, 0x68, 0x69, 0x6c, -+ 0x20, 0x6d, 0x6f, 0x6c, 0x65, 0x73, 0x74, 0x69, 0x61, 0x65, 0x20, 0x63, -+ 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x61, 0x74, 0x75, 0x72, 0x2c, 0x20, -+ 0x76, 0x65, 0x6c, 0x20, 0x69, 0x6c, 0x6c, 0x75, 0x6d, 0x20, 0x71, 0x75, -+ 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x65, 0x75, -+ 0x6d, 0x20, 0x66, 0x75, 0x67, 0x69, 0x61, 0x74, 0x20, 0x71, 0x75, 0x6f, -+ 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x73, 0x20, 0x6e, 0x75, -+ 0x6c, 0x6c, 0x61, 0x20, 0x70, 0x61, 0x72, 0x69, 0x61, 0x74, 0x75, 0x72, -+ 0x3f, 0x0a -+}; -+unsigned int unsigned_msg_len = 866; -+ -+unsigned char certificate2_der[] = { -+ 0x30, 0x82, 0x05, 0x52, 0x30, 0x82, 0x03, 0x3a, 0xa0, 0x03, 0x02, 0x01, -+ 0x02, 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, -+ 0x3a, 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, -+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, -+ 0x05, 0x00, 0x30, 0x3a, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, -+ 0x03, 0x0c, 0x2f, 0x47, 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, -+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, -+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, -+ 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, -+ 0x74, 0x79, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x37, 0x32, 0x38, -+ 0x31, 0x33, 0x32, 0x34, 0x32, 0x39, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x32, -+ 0x30, 0x30, 0x37, 0x30, 0x34, 0x31, 0x33, 0x32, 0x34, 0x32, 0x39, 0x5a, -+ 0x30, 0x2b, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, -+ 0x20, 0x47, 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, -+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, -+ 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x65, 0x79, 0x30, 0x82, 0x02, -+ 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, -+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, -+ 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb0, 0x2f, 0x50, 0x01, 0x9c, 0x0e, -+ 0xd6, 0x8c, 0x07, 0xca, 0xc1, 0xcf, 0xbc, 0x03, 0xdd, 0xd3, 0xfa, 0xe3, -+ 0x4f, 0x71, 0xc1, 0x30, 0xaa, 0x09, 0x96, 0xe4, 0xd0, 0x6c, 0x42, 0x93, -+ 0xdb, 0x35, 0xf6, 0x7e, 0x1b, 0x67, 0xc0, 0xc2, 0x2d, 0x5b, 0xec, 0xca, -+ 0x35, 0x06, 0x32, 0x6c, 0x7b, 0x2c, 0xd3, 0x71, 0x2b, 0xe9, 0x7a, 0x19, -+ 0xd1, 0xf2, 0xa0, 0x7f, 0xd7, 0x4d, 0x6e, 0x28, 0xbb, 0xae, 0x49, 0x4a, -+ 0xbc, 0xea, 0x47, 0x67, 0xb8, 0x36, 0xa6, 0xf5, 0x0d, 0x0e, 0x20, 0x14, -+ 0x0c, 0x66, 0x67, 0x28, 0xb5, 0x97, 0x8b, 0x1f, 0x5e, 0x32, 0x06, 0x29, -+ 0x9c, 0x99, 0x92, 0x0f, 0x73, 0xac, 0xfd, 0xd2, 0x1d, 0xf2, 0xa8, 0x55, -+ 0x9d, 0x1b, 0xd8, 0x3d, 0xb0, 0x76, 0x9a, 0xb6, 0x6c, 0x9f, 0x62, 0x37, -+ 0x2f, 0xc0, 0xef, 0x44, 0xb3, 0x0d, 0x4a, 0x3e, 0x4f, 0x7d, 0xbd, 0xdb, -+ 0xd8, 0x75, 0x5f, 0x68, 0xe3, 0xf0, 0xec, 0x82, 0x66, 0x7c, 0x31, 0x70, -+ 0xa9, 0xa1, 0x6f, 0x38, 0x9f, 0xdf, 0xf5, 0xf0, 0x7d, 0x23, 0x9d, 0x34, -+ 0xa5, 0x85, 0xd3, 0xdf, 0x68, 0x41, 0xfc, 0x4f, 0x89, 0x45, 0x3c, 0x24, -+ 0x81, 0xa6, 0xf2, 0x3c, 0x02, 0x26, 0x09, 0x48, 0xdd, 0xfe, 0x4b, 0xb6, -+ 0x66, 0xbf, 0x8f, 0xe5, 0x5f, 0xf0, 0x5d, 0x8a, 0x61, 0x2e, 0x5f, 0x9f, -+ 0x80, 0xd9, 0xd5, 0xe6, 0x41, 0xd8, 0x10, 0x5e, 0x7a, 0xc6, 0xdb, 0x89, -+ 0xc7, 0xca, 0x6c, 0x5b, 0xb1, 0x4e, 0x7d, 0x0c, 0x03, 0xfd, 0x50, 0xca, -+ 0xbf, 0xbb, 0xe2, 0x69, 0x4b, 0x4e, 0xc2, 0x3d, 0x75, 0xfa, 0xd1, 0xcc, -+ 0xd6, 0xf9, 0x39, 0xb9, 0xdc, 0x53, 0xad, 0x62, 0xfb, 0x1b, 0x94, 0x26, -+ 0x7f, 0x21, 0x54, 0x5c, 0xb7, 0xdc, 0xe7, 0x96, 0x8c, 0xce, 0x75, 0xe0, -+ 0x17, 0x01, 0x3a, 0x3c, 0x77, 0x6e, 0xa4, 0x8b, 0x7a, 0x83, 0x28, 0x7a, -+ 0xf7, 0xb0, 0x5f, 0xfc, 0x7f, 0x2d, 0x2e, 0xec, 0xf5, 0xeb, 0x9c, 0x63, -+ 0x74, 0xd0, 0xe5, 0xdc, 0x19, 0xe4, 0x71, 0xc5, 0x4a, 0x8a, 0x54, 0xa4, -+ 0xe0, 0x7d, 0x4e, 0xbf, 0x53, 0x30, 0xaf, 0xd0, 0xeb, 0x96, 0xc3, 0xbb, -+ 0x65, 0xf7, 0x67, 0xf5, 0xae, 0xd3, 0x96, 0xf2, 0x63, 0xc8, 0x69, 0xf7, -+ 0x47, 0xcb, 0x27, 0x79, 0xe1, 0xff, 0x2f, 0x68, 0xdf, 0x1e, 0xb3, 0xb8, -+ 0x0c, 0xc5, 0x58, 0x73, 0xcc, 0xfe, 0x8c, 0xda, 0x4e, 0x3b, 0x01, 0x04, -+ 0xcd, 0xcb, 0xb8, 0x3e, 0x06, 0xfd, 0x4c, 0x0a, 0x9f, 0x5e, 0x76, 0x8c, -+ 0x0c, 0x83, 0x75, 0x09, 0x08, 0xb2, 0xdb, 0xf4, 0x49, 0x4e, 0xa0, 0xf2, -+ 0x0c, 0x7b, 0x87, 0x38, 0x9e, 0x22, 0x67, 0xbd, 0xd1, 0x97, 0x57, 0x24, -+ 0xf1, 0x46, 0x07, 0xf9, 0xd2, 0x1b, 0xec, 0x25, 0x5e, 0x67, 0xd9, 0x66, -+ 0x23, 0x1b, 0xd3, 0xe4, 0xaa, 0xec, 0x88, 0xf0, 0x7e, 0x15, 0x83, 0x51, -+ 0x31, 0x67, 0x51, 0x76, 0x5f, 0x55, 0xd7, 0x36, 0xdf, 0x4a, 0x84, 0x0b, -+ 0x6f, 0x5c, 0xbb, 0x5b, 0x8f, 0x37, 0x23, 0x7f, 0xf8, 0x17, 0x84, 0xa2, -+ 0x70, 0x20, 0x07, 0x0c, 0x90, 0x3a, 0x04, 0xfd, 0xf0, 0x08, 0x4a, 0xb1, -+ 0x16, 0x0f, 0xe6, 0xf6, 0x40, 0x51, 0x83, 0xd2, 0x87, 0x40, 0x9c, 0x1c, -+ 0x9f, 0x13, 0x38, 0x17, 0xd3, 0x34, 0x58, 0xad, 0x05, 0x71, 0xa0, 0x73, -+ 0xca, 0x40, 0xa6, 0xa4, 0x81, 0x02, 0xee, 0xa8, 0x72, 0x41, 0xa1, 0x41, -+ 0x18, 0x64, 0x8a, 0x86, 0x8a, 0x5d, 0xe6, 0x4f, 0x0a, 0xc5, 0x95, 0x98, -+ 0xf9, 0x78, 0xfe, 0x19, 0x0d, 0xc9, 0xb3, 0x89, 0xc1, 0x2b, 0x09, 0xbe, -+ 0xf1, 0xd2, 0x04, 0x5d, 0xcc, 0x28, 0xf5, 0x4b, 0xd2, 0x20, 0x4f, 0xc5, -+ 0x41, 0x9d, 0x8c, 0x85, 0xd8, 0xb0, 0x68, 0x5e, 0xc1, 0x0c, 0xb7, 0x24, -+ 0x4d, 0x67, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x5d, 0x30, 0x5b, 0x30, -+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, -+ 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, -+ 0x07, 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, -+ 0x14, 0xac, 0xf5, 0x47, 0x17, 0xd9, 0x7d, 0xc1, 0xb1, 0xc4, 0x41, 0xe1, -+ 0x41, 0x60, 0xcb, 0x37, 0x11, 0x60, 0x28, 0x78, 0x5f, 0x30, 0x1f, 0x06, -+ 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x21, 0x94, -+ 0xfb, 0xf9, 0xb2, 0x43, 0xe9, 0x33, 0xd7, 0x50, 0x7d, 0xc7, 0x37, 0xdb, -+ 0xd5, 0x82, 0x5a, 0x4e, 0xbe, 0x1b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, -+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, -+ 0x01, 0x00, 0x96, 0x70, 0x65, 0x26, 0x42, 0xf8, 0xdc, 0x69, 0xde, 0xcf, -+ 0x41, 0x3a, 0x2e, 0x7f, 0x5b, 0xf1, 0xf9, 0x3b, 0x9b, 0xd2, 0x4e, 0x64, -+ 0x48, 0x81, 0xe4, 0x5d, 0x1e, 0x22, 0xce, 0x68, 0x63, 0x62, 0xe5, 0x1b, -+ 0x9b, 0xf2, 0xc7, 0x12, 0xda, 0x1e, 0x9b, 0x90, 0x84, 0x79, 0x48, 0x12, -+ 0xe6, 0x21, 0x6f, 0x2f, 0x7e, 0x18, 0x77, 0xdb, 0x8c, 0xc4, 0xd1, 0x0d, -+ 0x91, 0xbf, 0x39, 0x22, 0x0f, 0x64, 0xcf, 0x25, 0x2e, 0x8c, 0x1f, 0x91, -+ 0x81, 0xb5, 0xe9, 0x6c, 0x02, 0x3a, 0xf8, 0x07, 0xa2, 0x6f, 0x46, 0x5d, -+ 0x7b, 0xfd, 0x43, 0xff, 0x41, 0x0f, 0xe2, 0x57, 0x1c, 0xbd, 0x48, 0x60, -+ 0x53, 0x11, 0x48, 0x87, 0x88, 0x9d, 0x13, 0x82, 0x40, 0x68, 0x44, 0x2c, -+ 0xc6, 0xc8, 0x95, 0x27, 0x4f, 0xb6, 0xb9, 0x4a, 0x22, 0x0a, 0xfd, 0xe4, -+ 0x46, 0x8f, 0x35, 0x12, 0x98, 0x5a, 0x34, 0x6f, 0x2b, 0x57, 0x62, 0xa1, -+ 0x4d, 0x8d, 0x79, 0x37, 0xe4, 0x6b, 0x8a, 0x32, 0x5b, 0xcb, 0xef, 0x79, -+ 0x11, 0xed, 0xa7, 0xf8, 0x7a, 0x1c, 0xbd, 0x86, 0xdc, 0x0e, 0x2e, 0xfd, -+ 0xd3, 0x51, 0xbb, 0x73, 0xad, 0x00, 0xa0, 0x1b, 0xf9, 0x1d, 0xd1, 0x4a, -+ 0xe4, 0xd4, 0x02, 0x63, 0x2b, 0x39, 0x5f, 0x18, 0x08, 0x2f, 0x42, 0xb7, -+ 0x23, 0x4b, 0x48, 0x46, 0x1f, 0x63, 0x87, 0xae, 0x6d, 0xd5, 0xdb, 0x60, -+ 0xf8, 0x5f, 0xd3, 0x13, 0xec, 0xca, 0xdd, 0x60, 0x60, 0x79, 0x52, 0x70, -+ 0x47, 0xae, 0x1d, 0x38, 0x78, 0x71, 0xcf, 0xb3, 0x04, 0x03, 0xbe, 0xba, -+ 0x81, 0xba, 0x74, 0xb1, 0x30, 0x35, 0xdc, 0xea, 0x21, 0x4a, 0x9b, 0x70, -+ 0xfb, 0xd6, 0x60, 0x59, 0x78, 0x0c, 0x4d, 0x39, 0x19, 0x1d, 0xe5, 0x75, -+ 0xba, 0x07, 0xf4, 0x22, 0x37, 0x64, 0xb7, 0xf2, 0x9a, 0xc9, 0x11, 0x2d, -+ 0x8e, 0x58, 0xa6, 0xcf, 0x83, 0xf1, 0xcb, 0x6c, 0x7f, 0x02, 0xbd, 0xda, -+ 0x03, 0x92, 0xa9, 0x45, 0x24, 0x56, 0xc5, 0xbd, 0x41, 0xd1, 0x20, 0x86, -+ 0xc0, 0xb6, 0xb7, 0xe8, 0xa7, 0xb2, 0x46, 0xf7, 0x8e, 0xa9, 0x38, 0x0e, -+ 0x23, 0x77, 0x3c, 0x0d, 0x66, 0x83, 0x6a, 0x1a, 0x6b, 0x7f, 0x54, 0x11, -+ 0x58, 0x0d, 0x4a, 0xb5, 0x74, 0x60, 0xca, 0xed, 0xff, 0x91, 0x47, 0xd9, -+ 0x29, 0xe0, 0xaa, 0x8c, 0xa8, 0x8f, 0x10, 0x4c, 0x15, 0x7d, 0xce, 0x95, -+ 0xf9, 0x87, 0x1e, 0x18, 0x38, 0x18, 0xfc, 0xcc, 0xaf, 0x91, 0x17, 0x3f, -+ 0xfa, 0xf0, 0x8a, 0x09, 0x6f, 0xba, 0x4e, 0x53, 0xf7, 0xfa, 0x4f, 0x20, -+ 0xa3, 0xf4, 0x4a, 0x5a, 0xde, 0x17, 0x1c, 0x29, 0x6a, 0x6f, 0x03, 0x48, -+ 0xdf, 0xad, 0x4f, 0xe4, 0xbc, 0x71, 0xc4, 0x72, 0x32, 0x11, 0x84, 0xac, -+ 0x09, 0xd2, 0x18, 0x44, 0x35, 0xf1, 0xcd, 0xaf, 0xa8, 0x98, 0xe0, 0x8b, -+ 0xec, 0xa0, 0x83, 0x37, 0xc3, 0x35, 0x85, 0xd6, 0xd8, 0x1b, 0xe0, 0x75, -+ 0xdc, 0xfd, 0xde, 0xc9, 0xeb, 0xd5, 0x18, 0x0f, 0xd3, 0x4c, 0x2f, 0x71, -+ 0xdc, 0x48, 0xe3, 0x14, 0xeb, 0xda, 0x00, 0x24, 0x24, 0x9e, 0xa3, 0x8e, -+ 0x3e, 0x08, 0x6f, 0x22, 0x24, 0xd6, 0xc4, 0x85, 0x8f, 0x68, 0x00, 0x4a, -+ 0x82, 0x4c, 0x33, 0x6e, 0xa5, 0x35, 0x7b, 0xeb, 0x4b, 0xdc, 0xa0, 0xa6, -+ 0x65, 0x6f, 0x5a, 0x7a, 0xdf, 0x8a, 0x01, 0x52, 0xa1, 0x6c, 0xff, 0x59, -+ 0x22, 0x7f, 0xe1, 0x96, 0x1b, 0x19, 0xb8, 0xf9, 0x5d, 0x44, 0x9f, 0x91, -+ 0x03, 0x3c, 0x3d, 0xa1, 0x2a, 0xb6, 0x5a, 0x51, 0xa0, 0xce, 0x4a, 0x88, -+ 0x22, 0x72, 0x9c, 0xdc, 0xc0, 0x47, 0x76, 0x35, 0x84, 0x75, 0x9b, 0x87, -+ 0x5c, 0xd3, 0xcf, 0xe7, 0xdd, 0xa3, 0x57, 0x14, 0xdf, 0x00, 0xfd, 0x19, -+ 0x2a, 0x7d, 0x89, 0x27, 0x1c, 0x78, 0x97, 0x04, 0x58, 0x48 -+}; -+unsigned int certificate2_der_len = 1366; -+ -+unsigned char hi_signed_2nd[] = { -+ 0x68, 0x69, 0x0a, 0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, -+ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, -+ 0x02, 0x9e, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, -+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, -+ 0x7b, 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x01, 0x30, 0x52, 0x30, 0x3a, -+ 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x47, -+ 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, 0x72, 0x74, -+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, -+ 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, -+ 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, 0x14, -+ 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, 0x3a, 0x91, 0x07, -+ 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, 0x0b, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0d, 0x06, -+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, -+ 0x04, 0x82, 0x02, 0x00, 0x0e, 0xc2, 0x30, 0x38, 0x81, 0x23, 0x68, 0x90, -+ 0xae, 0x5f, 0xce, 0xf7, 0x27, 0xb1, 0x8c, 0x2e, 0x12, 0x10, 0xc6, 0x99, -+ 0xdc, 0x4d, 0x4b, 0x79, 0xda, 0xe4, 0x32, 0x10, 0x46, 0x1c, 0x16, 0x07, -+ 0x87, 0x66, 0x55, 0xff, 0x64, 0x1c, 0x61, 0x25, 0xd5, 0xb9, 0xe1, 0xfe, -+ 0xea, 0x5a, 0xcd, 0x56, 0xa5, 0xc3, 0xbe, 0xb1, 0x61, 0xc7, 0x6f, 0x5f, -+ 0x69, 0x20, 0x64, 0x50, 0x6f, 0x12, 0x78, 0xb6, 0x0c, 0x72, 0x44, 0x4f, -+ 0x60, 0x0f, 0x9f, 0xa2, 0x83, 0x3b, 0xc2, 0x83, 0xd5, 0x14, 0x1f, 0x6f, -+ 0x3e, 0xb2, 0x47, 0xb5, 0x58, 0xc5, 0xa7, 0xb4, 0x82, 0x53, 0x2e, 0x53, -+ 0x95, 0x4e, 0x3d, 0xe4, 0x62, 0xe8, 0xa1, 0xaf, 0xae, 0xbf, 0xa9, 0xd2, -+ 0x22, 0x07, 0xbe, 0x71, 0x37, 0x2c, 0x5a, 0xa7, 0x6c, 0xaf, 0x14, 0xc0, -+ 0x6c, 0x2f, 0xbf, 0x4f, 0x15, 0xc2, 0x0f, 0x8b, 0xdc, 0x68, 0x45, 0xdf, -+ 0xf3, 0xa5, 0x7f, 0x11, 0x6a, 0x54, 0xcd, 0x67, 0xb9, 0x2e, 0x7d, 0x05, -+ 0xe3, 0x1c, 0x1d, 0xcc, 0x77, 0x8e, 0x97, 0xb1, 0xa0, 0x11, 0x09, 0x3d, -+ 0x90, 0x54, 0xfc, 0x7e, 0xbb, 0xbb, 0x21, 0x23, 0x03, 0x44, 0xbf, 0x7d, -+ 0x2c, 0xc9, 0x15, 0x42, 0xe5, 0xa0, 0x3b, 0xa2, 0xd1, 0x5b, 0x73, 0x81, -+ 0xff, 0xfa, 0x90, 0xfc, 0x27, 0x7b, 0x2f, 0x86, 0x9c, 0x1d, 0x14, 0x36, -+ 0x94, 0xa2, 0x6e, 0xe8, 0x9d, 0xa0, 0x5f, 0xfc, 0x5a, 0x0d, 0xa4, 0xd5, -+ 0x2f, 0x8d, 0xd6, 0x00, 0xfa, 0x93, 0x5b, 0x09, 0x7f, 0x42, 0x78, 0xcc, -+ 0x8c, 0x49, 0xda, 0xd9, 0xf6, 0x43, 0xe7, 0xe1, 0x3c, 0xa2, 0xe2, 0x70, -+ 0xe2, 0x6a, 0x99, 0xc5, 0xd6, 0xa2, 0xe3, 0x0b, 0xd4, 0x09, 0xac, 0x94, -+ 0xaf, 0xb7, 0xf0, 0xb3, 0x0c, 0x1e, 0xf5, 0x16, 0x4f, 0x53, 0x9a, 0xe3, -+ 0xcc, 0xe2, 0x0c, 0x4a, 0xb9, 0xe6, 0x06, 0xbb, 0xf7, 0x41, 0x43, 0x20, -+ 0x04, 0xee, 0x99, 0x2f, 0xd8, 0x9f, 0xda, 0x3f, 0xfd, 0x49, 0xb8, 0xc2, -+ 0xbd, 0xd9, 0xc5, 0x72, 0xfd, 0xe3, 0xce, 0x1c, 0xbc, 0xe4, 0x39, 0xac, -+ 0x2a, 0x99, 0xe9, 0xb4, 0x3e, 0x74, 0x10, 0xeb, 0xd5, 0x14, 0xcc, 0xdb, -+ 0xf1, 0x04, 0x63, 0x36, 0xfb, 0x1f, 0x2b, 0xe2, 0x73, 0xd4, 0xd8, 0x49, -+ 0x31, 0xa8, 0x55, 0xcc, 0xa7, 0x76, 0x36, 0x6e, 0x18, 0xdc, 0xb9, 0xb0, -+ 0x29, 0x99, 0xcf, 0x49, 0xbf, 0xf9, 0xdb, 0x7f, 0x24, 0x42, 0x02, 0xcb, -+ 0xc1, 0xaa, 0xcb, 0xba, 0x18, 0x85, 0x86, 0xc7, 0xf4, 0x1c, 0x62, 0x76, -+ 0xbc, 0x73, 0xfb, 0xe4, 0x15, 0xb8, 0xdd, 0x5d, 0xa6, 0x68, 0x39, 0xa5, -+ 0x3d, 0x33, 0xaf, 0xd5, 0x92, 0x4d, 0x48, 0xdb, 0x22, 0xc0, 0xdc, 0x49, -+ 0x5f, 0x7b, 0xa8, 0xd2, 0x62, 0x2d, 0xa7, 0x39, 0x93, 0x48, 0xe7, 0x6b, -+ 0x23, 0xba, 0xd4, 0xe0, 0xc1, 0x29, 0x55, 0xc4, 0x34, 0xe3, 0xac, 0x25, -+ 0xa7, 0x15, 0xad, 0xab, 0xb3, 0xb7, 0x25, 0xca, 0x37, 0x88, 0x40, 0x2e, -+ 0x47, 0x6e, 0x92, 0x20, 0x09, 0x2e, 0x5a, 0xec, 0xf2, 0xfb, 0xb3, 0xa0, -+ 0x16, 0xb6, 0x93, 0xf2, 0xf5, 0x8b, 0xfe, 0xaf, 0x25, 0xee, 0x2e, 0x98, -+ 0x6c, 0x0a, 0xfe, 0xae, 0x0b, 0x57, 0xf5, 0x9f, 0x3c, 0x80, 0xe9, 0x8b, -+ 0xaf, 0x92, 0x8a, 0xad, 0xe7, 0xa0, 0xe4, 0xe6, 0x0a, 0xa0, 0xc7, 0x83, -+ 0xb5, 0x48, 0x58, 0x5f, 0x55, 0x9e, 0x9b, 0x27, 0xcd, 0x31, 0x1f, 0x3e, -+ 0x50, 0x5a, 0x91, 0xad, 0x21, 0x1b, 0x97, 0x5b, 0xe8, 0xfa, 0x29, 0x8a, -+ 0xa4, 0x17, 0xe8, 0xab, 0x87, 0x02, 0xd6, 0x18, 0x8c, 0x9f, 0x65, 0xb7, -+ 0x2a, 0xfa, 0xde, 0x5f, 0x77, 0x30, 0x6c, 0x04, 0x22, 0xe6, 0x58, 0x26, -+ 0x14, 0x0d, 0x9c, 0x41, 0x0a, 0x82, 0x77, 0xdb, 0x40, 0xa1, 0x58, 0xac, -+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb5, -+ 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, -+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, -+ 0x65, 0x64, 0x7e, 0x0a -+}; -+unsigned int hi_signed_2nd_len = 736; -+ -+unsigned char certificate_printable_der[] = { -+ 0x30, 0x82, 0x03, 0x39, 0x30, 0x82, 0x02, 0x21, 0xa0, 0x03, 0x02, 0x01, -+ 0x02, 0x02, 0x09, 0x00, 0xde, 0xf6, 0x22, 0xc4, 0xf2, 0xf1, 0x86, 0x02, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x0b, 0x05, 0x00, 0x30, 0x2a, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, -+ 0x04, 0x03, 0x13, 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, -+ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, -+ 0x43, 0x41, 0x20, 0x32, 0x20, 0x28, 0x62, 0x65, 0x74, 0x61, 0x29, 0x30, -+ 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x30, 0x33, 0x31, 0x31, 0x34, 0x31, -+ 0x39, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x37, 0x31, 0x30, 0x32, 0x35, -+ 0x31, 0x34, 0x31, 0x39, 0x32, 0x33, 0x5a, 0x30, 0x2f, 0x31, 0x2d, 0x30, -+ 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x52, 0x65, 0x64, 0x20, -+ 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, -+ 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, -+ 0x33, 0x20, 0x28, 0x62, 0x65, 0x74, 0x61, 0x29, 0x30, 0x82, 0x01, 0x22, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, -+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xbd, 0xda, 0xa1, 0xed, 0x8d, 0x8e, 0x15, -+ 0x5c, 0xf8, 0x01, 0x77, 0x48, 0x4a, 0x60, 0x96, 0xf9, 0x27, 0xfa, 0xe2, -+ 0xb1, 0x69, 0x0f, 0x51, 0x19, 0x52, 0x7e, 0xc4, 0x34, 0x8e, 0xe1, 0x9b, -+ 0x9c, 0xa4, 0xb1, 0x5c, 0xd6, 0x81, 0x98, 0x78, 0xfe, 0xa9, 0xe5, 0x0b, -+ 0x00, 0xba, 0x9c, 0x64, 0x7e, 0xc7, 0xcc, 0x72, 0xb1, 0x73, 0x4b, 0x11, -+ 0x07, 0x52, 0xf0, 0x20, 0x96, 0x8b, 0x99, 0x39, 0xde, 0xdb, 0xfa, 0x3d, -+ 0x45, 0xe2, 0x98, 0x7b, 0x0c, 0x41, 0xe4, 0x0c, 0xb5, 0x5d, 0x92, 0x74, -+ 0x39, 0x96, 0xe1, 0x97, 0x97, 0xa1, 0xad, 0x2e, 0xcc, 0xd0, 0x1b, 0x4d, -+ 0x9d, 0xbd, 0x3e, 0xa9, 0x36, 0x8e, 0xcc, 0xc7, 0x5f, 0x6a, 0x7d, 0x39, -+ 0x5e, 0x0b, 0x8d, 0xca, 0xe4, 0x83, 0xe9, 0x3b, 0x5c, 0x86, 0x47, 0xd4, -+ 0xba, 0x7d, 0x98, 0x26, 0xa1, 0xf4, 0xe8, 0x90, 0x6b, 0x0f, 0xf1, 0x6b, -+ 0x8c, 0xe3, 0xa2, 0x80, 0x3c, 0x96, 0xf1, 0x0a, 0xb6, 0x66, 0xc0, 0x4b, -+ 0x61, 0xf7, 0x74, 0xcd, 0xd3, 0x7b, 0x8e, 0x5e, 0x39, 0xda, 0x99, 0x20, -+ 0x33, 0x93, 0xd3, 0xf0, 0x7f, 0xad, 0x35, 0xe9, 0x88, 0x8d, 0x9c, 0xbf, -+ 0x65, 0xf1, 0x47, 0x02, 0xf9, 0x7c, 0xed, 0x27, 0x5f, 0x4a, 0x65, 0x3c, -+ 0xcf, 0x5f, 0x0e, 0x88, 0x95, 0x74, 0xde, 0xfb, 0x9e, 0x2e, 0x91, 0x9b, -+ 0x45, 0x37, 0xc8, 0x85, 0xff, 0xe3, 0x41, 0x70, 0xfe, 0xd5, 0xef, 0x0e, -+ 0x82, 0x22, 0x08, 0xb7, 0x3b, 0x44, 0x3e, 0xdc, 0x5b, 0x7f, 0xba, 0xbf, -+ 0xe6, 0x58, 0x9d, 0x02, 0x6e, 0x75, 0xbf, 0x50, 0xec, 0xcf, 0x3f, 0xa5, -+ 0x91, 0x0a, 0xe2, 0x59, 0x2c, 0xc3, 0xe7, 0x05, 0x03, 0xe8, 0xf2, 0x6f, -+ 0x2a, 0x04, 0x68, 0x9a, 0x31, 0x32, 0x8f, 0x04, 0x35, 0xcd, 0x1f, 0x34, -+ 0xcc, 0x4f, 0x79, 0x5a, 0x99, 0x8d, 0x9d, 0x5c, 0xf5, 0x02, 0x03, 0x01, -+ 0x00, 0x01, 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, -+ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, -+ 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1d, 0x06, -+ 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x65, 0xc5, 0xbe, 0xca, -+ 0xe6, 0x59, 0x6a, 0xfd, 0x6c, 0x71, 0xc4, 0xa7, 0x98, 0xc6, 0x25, 0x8d, -+ 0x7b, 0x67, 0x05, 0xd0, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, -+ 0x18, 0x30, 0x16, 0x80, 0x14, 0x81, 0xf8, 0xee, 0x47, 0x5c, 0x3e, 0xed, -+ 0xfb, 0xce, 0xa5, 0x84, 0xbe, 0xd7, 0xae, 0xdb, 0xd3, 0x7d, 0x64, 0xb3, -+ 0x2a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, -+ 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x66, 0x1e, 0x3d, -+ 0x1d, 0x53, 0x33, 0xde, 0x4e, 0xc7, 0xc4, 0xf4, 0xdf, 0xda, 0x18, 0x19, -+ 0x8a, 0xa9, 0xff, 0xe2, 0x63, 0x2b, 0xbe, 0xf2, 0x61, 0x63, 0xe2, 0xf6, -+ 0xed, 0x47, 0x1a, 0x71, 0x02, 0xec, 0x2a, 0xef, 0x89, 0x77, 0xe3, 0xfd, -+ 0x86, 0x69, 0xf1, 0x3f, 0x0d, 0xf9, 0x6e, 0xf9, 0x3b, 0xad, 0x26, 0x47, -+ 0xb7, 0xf2, 0x0d, 0xad, 0x23, 0xa3, 0x67, 0x3b, 0xcb, 0x6d, 0x9e, 0x03, -+ 0x0f, 0xbc, 0x69, 0x73, 0x9f, 0xd4, 0xa5, 0x0f, 0x6f, 0xf8, 0xab, 0x4d, -+ 0x36, 0xd1, 0xe0, 0xe0, 0x5d, 0x20, 0x43, 0x90, 0xc4, 0x65, 0x61, 0x93, -+ 0xe2, 0x0f, 0x51, 0x59, 0x0a, 0xf7, 0x88, 0x70, 0x57, 0xb9, 0x04, 0xa9, -+ 0x32, 0x57, 0x9c, 0xb3, 0x57, 0x38, 0x8b, 0x8e, 0x46, 0xc8, 0x32, 0x6c, -+ 0xb4, 0xf3, 0x96, 0x7f, 0x4b, 0xf0, 0x88, 0xf9, 0x7f, 0xe2, 0x71, 0xe1, -+ 0x8b, 0xe2, 0x14, 0xf1, 0x4b, 0x25, 0x00, 0x48, 0x1c, 0x7e, 0xe5, 0x8d, -+ 0x65, 0x2d, 0xeb, 0x72, 0x4f, 0x92, 0x44, 0xf3, 0xe6, 0xe0, 0xd0, 0xdf, -+ 0x85, 0xa8, 0x13, 0x4a, 0xfb, 0x99, 0xca, 0x14, 0x2c, 0x97, 0x80, 0x93, -+ 0x27, 0xd3, 0x20, 0xf8, 0x6d, 0x29, 0x28, 0x2c, 0xb9, 0x77, 0xea, 0xb1, -+ 0x63, 0xbd, 0x7d, 0x53, 0xfd, 0x4a, 0x62, 0x64, 0x0b, 0x98, 0xa8, 0xae, -+ 0x11, 0xfc, 0x6e, 0x8d, 0x63, 0xd4, 0x15, 0x55, 0xc6, 0x4c, 0x74, 0xf5, -+ 0x5f, 0xa0, 0xb9, 0x2c, 0x2d, 0x9a, 0x7a, 0x87, 0x6e, 0xf0, 0x5e, 0x25, -+ 0xed, 0xfc, 0xd8, 0xc4, 0x34, 0x33, 0x32, 0xad, 0x01, 0xd4, 0x4b, 0x49, -+ 0x51, 0xc2, 0x07, 0x7f, 0x90, 0x6d, 0xea, 0xf5, 0x4c, 0x41, 0x71, 0x64, -+ 0xeb, 0x1f, 0x29, 0xa3, 0x1f, 0x64, 0xa2, 0x1e, 0x0e, 0x6f, 0xa1, 0x67, -+ 0x99, 0x8d, 0x98, 0x1c, 0xb8, 0x53, 0x9d, 0x30, 0x1d, 0xae, 0x32, 0x56, -+ 0xd2 -+}; -+unsigned int certificate_printable_der_len = 829; diff --git a/SOURCES/0196-EFI-console-Do-not-set-colorstate-until-the-first-te.patch b/SOURCES/0196-EFI-console-Do-not-set-colorstate-until-the-first-te.patch new file mode 100644 index 0000000..ade6aae --- /dev/null +++ b/SOURCES/0196-EFI-console-Do-not-set-colorstate-until-the-first-te.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 12:43:48 +0100 +Subject: [PATCH] EFI: console: Do not set colorstate until the first text + output + +GRUB_MOD_INIT(normal) does an unconditional: + +grub_env_set ("color_normal", "light-gray/black"); + +which triggers a grub_term_setcolorstate() call. The original version +of the "efi/console: Do not set text-mode until we actually need it" patch: +https://lists.gnu.org/archive/html/grub-devel/2018-03/msg00125.html + +Protected against this by caching the requested state in +grub_console_setcolorstate () and then only applying it when the first +text output actually happens. During refactoring to move the +grub_console_setcolorstate () up higher in the grub-core/term/efi/console.c +file the code to cache the color-state + bail early was accidentally +dropped. + +Restore the cache the color-state + bail early behavior from the original. + +Cc: Javier Martinez Canillas +Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") +Signed-off-by: Hans de Goede +--- + grub-core/term/efi/console.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c +index 2f1ae85ba7..c44b2ac318 100644 +--- a/grub-core/term/efi/console.c ++++ b/grub-core/term/efi/console.c +@@ -82,6 +82,16 @@ grub_console_setcolorstate (struct grub_term_output *term + { + grub_efi_simple_text_output_interface_t *o; + ++ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) ++ { ++ /* ++ * Cache colorstate changes before the first text-output, this avoids ++ * "color_normal" environment writes causing a switch to textmode. ++ */ ++ text_colorstate = state; ++ return; ++ } ++ + if (grub_efi_is_finished) + return; + diff --git a/SOURCES/0196-appended-signatures-documentation.patch b/SOURCES/0196-appended-signatures-documentation.patch deleted file mode 100644 index 864cfa3..0000000 --- a/SOURCES/0196-appended-signatures-documentation.patch +++ /dev/null @@ -1,341 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 1 Oct 2020 13:02:09 +1000 -Subject: [PATCH] appended signatures: documentation - -This explains how appended signatures can be used to form part of -a secure boot chain, and documents the commands and variables -introduced. - -Signed-off-by: Daniel Axtens ---- - docs/grub.texi | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 182 insertions(+), 17 deletions(-) - -diff --git a/docs/grub.texi b/docs/grub.texi -index afbde7c1f7b..4816be85611 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -3214,6 +3214,7 @@ These variables have special meaning to GRUB. - - @menu - * biosnum:: -+* check_appended_signatures:: - * check_signatures:: - * chosen:: - * cmdpath:: -@@ -3273,11 +3274,18 @@ For an alternative approach which also changes BIOS drive mappings for the - chain-loaded system, @pxref{drivemap}. - - -+@node check_appended_signatures -+@subsection check_appended_signatures -+ -+This variable controls whether GRUB enforces appended signature validation on -+certain loaded files. @xref{Using appended signatures}. -+ -+ - @node check_signatures - @subsection check_signatures - --This variable controls whether GRUB enforces digital signature --validation on loaded files. @xref{Using digital signatures}. -+This variable controls whether GRUB enforces GPG-style digital signature -+validation on loaded files. @xref{Using GPG-style digital signatures}. - - @node chosen - @subsection chosen -@@ -3994,6 +4002,7 @@ you forget a command, you can run the command @command{help} - * date:: Display or set current date and time - * devicetree:: Load a device tree blob - * distrust:: Remove a pubkey from trusted keys -+* distrust_certificate:: Remove a certificate from the list of trusted certificates - * drivemap:: Map a drive to another - * echo:: Display a line of text - * eval:: Evaluate agruments as GRUB commands -@@ -4010,6 +4019,7 @@ you forget a command, you can run the command @command{help} - * keystatus:: Check key modifier status - * linux:: Load a Linux kernel - * linux16:: Load a Linux kernel (16-bit mode) -+* list_certificates:: List trusted certificates - * list_env:: List variables in environment block - * list_trusted:: List trusted public keys - * load_env:: Load variables from environment block -@@ -4047,8 +4057,10 @@ you forget a command, you can run the command @command{help} - * test:: Check file types and compare values - * true:: Do nothing, successfully - * trust:: Add public key to list of trusted keys -+* trust_certificate:: Add an x509 certificate to the list of trusted certificates - * unset:: Unset an environment variable - @comment * vbeinfo:: List available video modes -+* verify_appended:: Verify appended digital signature - * verify_detached:: Verify detached digital signature - * videoinfo:: List available video modes - @comment * xen_*:: Xen boot commands for AArch64 -@@ -4376,9 +4388,28 @@ These keys are used to validate signatures when environment variable - @code{check_signatures} is set to @code{enforce} - (@pxref{check_signatures}), and by some invocations of - @command{verify_detached} (@pxref{verify_detached}). @xref{Using --digital signatures}, for more information. -+GPG-style digital signatures}, for more information. - @end deffn - -+ -+@node distrust_certificate -+@subsection distrust_certificate -+ -+@deffn Command distrust_certificate cert_number -+Remove the x509 certificate numbered @var{cert_number} from GRUB's keyring of -+trusted x509 certificates for verifying appended signatures. -+ -+@var{cert_number} is the certificate number as listed by -+@command{list_certificates} (@pxref{list_certificates}). -+ -+These certificates are used to validate appended signatures when environment -+variable @code{check_appended_signatures} is set to @code{enforce} or -+@code{forced} (@pxref{check_appended_signatures}), and by -+@command{verify_appended} (@pxref{verify_appended}). See -+@xref{Using appended signatures} for more information. -+@end deffn -+ -+ - @node drivemap - @subsection drivemap - -@@ -4636,6 +4667,21 @@ This command is only available on x86 systems. - @end deffn - - -+@node list_certificates -+@subsection list_certificates -+ -+@deffn Command list_certificates -+List all x509 certificates trusted by GRUB for validating appended signatures. -+The output is a numbered list of certificates, showing the certificate's serial -+number and Common Name. -+ -+The certificate number can be used as an argument to -+@command{distrust_certificate} (@pxref{distrust_certificate}). -+ -+See @xref{Using appended signatures} for more information. -+@end deffn -+ -+ - @node list_env - @subsection list_env - -@@ -4655,7 +4701,7 @@ The output is in GPG's v4 key fingerprint format (i.e., the output of - @code{gpg --fingerprint}). The least significant four bytes (last - eight hexadecimal digits) can be used as an argument to - @command{distrust} (@pxref{distrust}). --@xref{Using digital signatures}, for more information about uses for -+@xref{Using GPG-style digital signatures}, for more information about uses for - these keys. - @end deffn - -@@ -4690,8 +4736,13 @@ When used with care, @option{--skip-sig} and the whitelist enable an - administrator to configure a system to boot only signed - configurations, but to allow the user to select from among multiple - configurations, and to enable ``one-shot'' boot attempts and --``savedefault'' behavior. @xref{Using digital signatures}, for more -+``savedefault'' behavior. @xref{Using GPG-style digital signatures}, for more - information. -+ -+Extra care should be taken when combining this command with appended signatures -+(@pxref{Using appended signatures}), as this file is not validated by an -+appended signature and could set @code{check_appended_signatures=no} if GRUB is -+not in @pxref{Lockdown} mode. - @end deffn - - -@@ -4987,7 +5038,7 @@ read. It is possible to modify a digitally signed environment block - file from within GRUB using this command, such that its signature will - no longer be valid on subsequent boots. Care should be taken in such - advanced configurations to avoid rendering the system --unbootable. @xref{Using digital signatures}, for more information. -+unbootable. @xref{Using GPG-style digital signatures}, for more information. - @end deffn - - -@@ -5387,11 +5438,32 @@ signatures when environment variable @code{check_signatures} is set to - must itself be properly signed. The @option{--skip-sig} option can be - used to disable signature-checking when reading @var{pubkey_file} - itself. It is expected that @option{--skip-sig} is useful for testing --and manual booting. @xref{Using digital signatures}, for more -+and manual booting. @xref{Using GPG-style digital signatures}, for more - information. - @end deffn - - -+@node trust_certificate -+@subsection trust_certificate -+ -+@deffn Command trust_certificate x509_certificate -+Read an DER-formatted x509 certificate from the file @var{x509_certificate} -+and add it to GRUB's internal list of trusted x509 certificates. These -+certificates are used to validate appended signatures when the environment -+variable @code{check_appended_signatures} is set to @code{enforce} or -+@code{forced}. -+ -+Note that if @code{check_appended_signatures} is set to @code{enforce} or -+@code{forced} when @command{trust_certificate} is executed, then -+@var{x509_certificate} must itself bear an appended signature. (It is not -+sufficient that @var{x509_certificate} be signed by a trusted certificate -+according to the x509 rules: grub does not include support for validating -+signatures within x509 certificates themselves.) -+ -+See @xref{Using appended signatures} for more information. -+@end deffn -+ -+ - @node unset - @subsection unset - -@@ -5410,6 +5482,18 @@ only on PC BIOS platforms. - @end deffn - @end ignore - -+@node verify_appended -+@subsection verify_appended -+ -+@deffn Command verify_appended file -+Verifies an appended signature on @var{file} against the trusted certificates -+known to GRUB (See @pxref{list_certificates}, @pxref{trust_certificate}, and -+@pxref{distrust_certificate}). -+ -+Exit code @code{$?} is set to 0 if the signature validates -+successfully. If validation fails, it is set to a non-zero value. -+See @xref{Using appended signatures}, for more information. -+@end deffn - - @node verify_detached - @subsection verify_detached -@@ -5428,7 +5512,7 @@ tried. - - Exit code @code{$?} is set to 0 if the signature validates - successfully. If validation fails, it is set to a non-zero value. --@xref{Using digital signatures}, for more information. -+@xref{Using GPG-style digital signatures}, for more information. - @end deffn - - @node videoinfo -@@ -5811,13 +5895,14 @@ environment variables and commands are listed in the same order. - @chapter Security - - @menu --* Authentication and authorisation:: Users and access control --* Using digital signatures:: Booting digitally signed code --* UEFI secure boot and shim:: Booting digitally signed PE files --* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation --* Measured Boot:: Measuring boot components --* Lockdown:: Lockdown when booting on a secure setup --* Signing GRUB itself:: Ensuring the integrity of the GRUB core image -+* Authentication and authorisation:: Users and access control -+* Using GPG-style digital signatures:: Booting digitally signed code -+* Using appended signatures:: An alternative approach to booting digitally signed code -+* UEFI secure boot and shim:: Booting digitally signed PE files -+* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation -+* Measured Boot:: Measuring boot components -+* Lockdown:: Lockdown when booting on a secure setup -+* Signing GRUB itself:: Ensuring the integrity of the GRUB core image - @end menu - - @node Authentication and authorisation -@@ -5891,8 +5976,8 @@ generating configuration files with authentication. You can use - adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} - commands. - --@node Using digital signatures --@section Using digital signatures in GRUB -+@node Using GPG-style digital signatures -+@section Using GPG-style digital signatures in GRUB - - GRUB's @file{core.img} can optionally provide enforcement that all files - subsequently read from disk are covered by a valid digital signature. -@@ -5985,6 +6070,86 @@ or BIOS) configuration to cause the machine to boot from a different - (attacker-controlled) device. GRUB is at best only one link in a - secure boot chain. - -+@node Using appended signatures -+@section Using appended signatures in GRUB -+ -+GRUB supports verifying Linux-style 'appended signatures' for secure boot. -+Appended signatures are PKCS#7 messages containing a signature over the -+contents of a file, plus some metadata, appended to the end of a file. A file -+with an appended signature ends with the magic string: -+ -+@example -+~Module signature appended~\n -+@end example -+ -+where @code{\n} represents the line-feed character, @code{0x0a}. -+ -+Certificates can be managed at boot time using the @pxref{trust_certificate}, -+@pxref{distrust_certificate} and @pxref{list_certificates} commands. -+Certificates can also be built in to the core image using the @code{--x509} -+parameter to @command{grub-install} or @command{grub-mkimage}. -+ -+A file can be explictly verified using the @pxref{verify_appended} command. -+ -+Only signatures made with the SHA-256 or SHA-512 hash algorithm are supported, -+and only RSA signatures are supported. -+ -+A file can be signed with the @command{sign-file} utility supplied with the -+Linux kernel source. For example, if you have @code{signing.key} as the private -+key and @code{certificate.der} as the x509 certificate containing the public key: -+ -+@example -+sign-file SHA256 signing.key certificate.der vmlinux vmlinux.signed -+@end example -+ -+Enforcement of signature verification is controlled by the -+@code{check_appended_signatures} variable. -+ -+@itemize -+@item @samp{no}: no verification is performed. This is the default when GRUB -+ is not in @pxref{Lockdown} mode. -+@item @samp{enforce}: verification is performed. Verification can be disabled -+ by setting the variable back to @samp{no}. -+@item @samp{forced}: verification is performed and cannot be disabled. This is -+ set when GRUB is in Lockdown when the appendedsig module is loaded. -+@end itemize -+ -+Unlike GPG-style signatures, not all files loaded by GRUB are required to be -+signed. Once verification is turned on, the following file types will have -+appended signatures verified: -+ -+@itemize -+@item Linux kernels -+@item GRUB modules, except those built into the core image -+@item Any new certificate files to be trusted -+@end itemize -+ -+ACPI tables and Device Tree images will not be checked for appended signatures -+but must be verified by another mechanism such as GPG-style signatures before -+they will be loaded. -+ -+Unless lockdown mode is enabled, signature checking does @strong{not} -+stop an attacker with console access from dropping manually to the GRUB -+console and executing: -+ -+@example -+set check_appended_signatures=no -+@end example -+ -+Refer to the section on password-protecting GRUB (@pxref{Authentication -+and authorisation}) for more information on preventing this. -+ -+Additionally, unless lockdown mode is enabled: -+ -+@itemize -+@item Special care must be taken around the @command{loadenv} command, which -+ can be used to turn off @code{check_appended_signature}. -+ -+@item If the grub configuration file is loaded from the disk, anyone who can -+ modify the file on disk can turn off @code{check_appended_signature}. -+ Consider embedding the configuration into the core grub image. -+@end itemize -+ - @node UEFI secure boot and shim - @section UEFI secure boot and shim support - diff --git a/SOURCES/0197-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch b/SOURCES/0197-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch new file mode 100644 index 0000000..5fab5db --- /dev/null +++ b/SOURCES/0197-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 12:43:49 +0100 +Subject: [PATCH] EFI: console: Do not set cursor until the first text output + +To allow flickerfree boot the EFI console code does not call +grub_efi_set_text_mode (1) until some text is actually output. + +Depending on if the output text is because of an error loading +e.g. the .cfg file; or because of showing the menu the cursor needs +to be on or off when the first text is shown. + +So far the cursor was hardcoded to being on, but this is causing +drawing artifacts + slow drawing of the menu as reported here: +https://bugzilla.redhat.com/show_bug.cgi?id=1946969 + +Handle the cursorstate in the same way as the colorstate to fix this, +when no text has been output yet, just cache the cursorstate and +then use the last set value when the first text is output. + +Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") +Signed-off-by: Hans de Goede +--- + grub-core/term/efi/console.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c +index c44b2ac318..a3622e4fe5 100644 +--- a/grub-core/term/efi/console.c ++++ b/grub-core/term/efi/console.c +@@ -31,7 +31,15 @@ typedef enum { + } + grub_text_mode; + ++typedef enum { ++ GRUB_CURSOR_MODE_UNDEFINED = -1, ++ GRUB_CURSOR_MODE_OFF = 0, ++ GRUB_CURSUR_MODE_ON ++} ++grub_cursor_mode; ++ + static grub_text_mode text_mode = GRUB_TEXT_MODE_UNDEFINED; ++static grub_cursor_mode cursor_mode = GRUB_CURSOR_MODE_UNDEFINED; + static grub_term_color_state text_colorstate = GRUB_TERM_COLOR_UNDEFINED; + + static grub_uint32_t +@@ -119,8 +127,12 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), + { + grub_efi_simple_text_output_interface_t *o; + +- if (grub_efi_is_finished) +- return; ++ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) ++ { ++ /* Cache cursor changes before the first text-output */ ++ cursor_mode = on; ++ return; ++ } + + o = grub_efi_system_table->con_out; + efi_call_2 (o->enable_cursor, o, on); +@@ -143,7 +155,8 @@ grub_prepare_for_text_output (struct grub_term_output *term) + return GRUB_ERR_BAD_DEVICE; + } + +- grub_console_setcursor (term, 1); ++ if (cursor_mode != GRUB_CURSOR_MODE_UNDEFINED) ++ grub_console_setcursor (term, cursor_mode); + if (text_colorstate != GRUB_TERM_COLOR_UNDEFINED) + grub_console_setcolorstate (term, text_colorstate); + text_mode = GRUB_TEXT_MODE_AVAILABLE; diff --git a/SOURCES/0197-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch b/SOURCES/0197-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch deleted file mode 100644 index 40c3b3e..0000000 --- a/SOURCES/0197-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 28 Sep 2020 11:11:17 +1000 -Subject: [PATCH] ieee1275: enter lockdown based on /ibm,secure-boot - -If the 'ibm,secure-boot' property of the root node is 2 or greater, -enter lockdown. - -Signed-off-by: Daniel Axtens ---- - grub-core/Makefile.core.def | 1 + - grub-core/kern/ieee1275/init.c | 27 +++++++++++++++++++++++++++ - include/grub/lockdown.h | 3 ++- - docs/grub.texi | 4 ++-- - 4 files changed, 32 insertions(+), 3 deletions(-) - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 6bddc841b85..3f3459b2c70 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -323,6 +323,7 @@ kernel = { - powerpc_ieee1275 = kern/powerpc/cache.S; - powerpc_ieee1275 = kern/powerpc/dl.c; - powerpc_ieee1275 = kern/powerpc/compiler-rt.S; -+ powerpc_ieee1275 = kern/lockdown.c; - - sparc64_ieee1275 = kern/sparc64/cache.S; - sparc64_ieee1275 = kern/sparc64/dl.c; -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index 937c1bc44cb..fc7d9712729 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -44,6 +44,7 @@ - #ifdef __sparc__ - #include - #endif -+#include - - /* The minimal heap size we can live with. */ - #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) -@@ -271,6 +272,30 @@ grub_parse_cmdline (void) - } - } - -+static void -+grub_get_ieee1275_secure_boot (void) -+{ -+ grub_ieee1275_phandle_t root; -+ int rc; -+ grub_uint32_t is_sb; -+ -+ grub_ieee1275_finddevice ("/", &root); -+ -+ rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &is_sb, -+ sizeof (is_sb), 0); -+ -+ /* ibm,secure-boot: -+ * 0 - disabled -+ * 1 - audit -+ * 2 - enforce -+ * 3 - enforce + OS-specific behaviour -+ * -+ * We only support enforce. -+ */ -+ if (rc >= 0 && is_sb >= 2) -+ grub_lockdown (); -+} -+ - grub_addr_t grub_modbase; - - void -@@ -296,6 +321,8 @@ grub_machine_init (void) - #else - grub_install_get_time_ms (grub_rtc_get_time_ms); - #endif -+ -+ grub_get_ieee1275_secure_boot (); - } - - void -diff --git a/include/grub/lockdown.h b/include/grub/lockdown.h -index 40531fa823b..ebfee4bf06e 100644 ---- a/include/grub/lockdown.h -+++ b/include/grub/lockdown.h -@@ -24,7 +24,8 @@ - #define GRUB_LOCKDOWN_DISABLED 0 - #define GRUB_LOCKDOWN_ENABLED 1 - --#ifdef GRUB_MACHINE_EFI -+#if defined(GRUB_MACHINE_EFI) || \ -+ (defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)) - extern void - EXPORT_FUNC (grub_lockdown) (void); - extern int -diff --git a/docs/grub.texi b/docs/grub.texi -index 4816be85611..a4da9c2a1b9 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -6227,8 +6227,8 @@ Measured boot is currently only supported on EFI platforms. - @section Lockdown when booting on a secure setup - - The GRUB can be locked down when booted on a secure boot environment, for example --if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will --be restricted and some operations/commands cannot be executed. -+if UEFI or Power secure boot is enabled. On a locked down configuration, the -+GRUB will be restricted and some operations/commands cannot be executed. - - The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down. - Otherwise it does not exit. diff --git a/SOURCES/0198-Use-visual-indentation-in-config.h.in.patch b/SOURCES/0198-Use-visual-indentation-in-config.h.in.patch new file mode 100644 index 0000000..978eb07 --- /dev/null +++ b/SOURCES/0198-Use-visual-indentation-in-config.h.in.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Dec 2021 15:46:13 -0500 +Subject: [PATCH] Use visual indentation in config.h.in + +Signed-off-by: Robbie Harwood +(cherry picked from commit de8051f34de0aa55c921a510974e5bb27e39c17b) +[rharwood: GRUB_RPM_CONFIG presence] +--- + config.h.in | 58 +++++++++++++++++++++++++++++----------------------------- + 1 file changed, 29 insertions(+), 29 deletions(-) + +diff --git a/config.h.in b/config.h.in +index c80e3e0aba..f2ed0066ec 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -23,47 +23,47 @@ + #define MINILZO_CFG_SKIP_LZO1X_DECOMPRESS 1 + + #if defined (GRUB_BUILD) +-#undef ENABLE_NLS +-#define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ +-#define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ +-#if defined __APPLE__ +-# if defined __BIG_ENDIAN__ +-# define BUILD_WORDS_BIGENDIAN 1 +-# else +-# define BUILD_WORDS_BIGENDIAN 0 +-# endif +-#else +-#define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ +-#endif ++# undef ENABLE_NLS ++# define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ ++# define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ ++# if defined __APPLE__ ++# if defined __BIG_ENDIAN__ ++# define BUILD_WORDS_BIGENDIAN 1 ++# else ++# define BUILD_WORDS_BIGENDIAN 0 ++# endif ++# else /* !defined __APPLE__ */ ++# define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ ++# endif /* !defined __APPLE__ */ + #elif defined (GRUB_UTIL) || !defined (GRUB_MACHINE) +-#include +-#else +-#define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@ ++# include ++#else /* !defined GRUB_UTIL && defined GRUB_MACHINE */ ++# define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@ + /* Define if C symbols get an underscore after compilation. */ +-#define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ ++# define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ + /* Define it to one of __bss_start, edata and _edata. */ +-#define BSS_START_SYMBOL @BSS_START_SYMBOL@ ++# define BSS_START_SYMBOL @BSS_START_SYMBOL@ + /* Define it to either end or _end. */ +-#define END_SYMBOL @END_SYMBOL@ ++# define END_SYMBOL @END_SYMBOL@ + /* Name of package. */ +-#define PACKAGE "@PACKAGE@" ++# define PACKAGE "@PACKAGE@" + /* Version number of package. */ +-#define VERSION "@VERSION@" ++# define VERSION "@VERSION@" + /* Define to the full name and version of this package. */ +-#define PACKAGE_STRING "@PACKAGE_STRING@" ++# define PACKAGE_STRING "@PACKAGE_STRING@" + /* Define to the version of this package. */ +-#define PACKAGE_VERSION "@PACKAGE_VERSION@" ++# define PACKAGE_VERSION "@PACKAGE_VERSION@" + /* Define to the full name of this package. */ +-#define PACKAGE_NAME "@PACKAGE_NAME@" ++# define PACKAGE_NAME "@PACKAGE_NAME@" + /* Define to the address where bug reports for this package should be sent. */ +-#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" ++# define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +-#define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" +-#define GRUB_PLATFORM "@GRUB_PLATFORM@" +-#define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" ++# define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" ++# define GRUB_PLATFORM "@GRUB_PLATFORM@" ++# define GRUB_RPM_VERSION "@GRUB_RPM_VERSION@" + +-#define RE_ENABLE_I18N 1 ++# define RE_ENABLE_I18N 1 + +-#define _GNU_SOURCE 1 ++# define _GNU_SOURCE 1 + + #endif diff --git a/SOURCES/0198-ieee1275-drop-HEAP_MAX_ADDR-HEAP_MIN_SIZE.patch b/SOURCES/0198-ieee1275-drop-HEAP_MAX_ADDR-HEAP_MIN_SIZE.patch deleted file mode 100644 index 52fa9d2..0000000 --- a/SOURCES/0198-ieee1275-drop-HEAP_MAX_ADDR-HEAP_MIN_SIZE.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Wed, 14 Apr 2021 20:10:23 +1000 -Subject: [PATCH] ieee1275: drop HEAP_MAX_ADDR, HEAP_MIN_SIZE - -HEAP_MAX_ADDR is confusing. Currently it is set to 32MB, except -on ieee1275 on x86, where it is 64MB. - -There is a comment which purports to explain it: - -/* If possible, we will avoid claiming heap above this address, because it - seems to cause relocation problems with OSes that link at 4 MiB */ - -This doesn't make a lot of sense when the constants are well above 4MB -already. It was not always this way. Prior to -commit 7b5d0fe4440c ("Increase heap limit") in 2010, HEAP_MAX_SIZE and -HEAP_MAX_ADDR were indeed 4MB. However, when the constants were increased -the comment was left unchanged. - -It's been over a decade. It doesn't seem like we have problems with -claims over 4MB on powerpc or x86 ieee1275. (sparc does things completely -differently and never used the constant.) - -Drop the constant and the check. - -The only use of HEAP_MIN_SIZE was to potentially override the -HEAP_MAX_ADDR check. It is now unused. Remove it. - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/ieee1275/init.c | 17 ----------------- - 1 file changed, 17 deletions(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index fc7d9712729..0dcd114ce54 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -46,9 +46,6 @@ - #endif - #include - --/* The minimal heap size we can live with. */ --#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) -- - /* The maximum heap size we're going to claim */ - #ifdef __i386__ - #define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) -@@ -56,14 +53,6 @@ - #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) - #endif - --/* If possible, we will avoid claiming heap above this address, because it -- seems to cause relocation problems with OSes that link at 4 MiB */ --#ifdef __i386__ --#define HEAP_MAX_ADDR (unsigned long) (64 * 1024 * 1024) --#else --#define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024) --#endif -- - extern char _end[]; - - #ifdef __sparc__ -@@ -185,12 +174,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - if (*total + len > HEAP_MAX_SIZE) - len = HEAP_MAX_SIZE - *total; - -- /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */ -- if ((addr < HEAP_MAX_ADDR) && /* if it's too late, don't bother */ -- (addr + len > HEAP_MAX_ADDR) && /* if it wasn't available anyway, don't bother */ -- (*total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE)) /* only limit ourselves when we can afford to */ -- len = HEAP_MAX_ADDR - addr; -- - /* In theory, firmware should already prevent this from happening by not - listing our own image in /memory/available. The check below is intended - as a safeguard in case that doesn't happen. However, it doesn't protect diff --git a/SOURCES/0199-Where-present-ensure-config-util.h-precedes-config.h.patch b/SOURCES/0199-Where-present-ensure-config-util.h-precedes-config.h.patch new file mode 100644 index 0000000..22c2d9c --- /dev/null +++ b/SOURCES/0199-Where-present-ensure-config-util.h-precedes-config.h.patch @@ -0,0 +1,275 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 22 Feb 2022 16:57:54 -0500 +Subject: [PATCH] Where present, ensure config-util.h precedes config.h + +gnulib defines go in config-util.h, and we need to know whether to +provide duplicates in config.h or not. + +Signed-off-by: Robbie Harwood +(cherry picked from commit 46e82b28e1a75703d0424c7e13d009171310c6cd) +[rharwood: gensymlist isn't part of tarballs] +--- + grub-core/disk/host.c | 2 +- + grub-core/kern/emu/argp_common.c | 2 +- + grub-core/kern/emu/main.c | 2 +- + grub-core/osdep/aros/config.c | 2 +- + grub-core/osdep/basic/emunet.c | 2 +- + grub-core/osdep/basic/init.c | 2 +- + grub-core/osdep/haiku/getroot.c | 2 +- + grub-core/osdep/linux/emunet.c | 2 +- + grub-core/osdep/unix/config.c | 2 +- + grub-core/osdep/unix/cputime.c | 2 +- + grub-core/osdep/unix/dl.c | 2 +- + grub-core/osdep/unix/emuconsole.c | 2 +- + grub-core/osdep/unix/getroot.c | 2 +- + grub-core/osdep/windows/config.c | 2 +- + grub-core/osdep/windows/cputime.c | 2 +- + grub-core/osdep/windows/dl.c | 2 +- + grub-core/osdep/windows/emuconsole.c | 2 +- + grub-core/osdep/windows/init.c | 2 +- + 18 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c +index c151d225df..f34529f86a 100644 +--- a/grub-core/disk/host.c ++++ b/grub-core/disk/host.c +@@ -20,8 +20,8 @@ + /* When using the disk, make a reference to this module. Otherwise + the user will end up with a useless module :-). */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/kern/emu/argp_common.c b/grub-core/kern/emu/argp_common.c +index 1668858703..8cb4608c3d 100644 +--- a/grub-core/kern/emu/argp_common.c ++++ b/grub-core/kern/emu/argp_common.c +@@ -17,8 +17,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #pragma GCC diagnostic ignored "-Wmissing-prototypes" + #pragma GCC diagnostic ignored "-Wmissing-declarations" +diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c +index 55ea5a11cc..12277c34d2 100644 +--- a/grub-core/kern/emu/main.c ++++ b/grub-core/kern/emu/main.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/aros/config.c b/grub-core/osdep/aros/config.c +index c82d0ea8e7..55f5728efc 100644 +--- a/grub-core/osdep/aros/config.c ++++ b/grub-core/osdep/aros/config.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/basic/emunet.c b/grub-core/osdep/basic/emunet.c +index 6362e5cfbb..dbfd316d61 100644 +--- a/grub-core/osdep/basic/emunet.c ++++ b/grub-core/osdep/basic/emunet.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/basic/init.c b/grub-core/osdep/basic/init.c +index c54c710dbc..b104c7e162 100644 +--- a/grub-core/osdep/basic/init.c ++++ b/grub-core/osdep/basic/init.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/haiku/getroot.c b/grub-core/osdep/haiku/getroot.c +index 4e123c0903..927a1ebc94 100644 +--- a/grub-core/osdep/haiku/getroot.c ++++ b/grub-core/osdep/haiku/getroot.c +@@ -1,5 +1,5 @@ +-#include + #include ++#include + #include + #include + #include +diff --git a/grub-core/osdep/linux/emunet.c b/grub-core/osdep/linux/emunet.c +index 19b188f09e..d5a6417355 100644 +--- a/grub-core/osdep/linux/emunet.c ++++ b/grub-core/osdep/linux/emunet.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c +index 46a881530c..0ce0e309ac 100644 +--- a/grub-core/osdep/unix/config.c ++++ b/grub-core/osdep/unix/config.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/cputime.c b/grub-core/osdep/unix/cputime.c +index cff359a3b9..fb6ff55a1a 100644 +--- a/grub-core/osdep/unix/cputime.c ++++ b/grub-core/osdep/unix/cputime.c +@@ -1,5 +1,5 @@ +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/dl.c b/grub-core/osdep/unix/dl.c +index 562b101a28..99b189bc1c 100644 +--- a/grub-core/osdep/unix/dl.c ++++ b/grub-core/osdep/unix/dl.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/emuconsole.c b/grub-core/osdep/unix/emuconsole.c +index 7308798efe..cac159424d 100644 +--- a/grub-core/osdep/unix/emuconsole.c ++++ b/grub-core/osdep/unix/emuconsole.c +@@ -17,8 +17,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c +index 46d7116c6e..4f436284ce 100644 +--- a/grub-core/osdep/unix/getroot.c ++++ b/grub-core/osdep/unix/getroot.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/config.c b/grub-core/osdep/windows/config.c +index 928ab1a49b..2bb8a2fd88 100644 +--- a/grub-core/osdep/windows/config.c ++++ b/grub-core/osdep/windows/config.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/cputime.c b/grub-core/osdep/windows/cputime.c +index 3568aa2d35..5d06d79dd5 100644 +--- a/grub-core/osdep/windows/cputime.c ++++ b/grub-core/osdep/windows/cputime.c +@@ -1,5 +1,5 @@ +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/dl.c b/grub-core/osdep/windows/dl.c +index eec6a24ad7..8eab7057e4 100644 +--- a/grub-core/osdep/windows/dl.c ++++ b/grub-core/osdep/windows/dl.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/emuconsole.c b/grub-core/osdep/windows/emuconsole.c +index 4fb3693cc0..17a44de469 100644 +--- a/grub-core/osdep/windows/emuconsole.c ++++ b/grub-core/osdep/windows/emuconsole.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + + #include + #include +diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c +index 6297de6326..51a9647dde 100644 +--- a/grub-core/osdep/windows/init.c ++++ b/grub-core/osdep/windows/init.c +@@ -16,8 +16,8 @@ + * along with GRUB. If not, see . + */ + +-#include + #include ++#include + #include + #include + #include diff --git a/SOURCES/0199-ieee1275-claim-more-memory.patch b/SOURCES/0199-ieee1275-claim-more-memory.patch deleted file mode 100644 index 001a9df..0000000 --- a/SOURCES/0199-ieee1275-claim-more-memory.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Wed, 15 Apr 2020 23:28:29 +1000 -Subject: [PATCH] ieee1275: claim more memory - -On powerpc-ieee1275, we are running out of memory trying to verify -anything. This is because: - - - we have to load an entire file into memory to verify it. This is - extremely difficult to change with appended signatures. - - We only have 32MB of heap. - - Distro kernels are now often around 30MB. - -So we want to claim more memory from OpenFirmware for our heap. - -There are some complications: - - - The grub mm code isn't the only thing that will make claims on - memory from OpenFirmware: - - * PFW/SLOF will have claimed some for their own use. - - * The ieee1275 loader will try to find other bits of memory that we - haven't claimed to place the kernel and initrd when we go to boot. - - * Once we load Linux, it will also try to claim memory. It claims - memory without any reference to /memory/available, it just starts - at min(top of RMO, 768MB) and works down. So we need to avoid this - area. See arch/powerpc/kernel/prom_init.c as of v5.11. - - - The smallest amount of memory a ppc64 KVM guest can have is 256MB. - It doesn't work with distro kernels but can work with custom kernels. - We should maintain support for that. (ppc32 can boot with even less, - and we shouldn't break that either.) - - - Even if a VM has more memory, the memory OpenFirmware makes available - as Real Memory Area can be restricted. A freshly created LPAR on a - PowerVM machine is likely to have only 256MB available to OpenFirmware - even if it has many gigabytes of memory allocated. - -EFI systems will attempt to allocate 1/4th of the available memory, -clamped to between 1M and 1600M. That seems like a good sort of -approach, we just need to figure out if 1/4 is the right fraction -for us. - -We don't know in advance how big the kernel and initrd are going to be, -which makes figuring out how much memory we can take a bit tricky. - -To figure out how much memory we should leave unused, I looked at: - - - an Ubuntu 20.04.1 ppc64le pseries KVM guest: - vmlinux: ~30MB - initrd: ~50MB - - - a RHEL8.2 ppc64le pseries KVM guest: - vmlinux: ~30MB - initrd: ~30MB - -Ubuntu VMs struggle to boot with just 256MB under SLOF. -RHEL likewise has a higher minimum supported memory figure. -So lets first consider a distro kernel and 512MB of addressible memory. -(This is the default case for anything booting under PFW.) Say we lose -131MB to PFW (based on some tests). This leaves us 381MB. 1/4 of 381MB -is ~95MB. That should be enough to verify a 30MB vmlinux and should -leave plenty of space to load Linux and the initrd. - -If we consider 256MB of RMA under PFW, we have just 125MB remaining. 1/4 -of that is a smidge under 32MB, which gives us very poor odds of verifying -a distro-sized kernel. However, if we need 80MB just to put the kernel -and initrd in memory, we can't claim any more than 45MB anyway. So 1/4 -will do. We'll come back to this later. - -grub is always built as a 32-bit binary, even if it's loading a ppc64 -kernel. So we can't address memory beyond 4GB. This gives a natural cap -of 1GB for powerpc-ieee1275. - -Also apply this 1/4 approach to i386-ieee1275, but keep the 32MB cap. - -make check still works for both i386 and powerpc and I've booted -powerpc grub with this change under SLOF and PFW. - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/ieee1275/init.c | 81 +++++++++++++++++++++++++++++++++--------- - docs/grub-dev.texi | 6 ++-- - 2 files changed, 69 insertions(+), 18 deletions(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index 0dcd114ce54..c61d91a0285 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -46,11 +46,12 @@ - #endif - #include - --/* The maximum heap size we're going to claim */ -+/* The maximum heap size we're going to claim. Not used by sparc. -+ We allocate 1/4 of the available memory under 4G, up to this limit. */ - #ifdef __i386__ - #define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) --#else --#define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) -+#else // __powerpc__ -+#define HEAP_MAX_SIZE (unsigned long) (1 * 1024 * 1024 * 1024) - #endif - - extern char _end[]; -@@ -147,16 +148,45 @@ grub_claim_heap (void) - + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); - } - #else --/* Helper for grub_claim_heap. */ -+/* Helper for grub_claim_heap on powerpc. */ -+static int -+heap_size (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, -+ void *data) -+{ -+ grub_uint32_t total = *(grub_uint32_t *)data; -+ -+ if (type != GRUB_MEMORY_AVAILABLE) -+ return 0; -+ -+ /* Do not consider memory beyond 4GB */ -+ if (addr > 0xffffffffUL) -+ return 0; -+ -+ if (addr + len > 0xffffffffUL) -+ len = 0xffffffffUL - addr; -+ -+ total += len; -+ *(grub_uint32_t *)data = total; -+ -+ return 0; -+} -+ - static int - heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - void *data) - { -- unsigned long *total = data; -+ grub_uint32_t total = *(grub_uint32_t *)data; - - if (type != GRUB_MEMORY_AVAILABLE) - return 0; - -+ /* Do not consider memory beyond 4GB */ -+ if (addr > 0xffffffffUL) -+ return 0; -+ -+ if (addr + len > 0xffffffffUL) -+ len = 0xffffffffUL - addr; -+ - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) - { - if (addr + len <= 0x180000) -@@ -170,10 +200,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - } - len -= 1; /* Required for some firmware. */ - -- /* Never exceed HEAP_MAX_SIZE */ -- if (*total + len > HEAP_MAX_SIZE) -- len = HEAP_MAX_SIZE - *total; -- - /* In theory, firmware should already prevent this from happening by not - listing our own image in /memory/available. The check below is intended - as a safeguard in case that doesn't happen. However, it doesn't protect -@@ -185,6 +211,18 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - len = 0; - } - -+ /* If this block contains 0x30000000 (768MB), do not claim below that. -+ Linux likes to claim memory at min(RMO top, 768MB) and works down -+ without reference to /memory/available. */ -+ if ((addr < 0x30000000) && ((addr + len) > 0x30000000)) -+ { -+ len = len - (0x30000000 - addr); -+ addr = 0x30000000; -+ } -+ -+ if (len > total) -+ len = total; -+ - if (len) - { - grub_err_t err; -@@ -193,10 +231,12 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - if (err) - return err; - grub_mm_init_region ((void *) (grub_addr_t) addr, len); -+ total -= len; - } - -- *total += len; -- if (*total >= HEAP_MAX_SIZE) -+ *(grub_uint32_t *)data = total; -+ -+ if (total == 0) - return 1; - - return 0; -@@ -205,13 +245,22 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - static void - grub_claim_heap (void) - { -- unsigned long total = 0; -+ grub_uint32_t total = 0; - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) -- heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, -- 1, &total); -- else -- grub_machine_mmap_iterate (heap_init, &total); -+ { -+ heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, -+ 1, &total); -+ return; -+ } -+ -+ grub_machine_mmap_iterate (heap_size, &total); -+ -+ total = total / 4; -+ if (total > HEAP_MAX_SIZE) -+ total = HEAP_MAX_SIZE; -+ -+ grub_machine_mmap_iterate (heap_init, &total); - } - #endif - -diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi -index 19f708ee662..90083772c8a 100644 ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -1047,7 +1047,9 @@ space is limited to 4GiB. GRUB allocates pages from EFI for its heap, at most - 1.6 GiB. - - On i386-ieee1275 and powerpc-ieee1275 GRUB uses same stack as IEEE1275. --It allocates at most 32MiB for its heap. -+ -+On i386-ieee1275, GRUB allocates at most 32MiB for its heap. On -+powerpc-ieee1275, GRUB allocates up to 1GiB. - - On sparc64-ieee1275 stack is 256KiB and heap is 2MiB. - -@@ -1075,7 +1077,7 @@ In short: - @item i386-qemu @tab 60 KiB @tab < 4 GiB - @item *-efi @tab ? @tab < 1.6 GiB - @item i386-ieee1275 @tab ? @tab < 32 MiB --@item powerpc-ieee1275 @tab ? @tab < 32 MiB -+@item powerpc-ieee1275 @tab ? @tab < 1 GiB - @item sparc64-ieee1275 @tab 256KiB @tab 2 MiB - @item arm-uboot @tab 256KiB @tab 2 MiB - @item mips(el)-qemu_mips @tab 2MiB @tab 253 MiB diff --git a/SOURCES/0200-Drop-gnulib-fix-base64.patch.patch b/SOURCES/0200-Drop-gnulib-fix-base64.patch.patch new file mode 100644 index 0000000..054e476 --- /dev/null +++ b/SOURCES/0200-Drop-gnulib-fix-base64.patch.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 28 Oct 2021 15:07:50 -0400 +Subject: [PATCH] Drop gnulib fix-base64.patch + +Originally added in 9fbdec2f6b4fa8b549daa4d49134d1fe89d95ef9 and +subsequently modified in 552c9fd08122a3036c724ce96dfe68aa2f75705f, +fix-base64.patch handled two problems we have using gnulib, which are +exerciesd by the base64 module but not directly caused by it. + +First, grub2 defines its own bool type, while gnulib expects the +equivalent of stdbool.h to be present. Rather than patching gnulib, +instead use gnulib's stdbool module to provide a bool type if needed. +(Suggested by Simon Josefsson.) + +Second, our config.h doesn't always inherit config-util.h, which is +where gnulib-related options like _GL_ATTRIBUTE_CONST end up. +fix-base64.h worked around this by defining the attribute away, but this +workaround is better placed in config.h itself, not a gnulib patch. + +Signed-off-by: Robbie Harwood +(cherry picked from commit 54fd1c3301dd15f6b6212c12887265e8a6cbc076) +--- + grub-core/lib/posix_wrap/sys/types.h | 7 +++---- + grub-core/lib/xzembed/xz.h | 5 +---- + bootstrap.conf | 3 ++- + conf/Makefile.extra-dist | 1 - + config.h.in | 4 ++++ + grub-core/lib/gnulib-patches/fix-base64.patch | 21 --------------------- + 6 files changed, 10 insertions(+), 31 deletions(-) + delete mode 100644 grub-core/lib/gnulib-patches/fix-base64.patch + +diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h +index f63412c8da..2f3e865495 100644 +--- a/grub-core/lib/posix_wrap/sys/types.h ++++ b/grub-core/lib/posix_wrap/sys/types.h +@@ -23,11 +23,10 @@ + + #include + ++/* Provided by gnulib if not present. */ ++#include ++ + typedef grub_ssize_t ssize_t; +-#ifndef GRUB_POSIX_BOOL_DEFINED +-typedef enum { false = 0, true = 1 } bool; +-#define GRUB_POSIX_BOOL_DEFINED 1 +-#endif + + typedef grub_uint8_t uint8_t; + typedef grub_uint16_t uint16_t; +diff --git a/grub-core/lib/xzembed/xz.h b/grub-core/lib/xzembed/xz.h +index f7b32d8003..d1417039aa 100644 +--- a/grub-core/lib/xzembed/xz.h ++++ b/grub-core/lib/xzembed/xz.h +@@ -29,10 +29,7 @@ + #include + #include + #include +- +-#ifndef GRUB_POSIX_BOOL_DEFINED +-typedef enum { false = 0, true = 1 } bool; +-#endif ++#include + + /** + * enum xz_ret - Return codes +diff --git a/bootstrap.conf b/bootstrap.conf +index 52d4af44be..645e3a459c 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -35,6 +35,7 @@ gnulib_modules=" + realloc-gnu + regex + save-cwd ++ stdbool + " + + gnulib_tool_option_extras="\ +@@ -79,7 +80,7 @@ cp -a INSTALL INSTALL.grub + + bootstrap_post_import_hook () { + set -e +- for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ ++ for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ + fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do + patch -d grub-core/lib/gnulib -p2 \ + < "grub-core/lib/gnulib-patches/$patchname.patch" +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index ad235de7fc..f4791dc6ca 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -31,7 +31,6 @@ EXTRA_DIST += grub-core/gensymlist.sh + EXTRA_DIST += grub-core/genemuinit.sh + EXTRA_DIST += grub-core/genemuinitheader.sh + +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch +diff --git a/config.h.in b/config.h.in +index f2ed0066ec..9c7b4afaaa 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -66,4 +66,8 @@ + + # define _GNU_SOURCE 1 + ++# ifndef _GL_INLINE_HEADER_BEGIN ++# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) ++# endif /* !_GL_INLINE_HEADER_BEGIN */ ++ + #endif +diff --git a/grub-core/lib/gnulib-patches/fix-base64.patch b/grub-core/lib/gnulib-patches/fix-base64.patch +deleted file mode 100644 +index 985db12797..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-base64.patch ++++ /dev/null +@@ -1,21 +0,0 @@ +-diff --git a/lib/base64.h b/lib/base64.h +-index 9cd0183b8..185a2afa1 100644 +---- a/lib/base64.h +-+++ b/lib/base64.h +-@@ -21,8 +21,14 @@ +- /* Get size_t. */ +- # include +- +--/* Get bool. */ +--# include +-+#ifndef GRUB_POSIX_BOOL_DEFINED +-+typedef enum { false = 0, true = 1 } bool; +-+#define GRUB_POSIX_BOOL_DEFINED 1 +-+#endif +-+ +-+#ifndef _GL_ATTRIBUTE_CONST +-+# define _GL_ATTRIBUTE_CONST /* empty */ +-+#endif +- +- # ifdef __cplusplus +- extern "C" { diff --git a/SOURCES/0200-ieee1275-request-memory-with-ibm-client-architecture.patch b/SOURCES/0200-ieee1275-request-memory-with-ibm-client-architecture.patch deleted file mode 100644 index 6e6c1f0..0000000 --- a/SOURCES/0200-ieee1275-request-memory-with-ibm-client-architecture.patch +++ /dev/null @@ -1,268 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 16 Apr 2021 11:48:46 +1000 -Subject: [PATCH] ieee1275: request memory with ibm,client-architecture-support - -On PowerVM, the first time we boot a Linux partition, we may only get -256MB of real memory area, even if the partition has more memory. - -This isn't really enough. Fortunately, the Power Architecture Platform -Reference (PAPR) defines a method we can call to ask for more memory. -This is part of the broad and powerful ibm,client-architecture-support -(CAS) method. - -CAS can do an enormous amount of things on a PAPR platform: as well as -asking for memory, you can set the supported processor level, the interrupt -controller, hash vs radix mmu, and so on. We want to touch as little of -this as possible because we don't want to step on the toes of the future OS. - -If: - - - we are running under what we think is PowerVM (compatible property of / - begins with "IBM"), and - - - the full amount of RMA is less than 512MB (as determined by the reg - property of /memory) - -then call CAS as follows: (refer to the Linux on Power Architecture -Reference, LoPAR, which is public, at B.5.2.3): - - - Use the "any" PVR value and supply 2 option vectors. - - - Set option vector 1 (PowerPC Server Processor Architecture Level) - to "ignore". - - - Set option vector 2 with default or Linux-like options, including a - min-rma-size of 512MB. - -This will cause a CAS reboot and the partition will restart with 512MB -of RMA. Grub will notice the 512MB and not call CAS again. - -(A partition can be configured with only 256MB of memory, which would -mean this request couldn't be satisfied, but PFW refuses to load with -only 256MB of memory, so it's a bit moot. SLOF will run fine with 256MB, -but we will never call CAS under qemu/SLOF because /compatible won't -begin with "IBM".) - -One of the first things Linux does while still running under OpenFirmware -is to call CAS with a much fuller set of options (including asking for -512MB of memory). This includes a much more restrictive set of PVR values -and processor support levels, and this will induce another reboot. On this -reboot grub will again notice the higher RMA, and not call CAS. We will get -to Linux, Linux will call CAS but because the values are now set for Linux -this will not induce another CAS reboot and we will finally boot. - -On all subsequent boots, everything will be configured with 512MB of RMA -and all the settings Linux likes, so there will be no further CAS reboots. - -(phyp is super sticky with the RMA size - it persists even on cold boots. -So if you've ever booted Linux in a partition, you'll probably never have -grub call CAS. It'll only ever fire the first time a partition loads grub, -or if you deliberately lower the amount of memory your partition has below -512MB.) - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/ieee1275/cmain.c | 3 + - grub-core/kern/ieee1275/init.c | 144 ++++++++++++++++++++++++++++++++++++++- - include/grub/ieee1275/ieee1275.h | 8 ++- - 3 files changed, 152 insertions(+), 3 deletions(-) - -diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c -index 04df9d2c667..6435628ec57 100644 ---- a/grub-core/kern/ieee1275/cmain.c -+++ b/grub-core/kern/ieee1275/cmain.c -@@ -127,6 +127,9 @@ grub_ieee1275_find_options (void) - break; - } - } -+ -+ if (grub_strncmp (tmp, "IBM,", 4) == 0) -+ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY); - } - - if (is_smartfirmware) -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index c61d91a0285..9704715c837 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -242,6 +242,135 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - return 0; - } - -+/* How much memory does OF believe it has? (regardless of whether -+ it's accessible or not) */ -+static grub_err_t -+grub_ieee1275_total_mem (grub_uint64_t *total) -+{ -+ grub_ieee1275_phandle_t root; -+ grub_ieee1275_phandle_t memory; -+ grub_uint32_t reg[4]; -+ grub_ssize_t reg_size; -+ grub_uint32_t address_cells = 1; -+ grub_uint32_t size_cells = 1; -+ grub_uint64_t size; -+ -+ /* If we fail to get to the end, report 0. */ -+ *total = 0; -+ -+ /* Determine the format of each entry in `reg'. */ -+ grub_ieee1275_finddevice ("/", &root); -+ grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells, -+ sizeof address_cells, 0); -+ grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells, -+ sizeof size_cells, 0); -+ -+ if (size_cells > address_cells) -+ address_cells = size_cells; -+ -+ /* Load `/memory/reg'. */ -+ if (grub_ieee1275_finddevice ("/memory", &memory)) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, -+ "couldn't find /memory node"); -+ if (grub_ieee1275_get_integer_property (memory, "reg", reg, -+ sizeof reg, ®_size)) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, -+ "couldn't examine /memory/reg property"); -+ if (reg_size < 0 || (grub_size_t) reg_size > sizeof (reg)) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, -+ "/memory response buffer exceeded"); -+ -+ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS)) -+ { -+ address_cells = 1; -+ size_cells = 1; -+ } -+ -+ /* Decode only the size */ -+ size = reg[address_cells]; -+ if (size_cells == 2) -+ size = (size << 32) | reg[address_cells + 1]; -+ -+ *total = size; -+ -+ return grub_errno; -+} -+ -+/* Based on linux - arch/powerpc/kernel/prom_init.c */ -+struct option_vector2 { -+ grub_uint8_t byte1; -+ grub_uint16_t reserved; -+ grub_uint32_t real_base; -+ grub_uint32_t real_size; -+ grub_uint32_t virt_base; -+ grub_uint32_t virt_size; -+ grub_uint32_t load_base; -+ grub_uint32_t min_rma; -+ grub_uint32_t min_load; -+ grub_uint8_t min_rma_percent; -+ grub_uint8_t max_pft_size; -+} __attribute__((packed)); -+ -+struct pvr_entry { -+ grub_uint32_t mask; -+ grub_uint32_t entry; -+}; -+ -+struct cas_vector { -+ struct { -+ struct pvr_entry terminal; -+ } pvr_list; -+ grub_uint8_t num_vecs; -+ grub_uint8_t vec1_size; -+ grub_uint8_t vec1; -+ grub_uint8_t vec2_size; -+ struct option_vector2 vec2; -+} __attribute__((packed)); -+ -+/* Call ibm,client-architecture-support to try to get more RMA. -+ We ask for 512MB which should be enough to verify a distro kernel. -+ We ignore most errors: if we don't succeed we'll proceed with whatever -+ memory we have. */ -+static void -+grub_ieee1275_ibm_cas (void) -+{ -+ int rc; -+ grub_ieee1275_ihandle_t root; -+ struct cas_args { -+ struct grub_ieee1275_common_hdr common; -+ grub_ieee1275_cell_t method; -+ grub_ieee1275_ihandle_t ihandle; -+ grub_ieee1275_cell_t cas_addr; -+ grub_ieee1275_cell_t result; -+ } args; -+ struct cas_vector vector = { -+ .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ -+ .num_vecs = 2 - 1, -+ .vec1_size = 0, -+ .vec1 = 0x80, /* ignore */ -+ .vec2_size = 1 + sizeof(struct option_vector2) - 2, -+ .vec2 = { -+ 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48 -+ }, -+ }; -+ -+ INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); -+ args.method = (grub_ieee1275_cell_t)"ibm,client-architecture-support"; -+ rc = grub_ieee1275_open("/", &root); -+ if (rc) { -+ grub_error (GRUB_ERR_IO, "could not open root when trying to call CAS"); -+ return; -+ } -+ args.ihandle = root; -+ args.cas_addr = (grub_ieee1275_cell_t)&vector; -+ -+ grub_printf("Calling ibm,client-architecture-support..."); -+ IEEE1275_CALL_ENTRY_FN (&args); -+ grub_printf("done\n"); -+ -+ grub_ieee1275_close(root); -+} -+ - static void - grub_claim_heap (void) - { -@@ -249,11 +378,22 @@ grub_claim_heap (void) - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) - { -- heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, -- 1, &total); -+ heap_init (GRUB_IEEE1275_STATIC_HEAP_START, -+ GRUB_IEEE1275_STATIC_HEAP_LEN, 1, &total); - return; - } - -+ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY)) -+ { -+ grub_uint64_t rma_size; -+ grub_err_t err; -+ -+ err = grub_ieee1275_total_mem (&rma_size); -+ /* if we have an error, don't call CAS, just hope for the best */ -+ if (!err && rma_size < (512 * 1024 * 1024)) -+ grub_ieee1275_ibm_cas(); -+ } -+ - grub_machine_mmap_iterate (heap_size, &total); - - total = total / 4; -diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h -index b5a1d49bbc3..e0a6c2ce1e6 100644 ---- a/include/grub/ieee1275/ieee1275.h -+++ b/include/grub/ieee1275/ieee1275.h -@@ -149,7 +149,13 @@ enum grub_ieee1275_flag - - GRUB_IEEE1275_FLAG_RAW_DEVNAMES, - -- GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT -+ GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT, -+ -+ /* On PFW, the first time we boot a Linux partition, we may only get 256MB -+ of real memory area, even if the partition has more memory. Set this flag -+ if we think we're running under PFW. Then, if this flag is set, and the -+ RMA is only 256MB in size, try asking for more with CAS. */ -+ GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY, - }; - - extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); diff --git a/SOURCES/0201-Drop-gnulib-no-abort.patch.patch b/SOURCES/0201-Drop-gnulib-no-abort.patch.patch new file mode 100644 index 0000000..a12789f --- /dev/null +++ b/SOURCES/0201-Drop-gnulib-no-abort.patch.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 5 Jan 2022 16:42:11 -0500 +Subject: [PATCH] Drop gnulib no-abort.patch + +Originally added in db7337a3d353a817ffe9eb4a3702120527100be9, this +patched out all relevant invocations of abort() in gnulib. While it was +not documented why at the time, testing suggests that there's no abort() +implementation available for gnulib to use. + +gnulib's position is that the use of abort() is correct here, since it +happens when input violates a "shall" from POSIX. Additionally, the +code in question is probably not reachable. Since abort() is more +friendly to user-space, they prefer to make no change, so we can just +carry a define instead. (Suggested by Paul Eggert.) + +Signed-off-by: Robbie Harwood +(cherry picked from commit 5137c8eb3ec11c3217acea1a93a3f88f3fa4cbca) +--- + bootstrap.conf | 2 +- + conf/Makefile.extra-dist | 1 - + config.h.in | 3 +++ + grub-core/lib/gnulib-patches/no-abort.patch | 26 -------------------------- + 4 files changed, 4 insertions(+), 28 deletions(-) + delete mode 100644 grub-core/lib/gnulib-patches/no-abort.patch + +diff --git a/bootstrap.conf b/bootstrap.conf +index 645e3a459c..71ce943c7d 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -81,7 +81,7 @@ cp -a INSTALL INSTALL.grub + bootstrap_post_import_hook () { + set -e + for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ +- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do ++ fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width; do + patch -d grub-core/lib/gnulib -p2 \ + < "grub-core/lib/gnulib-patches/$patchname.patch" + done +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index f4791dc6ca..5eef708338 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -38,7 +38,6 @@ EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/no-abort.patch + + EXTRA_DIST += grub-core/lib/libgcrypt + EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic +diff --git a/config.h.in b/config.h.in +index 9c7b4afaaa..c3134309c6 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -68,6 +68,9 @@ + + # ifndef _GL_INLINE_HEADER_BEGIN + # define _GL_ATTRIBUTE_CONST __attribute__ ((const)) ++ ++/* We don't have an abort() for gnulib to call in regexp. */ ++# define abort __builtin_unreachable + # endif /* !_GL_INLINE_HEADER_BEGIN */ + + #endif +diff --git a/grub-core/lib/gnulib-patches/no-abort.patch b/grub-core/lib/gnulib-patches/no-abort.patch +deleted file mode 100644 +index e469c4762e..0000000000 +--- a/grub-core/lib/gnulib-patches/no-abort.patch ++++ /dev/null +@@ -1,26 +0,0 @@ +-diff --git a/lib/regcomp.c b/lib/regcomp.c +-index cc85f35ac..de45ebb5c 100644 +---- a/lib/regcomp.c +-+++ b/lib/regcomp.c +-@@ -528,9 +528,9 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, +- to this routine. If we are given anything else, or if other regex +- code generates an invalid error code, then the program has a bug. +- Dump core so we can fix it. */ +-- abort (); +-- +-- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); +-+ msg = gettext ("unknown regexp error"); +-+ else +-+ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); +- +- msg_size = strlen (msg) + 1; /* Includes the null. */ +- +-@@ -1136,7 +1136,7 @@ optimize_utf8 (re_dfa_t *dfa) +- } +- break; +- default: +-- abort (); +-+ break; +- } +- +- if (mb_chars || has_period) diff --git a/SOURCES/0201-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch b/SOURCES/0201-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch deleted file mode 100644 index a237a21..0000000 --- a/SOURCES/0201-appendedsig-x509-Also-handle-the-Extended-Key-Usage-.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Sat, 8 May 2021 02:27:58 +0200 -Subject: [PATCH] appendedsig/x509: Also handle the Extended Key Usage - extension - -Red Hat certificates have both Key Usage and Extended Key Usage extensions -present, but the appended signatures x509 parser doesn't handle the latter -and so buils due finding an unrecognised critical extension: - -Error loading initial key: -../../grub-core/commands/appendedsig/x509.c:780:Unhandled critical x509 extension with OID 2.5.29.37 - -Fix this by also parsing the Extended Key Usage extension and handle it by -verifying that the certificate has a single purpose, that is code signing. - -Signed-off-by: Javier Martinez Canillas -Signed-off-by: Daniel Axtens ---- - grub-core/commands/appendedsig/x509.c | 94 ++++++++++++++++++++++++++++++- - grub-core/tests/appended_signature_test.c | 29 +++++++++- - grub-core/tests/appended_signatures.h | 81 ++++++++++++++++++++++++++ - 3 files changed, 201 insertions(+), 3 deletions(-) - -diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c -index 2b38b3670a2..42ec65c54aa 100644 ---- a/grub-core/commands/appendedsig/x509.c -+++ b/grub-core/commands/appendedsig/x509.c -@@ -47,6 +47,12 @@ const char *keyUsage_oid = "2.5.29.15"; - */ - const char *basicConstraints_oid = "2.5.29.19"; - -+/* -+ * RFC 5280 4.2.1.12 Extended Key Usage -+ */ -+const char *extendedKeyUsage_oid = "2.5.29.37"; -+const char *codeSigningUsage_oid = "1.3.6.1.5.5.7.3.3"; -+ - /* - * RFC 3279 2.3.1 - * -@@ -637,6 +643,77 @@ cleanup: - return err; - } - -+/* -+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId -+ * -+ * KeyPurposeId ::= OBJECT IDENTIFIER -+ */ -+static grub_err_t -+verify_extended_key_usage (grub_uint8_t * value, int value_size) -+{ -+ asn1_node extendedasn; -+ int result, count; -+ grub_err_t err = GRUB_ERR_NONE; -+ char usage[MAX_OID_LEN]; -+ int usage_size = sizeof (usage); -+ -+ result = -+ asn1_create_element (_gnutls_pkix_asn, "PKIX1.ExtKeyUsageSyntax", -+ &extendedasn); -+ if (result != ASN1_SUCCESS) -+ { -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ "Could not create ASN.1 structure for Extended Key Usage"); -+ } -+ -+ result = asn1_der_decoding2 (&extendedasn, value, &value_size, -+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error parsing DER for Extended Key Usage: %s", -+ asn1_error); -+ goto cleanup; -+ } -+ -+ /* -+ * If EKUs are present, there must be exactly 1 and it must be a -+ * codeSigning usage. -+ */ -+ result = asn1_number_of_elements(extendedasn, "", &count); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error counting number of Extended Key Usages: %s", -+ asn1_strerror (result)); -+ goto cleanup; -+ } -+ -+ result = asn1_read_value (extendedasn, "?1", usage, &usage_size); -+ if (result != ASN1_SUCCESS) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Error reading Extended Key Usage: %s", -+ asn1_strerror (result)); -+ goto cleanup; -+ } -+ -+ if (grub_strncmp (codeSigningUsage_oid, usage, usage_size) != 0) -+ { -+ err = -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unexpected Extended Key Usage OID, got: %s", -+ usage); -+ goto cleanup; -+ } -+ -+cleanup: -+ asn1_delete_structure (&extendedasn); -+ return err; -+} - - /* - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension -@@ -660,7 +737,7 @@ verify_extensions (asn1_node cert) - { - int result; - int ext, num_extensions = 0; -- int usage_present = 0, constraints_present = 0; -+ int usage_present = 0, constraints_present = 0, extended_usage_present = 0; - char *oid_path, *critical_path, *value_path; - char extnID[MAX_OID_LEN]; - int extnID_size; -@@ -754,6 +831,15 @@ verify_extensions (asn1_node cert) - } - constraints_present++; - } -+ else if (grub_strncmp (extendedKeyUsage_oid, extnID, extnID_size) == 0) -+ { -+ err = verify_extended_key_usage (value, value_size); -+ if (err != GRUB_ERR_NONE) -+ { -+ goto cleanup_value; -+ } -+ extended_usage_present++; -+ } - else if (grub_strncmp ("TRUE", critical, critical_size) == 0) - { - /* -@@ -785,6 +871,12 @@ verify_extensions (asn1_node cert) - "Unexpected number of basic constraints extensions - expected 1, got %d", - constraints_present); - } -+ if (extended_usage_present > 1) -+ { -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "Unexpected number of Extended Key Usage extensions - expected 0 or 1, got %d", -+ extended_usage_present); -+ } - return GRUB_ERR_NONE; - - cleanup_value: -diff --git a/grub-core/tests/appended_signature_test.c b/grub-core/tests/appended_signature_test.c -index 88a485200d8..dbba0616621 100644 ---- a/grub-core/tests/appended_signature_test.c -+++ b/grub-core/tests/appended_signature_test.c -@@ -111,6 +111,22 @@ static struct grub_procfs_entry certificate_printable_der_entry = { - .get_contents = get_certificate_printable_der - }; - -+static char * -+get_certificate_eku_der (grub_size_t * sz) -+{ -+ char *ret; -+ *sz = certificate_eku_der_len; -+ ret = grub_malloc (*sz); -+ if (ret) -+ grub_memcpy (ret, certificate_eku_der, *sz); -+ return ret; -+} -+ -+static struct grub_procfs_entry certificate_eku_der_entry = { -+ .name = "certificate_eku.der", -+ .get_contents = get_certificate_eku_der -+}; -+ - - static void - do_verify (const char *f, int is_valid) -@@ -149,6 +165,7 @@ appended_signature_test (void) - char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL }; - char *trust_args_printable[] = { (char *) "(proc)/certificate_printable.der", - NULL }; -+ char *trust_args_eku[] = { (char *) "(proc)/certificate_eku.der", NULL }; - char *distrust_args[] = { (char *) "1", NULL }; - char *distrust2_args[] = { (char *) "2", NULL }; - grub_err_t err; -@@ -157,6 +174,7 @@ appended_signature_test (void) - grub_procfs_register ("certificate2.der", &certificate2_der_entry); - grub_procfs_register ("certificate_printable.der", - &certificate_printable_der_entry); -+ grub_procfs_register ("certificate_eku.der", &certificate_eku_der_entry); - - cmd_trust = grub_command_find ("trust_certificate"); - if (!cmd_trust) -@@ -266,16 +284,23 @@ appended_signature_test (void) - - /* - * Lastly, check a certificate that uses printableString rather than -- * utf8String loads properly. -+ * utf8String loads properly, and that a certificate with an appropriate -+ * extended key usage loads. - */ - err = (cmd_trust->func) (cmd_trust, 1, trust_args_printable); - grub_test_assert (err == GRUB_ERR_NONE, -- "distrusting printable certificate failed: %d: %s", -+ "trusting printable certificate failed: %d: %s", -+ grub_errno, grub_errmsg); -+ -+ err = (cmd_trust->func) (cmd_trust, 1, trust_args_eku); -+ grub_test_assert (err == GRUB_ERR_NONE, -+ "trusting certificate with extended key usage failed: %d: %s", - grub_errno, grub_errmsg); - - grub_procfs_unregister (&certificate_der_entry); - grub_procfs_unregister (&certificate2_der_entry); - grub_procfs_unregister (&certificate_printable_der_entry); -+ grub_procfs_unregister (&certificate_eku_der_entry); - } - - GRUB_FUNCTIONAL_TEST (appended_signature_test, appended_signature_test); -diff --git a/grub-core/tests/appended_signatures.h b/grub-core/tests/appended_signatures.h -index aa3dc6278e3..2e5ebd7d8bd 100644 ---- a/grub-core/tests/appended_signatures.h -+++ b/grub-core/tests/appended_signatures.h -@@ -555,3 +555,84 @@ unsigned char certificate_printable_der[] = { - 0xd2 - }; - unsigned int certificate_printable_der_len = 829; -+ -+unsigned char certificate_eku_der[] = { -+ 0x30, 0x82, 0x03, 0x90, 0x30, 0x82, 0x02, 0x78, 0xa0, 0x03, 0x02, 0x01, -+ 0x02, 0x02, 0x09, 0x00, 0xd3, 0x9c, 0x41, 0x33, 0xdd, 0x6b, 0x5f, 0x45, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x0b, 0x05, 0x00, 0x30, 0x47, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, -+ 0x04, 0x03, 0x0c, 0x18, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, -+ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, -+ 0x43, 0x41, 0x20, 0x36, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2a, 0x86, -+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x13, 0x73, 0x65, 0x63, -+ 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, -+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, -+ 0x31, 0x35, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x33, -+ 0x38, 0x30, 0x31, 0x31, 0x37, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, -+ 0x30, 0x4e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, -+ 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, -+ 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, -+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x36, 0x30, 0x32, 0x31, 0x22, 0x30, 0x20, -+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, -+ 0x13, 0x73, 0x65, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, -+ 0x64, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, -+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, -+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, -+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x6f, 0xbb, 0x92, 0x77, 0xd7, 0x15, -+ 0xef, 0x88, 0x80, 0x88, 0xc0, 0xe7, 0x89, 0xeb, 0x35, 0x76, 0xf4, 0x85, -+ 0x05, 0x0f, 0x19, 0xe4, 0x5f, 0x25, 0xdd, 0xc1, 0xa2, 0xe5, 0x5c, 0x06, -+ 0xfb, 0xf1, 0x06, 0xb5, 0x65, 0x45, 0xcb, 0xbd, 0x19, 0x33, 0x54, 0xb5, -+ 0x1a, 0xcd, 0xe4, 0xa8, 0x35, 0x2a, 0xfe, 0x9c, 0x53, 0xf4, 0xc6, 0x76, -+ 0xdb, 0x1f, 0x8a, 0xd4, 0x7b, 0x18, 0x11, 0xaf, 0xa3, 0x90, 0xd4, 0xdd, -+ 0x4d, 0xd5, 0x42, 0xcc, 0x14, 0x9a, 0x64, 0x6b, 0xc0, 0x7f, 0xaa, 0x1c, -+ 0x94, 0x47, 0x4d, 0x79, 0xbd, 0x57, 0x9a, 0xbf, 0x99, 0x4e, 0x96, 0xa9, -+ 0x31, 0x2c, 0xa9, 0xe7, 0x14, 0x65, 0x86, 0xc8, 0xac, 0x79, 0x5e, 0x78, -+ 0xa4, 0x3c, 0x00, 0x24, 0xd3, 0xf7, 0xe1, 0xf5, 0x12, 0xad, 0xa0, 0x29, -+ 0xe5, 0xfe, 0x80, 0xae, 0xf8, 0xaa, 0x60, 0x36, 0xe7, 0xe8, 0x94, 0xcb, -+ 0xe9, 0xd1, 0xcc, 0x0b, 0x4d, 0xf7, 0xde, 0xeb, 0x52, 0xd2, 0x73, 0x09, -+ 0x28, 0xdf, 0x48, 0x99, 0x53, 0x9f, 0xc5, 0x9a, 0xd4, 0x36, 0xa3, 0xc6, -+ 0x5e, 0x8d, 0xbe, 0xd5, 0xdc, 0x76, 0xb4, 0x74, 0xb8, 0x26, 0x18, 0x27, -+ 0xfb, 0xf2, 0xfb, 0xd0, 0x9b, 0x3d, 0x7f, 0x10, 0xe2, 0xab, 0x44, 0xc7, -+ 0x88, 0x7f, 0xb4, 0x3d, 0x3e, 0xa3, 0xff, 0x6d, 0x06, 0x4b, 0x3e, 0x55, -+ 0xb2, 0x84, 0xf4, 0xad, 0x54, 0x88, 0x81, 0xc3, 0x9c, 0xf8, 0xb6, 0x68, -+ 0x96, 0x38, 0x8b, 0xcd, 0x90, 0x6d, 0x25, 0x4b, 0xbf, 0x0c, 0x44, 0x90, -+ 0xa5, 0x5b, 0x98, 0xd0, 0x40, 0x2f, 0xbb, 0x0d, 0xa8, 0x4b, 0x8a, 0x62, -+ 0x82, 0x46, 0x46, 0x18, 0x38, 0xae, 0x82, 0x07, 0xd0, 0xb4, 0x2f, 0x16, -+ 0x79, 0x55, 0x9f, 0x1b, 0xc5, 0x08, 0x6d, 0x85, 0xdf, 0x3f, 0xa9, 0x9b, -+ 0x4b, 0xc6, 0x28, 0xd3, 0x58, 0x72, 0x3d, 0x37, 0x11, 0x02, 0x03, 0x01, -+ 0x00, 0x01, 0xa3, 0x78, 0x30, 0x76, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, -+ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, -+ 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, -+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, -+ 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, -+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6c, -+ 0xe4, 0x6c, 0x27, 0xaa, 0xcd, 0x0d, 0x4b, 0x74, 0x21, 0xa4, 0xf6, 0x5f, -+ 0x87, 0xb5, 0x31, 0xfe, 0x10, 0xbb, 0xa7, 0x30, 0x1f, 0x06, 0x03, 0x55, -+ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xe8, 0x6a, 0x1c, 0xab, -+ 0x2c, 0x48, 0xf9, 0x60, 0x36, 0xa2, 0xf0, 0x7b, 0x8e, 0xd2, 0x9d, 0xb4, -+ 0x2a, 0x28, 0x98, 0xc8, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, -+ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, -+ 0x55, 0x34, 0xe2, 0xfa, 0xf6, 0x89, 0x86, 0xad, 0x92, 0x21, 0xec, 0xb9, -+ 0x54, 0x0e, 0x18, 0x47, 0x0d, 0x1b, 0xa7, 0x58, 0xad, 0x69, 0xe4, 0xef, -+ 0x3b, 0xe6, 0x8d, 0xdd, 0xda, 0x0c, 0x45, 0xf6, 0xe8, 0x96, 0xa4, 0x29, -+ 0x0f, 0xbb, 0xcf, 0x16, 0xae, 0x93, 0xd0, 0xcb, 0x2a, 0x26, 0x1a, 0x7b, -+ 0xfc, 0x51, 0x22, 0x76, 0x98, 0x31, 0xa7, 0x0f, 0x29, 0x35, 0x79, 0xbf, -+ 0xe2, 0x4f, 0x0f, 0x14, 0xf5, 0x1f, 0xcb, 0xbf, 0x87, 0x65, 0x13, 0x32, -+ 0xa3, 0x19, 0x4a, 0xd1, 0x3f, 0x45, 0xd4, 0x4b, 0xe2, 0x00, 0x26, 0xa9, -+ 0x3e, 0xd7, 0xa5, 0x37, 0x9f, 0xf5, 0xad, 0x61, 0xe2, 0x40, 0xa9, 0x74, -+ 0x24, 0x53, 0xf2, 0x78, 0xeb, 0x10, 0x9b, 0x2c, 0x27, 0x88, 0x46, 0xcb, -+ 0xe4, 0x60, 0xca, 0xf5, 0x06, 0x24, 0x40, 0x2a, 0x97, 0x3a, 0xcc, 0xd0, -+ 0x81, 0xb1, 0x15, 0xa3, 0x4f, 0xd0, 0x2b, 0x4f, 0xca, 0x6e, 0xaa, 0x24, -+ 0x31, 0xb3, 0xac, 0xa6, 0x75, 0x05, 0xfe, 0x8a, 0xf4, 0x41, 0xc4, 0x06, -+ 0x8a, 0xc7, 0x0a, 0x83, 0x4e, 0x49, 0xd4, 0x3f, 0x83, 0x50, 0xec, 0x57, -+ 0x04, 0x97, 0x14, 0x49, 0xf5, 0xe1, 0xb1, 0x7a, 0x9c, 0x09, 0x4f, 0x61, -+ 0x87, 0xc3, 0x97, 0x22, 0x17, 0xc2, 0xeb, 0xcc, 0x32, 0x81, 0x31, 0x21, -+ 0x3f, 0x10, 0x57, 0x5b, 0x43, 0xbe, 0xcd, 0x68, 0x82, 0xbe, 0xe5, 0xc1, -+ 0x65, 0x94, 0x7e, 0xc2, 0x34, 0x76, 0x2b, 0xcf, 0x89, 0x3c, 0x2b, 0x81, -+ 0x23, 0x72, 0x95, 0xcf, 0xc9, 0x67, 0x19, 0x2a, 0xd5, 0x5c, 0xca, 0xa3, -+ 0x46, 0xbd, 0x48, 0x06, 0x0b, 0xa6, 0xa3, 0x96, 0x50, 0x28, 0xc7, 0x7e, -+ 0xcf, 0x62, 0xf2, 0xfa, 0xc4, 0xf2, 0x53, 0xe3, 0xc9, 0xe8, 0x2e, 0xdd, -+ 0x29, 0x37, 0x07, 0x47, 0xff, 0xff, 0x8a, 0x32, 0xbd, 0xa2, 0xb7, 0x21, -+ 0x89, 0xa0, 0x55, 0xf7 -+}; -+unsigned int certificate_eku_der_len = 916; diff --git a/SOURCES/0202-Update-gnulib-version-and-drop-most-gnulib-patches.patch b/SOURCES/0202-Update-gnulib-version-and-drop-most-gnulib-patches.patch new file mode 100644 index 0000000..c2c50f1 --- /dev/null +++ b/SOURCES/0202-Update-gnulib-version-and-drop-most-gnulib-patches.patch @@ -0,0 +1,832 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Dec 2021 15:07:50 -0500 +Subject: [PATCH] Update gnulib version and drop most gnulib patches + +In addition to the changes carried in our gnulib patches, several +Coverity and code hygiene fixes that were previously downstream are also +included in this 3-year gnulib increment. + +Unfortunately, fix-width.patch is retained. + +Bump minimum autoconf version from 2.63 to 2.64 and automake from 1.11 +to 1.14, as required by gnulib. + +Sync bootstrap script itself with gnulib. + +Update regexp module for new dynarray dependency. + +Fix various new warnings. + +Signed-off-by: Robbie Harwood +(cherry picked from commit deb18ff931c3133c2aa536a92bd92e50d6615303) +[rharwood: backport around requirements in INSTALL] +--- + configure.ac | 2 +- + grub-core/Makefile.core.def | 3 + + grub-core/disk/luks2.c | 4 +- + grub-core/lib/posix_wrap/limits.h | 6 +- + include/grub/compiler.h | 4 +- + include/grub/list.h | 2 +- + INSTALL | 2 +- + bootstrap | 291 ++++++++++++--------- + bootstrap.conf | 22 +- + conf/Makefile.extra-dist | 6 - + config.h.in | 68 +++++ + grub-core/lib/gnulib-patches/fix-null-deref.patch | 13 - + .../lib/gnulib-patches/fix-null-state-deref.patch | 12 - + .../gnulib-patches/fix-regcomp-uninit-token.patch | 15 -- + .../gnulib-patches/fix-regexec-null-deref.patch | 12 - + .../lib/gnulib-patches/fix-uninit-structure.patch | 11 - + .../lib/gnulib-patches/fix-unused-value.patch | 14 - + 17 files changed, 262 insertions(+), 225 deletions(-) + delete mode 100644 grub-core/lib/gnulib-patches/fix-null-deref.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-null-state-deref.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-uninit-structure.patch + delete mode 100644 grub-core/lib/gnulib-patches/fix-unused-value.patch + +diff --git a/configure.ac b/configure.ac +index 40c4338bce..79f45ef1e1 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -49,7 +49,7 @@ AC_CANONICAL_TARGET + program_prefix="${save_program_prefix}" + + AM_INIT_AUTOMAKE([1.11]) +-AC_PREREQ(2.63) ++AC_PREREQ(2.64) + AC_CONFIG_SRCDIR([include/grub/dl.h]) + AC_CONFIG_HEADER([config-util.h]) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 08ac0fb15f..ec1ec5083b 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -762,6 +762,9 @@ module = { + name = regexp; + common = commands/regexp.c; + common = commands/wildcard.c; ++ common = lib/gnulib/malloc/dynarray_finalize.c; ++ common = lib/gnulib/malloc/dynarray_emplace_enlarge.c; ++ common = lib/gnulib/malloc/dynarray_resize.c; + common = lib/gnulib/regex.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; +diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c +index 371a53b837..c917a5f91e 100644 +--- a/grub-core/disk/luks2.c ++++ b/grub-core/disk/luks2.c +@@ -389,7 +389,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key, + { + grub_uint8_t candidate_digest[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN], salt[GRUB_CRYPTODISK_MAX_KEYLEN]; +- grub_size_t saltlen = sizeof (salt), digestlen = sizeof (digest); ++ idx_t saltlen = sizeof (salt), digestlen = sizeof (digest); + const gcry_md_spec_t *hash; + gcry_err_code_t gcry_ret; + +@@ -428,7 +428,7 @@ luks2_decrypt_key (grub_uint8_t *out_key, + grub_uint8_t area_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t *split_key = NULL; +- grub_size_t saltlen = sizeof (salt); ++ idx_t saltlen = sizeof (salt); + char cipher[32], *p; + const gcry_md_spec_t *hash; + gcry_err_code_t gcry_ret; +diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h +index 591dbf3289..4be7b40806 100644 +--- a/grub-core/lib/posix_wrap/limits.h ++++ b/grub-core/lib/posix_wrap/limits.h +@@ -25,7 +25,11 @@ + #define USHRT_MAX GRUB_USHRT_MAX + #define UINT_MAX GRUB_UINT_MAX + #define ULONG_MAX GRUB_ULONG_MAX +-#define SIZE_MAX GRUB_SIZE_MAX ++ ++/* gnulib also defines this type */ ++#ifndef SIZE_MAX ++# define SIZE_MAX GRUB_SIZE_MAX ++#endif + + #define SCHAR_MIN GRUB_SCHAR_MIN + #define SCHAR_MAX GRUB_SCHAR_MAX +diff --git a/include/grub/compiler.h b/include/grub/compiler.h +index ebafec6895..441a9eca07 100644 +--- a/include/grub/compiler.h ++++ b/include/grub/compiler.h +@@ -30,10 +30,10 @@ + + /* Does this compiler support compile-time error attributes? */ + #if GNUC_PREREQ(4,3) +-# define ATTRIBUTE_ERROR(msg) \ ++# define GRUB_ATTRIBUTE_ERROR(msg) \ + __attribute__ ((__error__ (msg))) + #else +-# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) ++# define GRUB_ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) + #endif + + #if GNUC_PREREQ(4,4) +diff --git a/include/grub/list.h b/include/grub/list.h +index b13acb9624..21f4b4b44a 100644 +--- a/include/grub/list.h ++++ b/include/grub/list.h +@@ -40,7 +40,7 @@ void EXPORT_FUNC(grub_list_remove) (grub_list_t item); + + static inline void * + grub_bad_type_cast_real (int line, const char *file) +- ATTRIBUTE_ERROR ("bad type cast between incompatible grub types"); ++ GRUB_ATTRIBUTE_ERROR ("bad type cast between incompatible grub types"); + + static inline void * + grub_bad_type_cast_real (int line, const char *file) +diff --git a/INSTALL b/INSTALL +index 79a0af7d93..ee9f536f76 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -42,7 +42,7 @@ If you use a development snapshot or want to hack on GRUB you may + need the following. + + * Python 2.6 or later +-* Autoconf 2.63 or later ++* Autoconf 2.64 or later + * Automake 1.11 or later + + Prerequisites for make-check: +diff --git a/bootstrap b/bootstrap +index 5b08e7e2d4..dc2238f4ad 100755 +--- a/bootstrap ++++ b/bootstrap +@@ -1,10 +1,10 @@ + #! /bin/sh + # Print a version string. +-scriptversion=2019-01-04.17; # UTC ++scriptversion=2022-01-26.05; # UTC + + # Bootstrap this package from checked-out sources. + +-# Copyright (C) 2003-2019 Free Software Foundation, Inc. ++# Copyright (C) 2003-2022 Free Software Foundation, Inc. + + # This program is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -47,7 +47,7 @@ PERL="${PERL-perl}" + + me=$0 + +-default_gnulib_url=git://git.sv.gnu.org/gnulib ++default_gnulib_url=https://git.savannah.gnu.org/git/gnulib.git + + usage() { + cat </dev/null) ++if test -z "$package"; then ++ package=$(sed -n "$extract_package_name" configure.ac) \ ++ || die 'cannot find package name in configure.ac' ++fi + gnulib_name=lib$package + + build_aux=build-aux +@@ -290,6 +313,116 @@ find_tool () + eval "export $find_tool_envvar" + } + ++# Strip blank and comment lines to leave significant entries. ++gitignore_entries() { ++ sed '/^#/d; /^$/d' "$@" ++} ++ ++# If $STR is not already on a line by itself in $FILE, insert it at the start. ++# Entries are inserted at the start of the ignore list to ensure existing ++# entries starting with ! are not overridden. Such entries support ++# whitelisting exceptions after a more generic blacklist pattern. ++insert_if_absent() { ++ file=$1 ++ str=$2 ++ test -f $file || touch $file ++ test -r $file || die "Error: failed to read ignore file: $file" ++ duplicate_entries=$(gitignore_entries $file | sort | uniq -d) ++ if [ "$duplicate_entries" ] ; then ++ die "Error: Duplicate entries in $file: " $duplicate_entries ++ fi ++ linesold=$(gitignore_entries $file | wc -l) ++ linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l) ++ if [ $linesold != $linesnew ] ; then ++ { echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \ ++ || die "insert_if_absent $file $str: failed" ++ fi ++} ++ ++# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with ++# insert_if_absent. ++insert_vc_ignore() { ++ vc_ignore_file="$1" ++ pattern="$2" ++ case $vc_ignore_file in ++ *.gitignore) ++ # A .gitignore entry that does not start with '/' applies ++ # recursively to subdirectories, so prepend '/' to every ++ # .gitignore entry. ++ pattern=$(echo "$pattern" | sed s,^,/,);; ++ esac ++ insert_if_absent "$vc_ignore_file" "$pattern" ++} ++ ++symlink_to_dir() ++{ ++ src=$1/$2 ++ dst=${3-$2} ++ ++ test -f "$src" && { ++ ++ # If the destination directory doesn't exist, create it. ++ # This is required at least for "lib/uniwidth/cjk.h". ++ dst_dir=$(dirname "$dst") ++ if ! test -d "$dst_dir"; then ++ mkdir -p "$dst_dir" ++ ++ # If we've just created a directory like lib/uniwidth, ++ # tell version control system(s) it's ignorable. ++ # FIXME: for now, this does only one level ++ parent=$(dirname "$dst_dir") ++ for dot_ig in x $vc_ignore; do ++ test $dot_ig = x && continue ++ ig=$parent/$dot_ig ++ insert_vc_ignore $ig "${dst_dir##*/}" ++ done ++ fi ++ ++ if $copy; then ++ { ++ test ! -h "$dst" || { ++ echo "$me: rm -f $dst" && ++ rm -f "$dst" ++ } ++ } && ++ test -f "$dst" && ++ cmp -s "$src" "$dst" || { ++ echo "$me: cp -fp $src $dst" && ++ cp -fp "$src" "$dst" ++ } ++ else ++ # Leave any existing symlink alone, if it already points to the source, ++ # so that broken build tools that care about symlink times ++ # aren't confused into doing unnecessary builds. Conversely, if the ++ # existing symlink's timestamp is older than the source, make it afresh, ++ # so that broken tools aren't confused into skipping needed builds. See ++ # . ++ test -h "$dst" && ++ src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 && ++ dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 && ++ test "$src_i" = "$dst_i" && ++ both_ls=$(ls -dt "$src" "$dst") && ++ test "X$both_ls" = "X$dst$nl$src" || { ++ dot_dots= ++ case $src in ++ /*) ;; ++ *) ++ case /$dst/ in ++ *//* | */../* | */./* | /*/*/*/*/*/) ++ die "invalid symlink calculation: $src -> $dst";; ++ /*/*/*/*/) dot_dots=../../../;; ++ /*/*/*/) dot_dots=../../;; ++ /*/*/) dot_dots=../;; ++ esac;; ++ esac ++ ++ echo "$me: ln -fs $dot_dots$src $dst" && ++ ln -fs "$dot_dots$src" "$dst" ++ } ++ fi ++ } ++} ++ + # Override the default configuration, if necessary. + # Make sure that bootstrap.conf is sourced from the current directory + # if we were invoked as "sh bootstrap". +@@ -320,6 +453,12 @@ do + --help) + usage + exit;; ++ --version) ++ set -e ++ echo "bootstrap $scriptversion" ++ echo "$copyright" ++ exit 0 ++ ;; + --gnulib-srcdir=*) + GNULIB_SRCDIR=${option#--gnulib-srcdir=};; + --skip-po) +@@ -335,7 +474,7 @@ do + --no-git) + use_git=false;; + *) +- die "$option: unknown option";; ++ bootstrap_option_hook $option || die "$option: unknown option";; + esac + done + +@@ -346,47 +485,6 @@ if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then + die "Bootstrapping from a non-checked-out distribution is risky." + fi + +-# Strip blank and comment lines to leave significant entries. +-gitignore_entries() { +- sed '/^#/d; /^$/d' "$@" +-} +- +-# If $STR is not already on a line by itself in $FILE, insert it at the start. +-# Entries are inserted at the start of the ignore list to ensure existing +-# entries starting with ! are not overridden. Such entries support +-# whitelisting exceptions after a more generic blacklist pattern. +-insert_if_absent() { +- file=$1 +- str=$2 +- test -f $file || touch $file +- test -r $file || die "Error: failed to read ignore file: $file" +- duplicate_entries=$(gitignore_entries $file | sort | uniq -d) +- if [ "$duplicate_entries" ] ; then +- die "Error: Duplicate entries in $file: " $duplicate_entries +- fi +- linesold=$(gitignore_entries $file | wc -l) +- linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l) +- if [ $linesold != $linesnew ] ; then +- { echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \ +- || die "insert_if_absent $file $str: failed" +- fi +-} +- +-# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with +-# insert_if_absent. +-insert_vc_ignore() { +- vc_ignore_file="$1" +- pattern="$2" +- case $vc_ignore_file in +- *.gitignore) +- # A .gitignore entry that does not start with '/' applies +- # recursively to subdirectories, so prepend '/' to every +- # .gitignore entry. +- pattern=$(echo "$pattern" | sed s,^,/,);; +- esac +- insert_if_absent "$vc_ignore_file" "$pattern" +-} +- + # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. + found_aux_dir=no + grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \ +@@ -665,9 +763,25 @@ if $use_gnulib; then + shallow= + if test -z "$GNULIB_REVISION"; then + git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' ++ git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ ++ || cleanup_gnulib ++ else ++ git fetch -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' ++ mkdir -p "$gnulib_path" ++ # Only want a shallow checkout of $GNULIB_REVISION, but git does not ++ # support cloning by commit hash. So attempt a shallow fetch by commit ++ # hash to minimize the amount of data downloaded and changes needed to ++ # be processed, which can drastically reduce download and processing ++ # time for checkout. If the fetch by commit fails, a shallow fetch can ++ # not be performed because we do not know what the depth of the commit ++ # is without fetching all commits. So fallback to fetching all commits. ++ git -C "$gnulib_path" init ++ git -C "$gnulib_path" remote add origin ${GNULIB_URL:-$default_gnulib_url} ++ git -C "$gnulib_path" fetch $shallow origin "$GNULIB_REVISION" \ ++ || git -C "$gnulib_path" fetch origin \ ++ || cleanup_gnulib ++ git -C "$gnulib_path" reset --hard FETCH_HEAD + fi +- git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ +- || cleanup_gnulib + + trap - 1 2 13 15 + fi +@@ -784,75 +898,6 @@ case $SKIP_PO in + fi;; + esac + +-symlink_to_dir() +-{ +- src=$1/$2 +- dst=${3-$2} +- +- test -f "$src" && { +- +- # If the destination directory doesn't exist, create it. +- # This is required at least for "lib/uniwidth/cjk.h". +- dst_dir=$(dirname "$dst") +- if ! test -d "$dst_dir"; then +- mkdir -p "$dst_dir" +- +- # If we've just created a directory like lib/uniwidth, +- # tell version control system(s) it's ignorable. +- # FIXME: for now, this does only one level +- parent=$(dirname "$dst_dir") +- for dot_ig in x $vc_ignore; do +- test $dot_ig = x && continue +- ig=$parent/$dot_ig +- insert_vc_ignore $ig "${dst_dir##*/}" +- done +- fi +- +- if $copy; then +- { +- test ! -h "$dst" || { +- echo "$me: rm -f $dst" && +- rm -f "$dst" +- } +- } && +- test -f "$dst" && +- cmp -s "$src" "$dst" || { +- echo "$me: cp -fp $src $dst" && +- cp -fp "$src" "$dst" +- } +- else +- # Leave any existing symlink alone, if it already points to the source, +- # so that broken build tools that care about symlink times +- # aren't confused into doing unnecessary builds. Conversely, if the +- # existing symlink's timestamp is older than the source, make it afresh, +- # so that broken tools aren't confused into skipping needed builds. See +- # . +- test -h "$dst" && +- src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 && +- dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 && +- test "$src_i" = "$dst_i" && +- both_ls=$(ls -dt "$src" "$dst") && +- test "X$both_ls" = "X$dst$nl$src" || { +- dot_dots= +- case $src in +- /*) ;; +- *) +- case /$dst/ in +- *//* | */../* | */./* | /*/*/*/*/*/) +- die "invalid symlink calculation: $src -> $dst";; +- /*/*/*/*/) dot_dots=../../../;; +- /*/*/*/) dot_dots=../../;; +- /*/*/) dot_dots=../;; +- esac;; +- esac +- +- echo "$me: ln -fs $dot_dots$src $dst" && +- ln -fs "$dot_dots$src" "$dst" +- } +- fi +- } +-} +- + version_controlled_file() { + parent=$1 + file=$2 +@@ -970,7 +1015,7 @@ bootstrap_post_import_hook \ + # Uninitialized submodules are listed with an initial dash. + if $use_git && git submodule | grep '^-' >/dev/null; then + die "some git submodules are not initialized. " \ +- "Run 'git submodule init' and bootstrap again." ++ "Run 'git submodule update --init' and bootstrap again." + fi + + # Remove any dangling symlink matching "*.m4" or "*.[ch]" in some +@@ -1064,7 +1109,7 @@ bootstrap_epilogue + + echo "$0: done. Now you can run './configure'." + +-# Local variables: ++# Local Variables: + # eval: (add-hook 'before-save-hook 'time-stamp) + # time-stamp-start: "scriptversion=" + # time-stamp-format: "%:y-%02m-%02d.%02H" +diff --git a/bootstrap.conf b/bootstrap.conf +index 71ce943c7d..e4e5f3750a 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -1,6 +1,6 @@ + # Bootstrap configuration. + +-# Copyright (C) 2006-2019 Free Software Foundation, Inc. ++# Copyright (C) 2006-2022 Free Software Foundation, Inc. + + # This program is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -16,11 +16,10 @@ + # along with this program. If not, see . + + +-GNULIB_REVISION=d271f868a8df9bbec29049d01e056481b7a1a263 ++GNULIB_REVISION=9f48fb992a3d7e96610c4ce8be969cff2d61a01b + + # gnulib modules used by this package. +-# mbswidth is used by gnulib-fix-width.diff's changes to argp rather than +-# directly. ++# mbswidth is used by fix-width.diff's changes to argp rather than directly. + gnulib_modules=" + argp + base64 +@@ -67,8 +66,8 @@ SKIP_PO=t + + # Build prerequisites + buildreq="\ +-autoconf 2.63 +-automake 1.11 ++autoconf 2.64 ++automake 1.14 + gettext 0.18.3 + git 1.5.5 + tar - +@@ -80,11 +79,12 @@ cp -a INSTALL INSTALL.grub + + bootstrap_post_import_hook () { + set -e +- for patchname in fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \ +- fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width; do +- patch -d grub-core/lib/gnulib -p2 \ +- < "grub-core/lib/gnulib-patches/$patchname.patch" +- done ++ ++ # Instead of patching our gnulib and therefore maintaining a fork, submit ++ # changes to gnulib and update the hash above when they've merged. Do not ++ # add new patches here. ++ patch -d grub-core/lib/gnulib -p2 < grub-core/lib/gnulib-patches/fix-width.patch ++ + for patchname in \ + 0001-Support-POTFILES-shell \ + 0002-Handle-gettext_printf-shell-function \ +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index 5eef708338..26ac8765e3 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -31,12 +31,6 @@ EXTRA_DIST += grub-core/gensymlist.sh + EXTRA_DIST += grub-core/genemuinit.sh + EXTRA_DIST += grub-core/genemuinitheader.sh + +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch +-EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch + EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch + + EXTRA_DIST += grub-core/lib/libgcrypt +diff --git a/config.h.in b/config.h.in +index c3134309c6..512d1bbe13 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -67,10 +67,78 @@ + # define _GNU_SOURCE 1 + + # ifndef _GL_INLINE_HEADER_BEGIN ++/* gnulib gets configured against the host, not the target, and the rest of ++ * our buildsystem works around that. This is difficult to avoid as gnulib's ++ * detection requires a more capable system than our target. Instead, we ++ * reach in and set values appropriately - intentionally setting more than the ++ * bare minimum. If, when updating gnulib, something breaks, there's probably ++ * a change needed here or in grub-core/Makefile.core.def. */ ++# define SIZE_MAX ((size_t) -1) ++# define _GL_ATTRIBUTE_ALLOC_SIZE(args) \ ++ __attribute__ ((__alloc_size__ args)) ++# define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__)) ++# define _GL_ATTRIBUTE_ARTIFICIAL __attribute__ ((__artificial__)) ++# define _GL_ATTRIBUTE_COLD __attribute__ ((cold)) + # define _GL_ATTRIBUTE_CONST __attribute__ ((const)) ++# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute ((__malloc__ (f, i))) ++# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1) ++# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) ++# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg))) ++# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE \ ++ __attribute__ ((externally_visible)) ++# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) ++# define _GL_ATTRIBUTE_LEAF __attribute__ ((__leaf__)) ++# define _GL_ATTRIBUTE_MALLOC __attribute__ ((malloc)) ++# define _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_UNUSED ++# define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__)) ++# define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__)) ++# define _GL_ATTRIBUTE_NOINLINE __attribute__ ((__noinline__)) ++# define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args)) ++# define _GL_ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__)) ++# define _GL_ATTRIBUTE_PACKED __attribute__ ((__packed__)) ++# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) ++# define _GL_ATTRIBUTE_RETURNS_NONNULL \ ++ __attribute__ ((__returns_nonnull__)) ++# define _GL_ATTRIBUTE_SENTINEL(pos) __attribute__ ((__sentinel__ pos)) ++# define _GL_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) ++# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg))) ++# define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2))) ++# define _GL_GNUC_PREREQ GNUC_PREREQ ++# define _GL_INLINE inline ++# define _GL_UNUSED_LABEL _GL_ATTRIBUTE_UNUSED ++ ++/* We can't use __has_attribute for these because gcc-5.1 is too old for ++ * that. Everything above is present in that version, though. */ ++# if __GNUC__ >= 7 ++# define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough)) ++# else ++# define _GL_ATTRIBUTE_FALLTHROUGH /* empty */ ++# endif ++ ++# ifndef ASM_FILE ++typedef __INT_FAST32_TYPE__ int_fast32_t; ++typedef __UINT_FAST32_TYPE__ uint_fast32_t; ++# endif ++ ++/* Ensure ialloc nests static/non-static inline properly. */ ++# define IALLOC_INLINE static inline ++ ++/* gnulib uses these for blocking out warnings they can't/won't fix. gnulib ++ * also makes the decision about whether to provide a declaration for ++ * reallocarray() at compile-time, so this is a convenient place to override - ++ * it's used by the ialloc module, which is used by base64. */ ++# define _GL_INLINE_HEADER_BEGIN _Pragma ("GCC diagnostic push") \ ++ void * \ ++ reallocarray (void *ptr, unsigned int nmemb, unsigned int size); ++# define _GL_INLINE_HEADER_END _Pragma ("GCC diagnostic pop") + + /* We don't have an abort() for gnulib to call in regexp. */ + # define abort __builtin_unreachable + # endif /* !_GL_INLINE_HEADER_BEGIN */ + ++/* gnulib doesn't build cleanly with older compilers. */ ++# if __GNUC__ < 11 ++_Pragma ("GCC diagnostic ignored \"-Wtype-limits\"") ++# endif ++ + #endif +diff --git a/grub-core/lib/gnulib-patches/fix-null-deref.patch b/grub-core/lib/gnulib-patches/fix-null-deref.patch +deleted file mode 100644 +index 8fafa153a4..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-null-deref.patch ++++ /dev/null +@@ -1,13 +0,0 @@ +-diff --git a/lib/argp-parse.c b/lib/argp-parse.c +-index 6dec57310..900adad54 100644 +---- a/lib/argp-parse.c +-+++ b/lib/argp-parse.c +-@@ -940,7 +940,7 @@ weak_alias (__argp_parse, argp_parse) +- void * +- __argp_input (const struct argp *argp, const struct argp_state *state) +- { +-- if (state) +-+ if (state && state->pstate) +- { +- struct group *group; +- struct parser *parser = state->pstate; +diff --git a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch +deleted file mode 100644 +index 813ec09c8a..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch ++++ /dev/null +@@ -1,12 +0,0 @@ +---- a/lib/argp-help.c 2020-10-28 14:32:19.189215988 +0000 +-+++ b/lib/argp-help.c 2020-10-28 14:38:21.204673940 +0000 +-@@ -145,7 +145,8 @@ +- if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) +- { +- __argp_failure (state, 0, 0, +-- dgettext (state->root_argp->argp_domain, +-+ dgettext (state == NULL ? NULL +-+ : state->root_argp->argp_domain, +- "\ +- ARGP_HELP_FMT: %s value is less than or equal to %s"), +- "rmargin", up->name); +diff --git a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch +deleted file mode 100644 +index 02e06315df..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch ++++ /dev/null +@@ -1,15 +0,0 @@ +---- a/lib/regcomp.c 2020-11-24 17:06:08.159223858 +0000 +-+++ b/lib/regcomp.c 2020-11-24 17:06:15.630253923 +0000 +-@@ -3808,11 +3808,7 @@ +- create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, +- re_token_type_t type) +- { +-- re_token_t t; +--#if defined GCC_LINT || defined lint +-- memset (&t, 0, sizeof t); +--#endif +-- t.type = type; +-+ re_token_t t = { .type = type }; +- return create_token_tree (dfa, left, right, &t); +- } +- +diff --git a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch +deleted file mode 100644 +index db6dac9c9e..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch ++++ /dev/null +@@ -1,12 +0,0 @@ +---- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 +-+++ b/lib/regexec.c 2020-11-05 10:55:09.621542984 +0000 +-@@ -1692,6 +1692,9 @@ +- { +- Idx top = mctx->state_log_top; +- +-+ if (mctx->state_log == NULL) +-+ return REG_NOERROR; +-+ +- if ((next_state_log_idx >= mctx->input.bufs_len +- && mctx->input.bufs_len < mctx->input.len) +- || (next_state_log_idx >= mctx->input.valid_len +diff --git a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch +deleted file mode 100644 +index 7b4d9f67af..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch ++++ /dev/null +@@ -1,11 +0,0 @@ +---- a/lib/regcomp.c 2020-10-22 13:49:06.770168928 +0000 +-+++ b/lib/regcomp.c 2020-10-22 13:50:37.026528298 +0000 +-@@ -3662,7 +3662,7 @@ +- Idx alloc = 0; +- #endif /* not RE_ENABLE_I18N */ +- reg_errcode_t ret; +-- re_token_t br_token; +-+ re_token_t br_token = {0}; +- bin_tree_t *tree; +- +- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); +diff --git a/grub-core/lib/gnulib-patches/fix-unused-value.patch b/grub-core/lib/gnulib-patches/fix-unused-value.patch +deleted file mode 100644 +index ba51f1bf22..0000000000 +--- a/grub-core/lib/gnulib-patches/fix-unused-value.patch ++++ /dev/null +@@ -1,14 +0,0 @@ +---- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 +-+++ b/lib/regexec.c 2020-10-21 14:32:07.961765604 +0000 +-@@ -828,7 +828,11 @@ +- break; +- if (__glibc_unlikely (err != REG_NOMATCH)) +- goto free_return; +-+#ifdef DEBUG +-+ /* Only used for assertion below when DEBUG is set, otherwise +-+ it will be over-written when we loop around. */ +- match_last = -1; +-+#endif +- } +- else +- break; /* We found a match. */ diff --git a/SOURCES/0202-ieee1275-ofdisk-retry-on-open-failure.patch b/SOURCES/0202-ieee1275-ofdisk-retry-on-open-failure.patch deleted file mode 100644 index 275d14f..0000000 --- a/SOURCES/0202-ieee1275-ofdisk-retry-on-open-failure.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Wed, 10 Mar 2021 14:17:52 -0500 -Subject: [PATCH] ieee1275/ofdisk: retry on open failure - -This patch aims to make grub more robust when booting from SAN/Multipath disks. - -If a path is failing intermittently so grub will retry the OPEN and READ the -disk (grub_ieee1275_open and grub_ieee1275_read) until the total amount of times -specified in MAX_RETRIES. - -Signed-off-by: Diego Domingos ---- - grub-core/disk/ieee1275/ofdisk.c | 25 ++++++++++++++++++++----- - include/grub/ieee1275/ofdisk.h | 8 ++++++++ - 2 files changed, 28 insertions(+), 5 deletions(-) - -diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c -index ea7f78ac7d8..55346849d35 100644 ---- a/grub-core/disk/ieee1275/ofdisk.c -+++ b/grub-core/disk/ieee1275/ofdisk.c -@@ -225,7 +225,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) - char *buf, *bufptr; - unsigned i; - -- if (grub_ieee1275_open (alias->path, &ihandle)) -+ -+ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle) -+ if (! ihandle) - return; - - /* This method doesn't need memory allocation for the table. Open -@@ -305,7 +307,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias) - return; - } - -- if (grub_ieee1275_open (alias->path, &ihandle)) -+ RETRY_IEEE1275_OFDISK_OPEN(alias->path, &ihandle); -+ -+ if (! ihandle) - { - grub_free (buf); - grub_free (table); -@@ -495,7 +499,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) - last_ihandle = 0; - last_devpath = NULL; - -- grub_ieee1275_open (op->open_path, &last_ihandle); -+ RETRY_IEEE1275_OFDISK_OPEN(op->open_path, &last_ihandle); - if (! last_ihandle) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - last_devpath = op->open_path; -@@ -571,7 +575,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) - last_ihandle = 0; - last_devpath = NULL; - -- grub_ieee1275_open (disk->data, &last_ihandle); -+ RETRY_IEEE1275_OFDISK_OPEN(disk->data, &last_ihandle); - if (! last_ihandle) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - last_devpath = disk->data; -@@ -598,12 +602,23 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, - return err; - grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, - &actual); -- if (actual != (grub_ssize_t) (size << disk->log_sector_size)) -+ int i = 0; -+ while(actual != (grub_ssize_t) (size << disk->log_sector_size)){ -+ if (i>MAX_RETRIES){ - return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " - "from `%s'"), - (unsigned long long) sector, - disk->name); -+ } -+ last_devpath = NULL; -+ err = grub_ofdisk_prepare (disk, sector); -+ if (err) -+ return err; - -+ grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, -+ &actual); -+ i++; -+ } - return 0; - } - -diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h -index 2f69e3f191d..7d2d5409305 100644 ---- a/include/grub/ieee1275/ofdisk.h -+++ b/include/grub/ieee1275/ofdisk.h -@@ -22,4 +22,12 @@ - extern void grub_ofdisk_init (void); - extern void grub_ofdisk_fini (void); - -+#define MAX_RETRIES 20 -+ -+ -+#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ -+ if(!grub_ieee1275_open(device, last_ihandle)) \ -+ break; \ -+ grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } -+ - #endif /* ! GRUB_INIT_HEADER */ diff --git a/SOURCES/0203-01_menu_auto_hide.in-fix-a-then-than-typo.patch b/SOURCES/0203-01_menu_auto_hide.in-fix-a-then-than-typo.patch deleted file mode 100644 index 4847ef9..0000000 --- a/SOURCES/0203-01_menu_auto_hide.in-fix-a-then-than-typo.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= -Date: Fri, 11 Jun 2021 12:57:56 +0200 -Subject: [PATCH] 01_menu_auto_hide.in: fix a then/than typo -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Jan Pokorný ---- - util/grub.d/10_reset_boot_success.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in -index 737e1ae5b68..e73f4137b36 100644 ---- a/util/grub.d/10_reset_boot_success.in -+++ b/util/grub.d/10_reset_boot_success.in -@@ -15,7 +15,7 @@ fi - # Reset boot_indeterminate after a successful boot - if [ "\${boot_success}" = "1" ] ; then - set boot_indeterminate=0 --# Avoid boot_indeterminate causing the menu to be hidden more then once -+# Avoid boot_indeterminate causing the menu to be hidden more than once - elif [ "\${boot_indeterminate}" = "1" ]; then - set boot_indeterminate=2 - fi diff --git a/SOURCES/0203-commands-search-Fix-bug-stopping-iteration-when-no-f.patch b/SOURCES/0203-commands-search-Fix-bug-stopping-iteration-when-no-f.patch new file mode 100644 index 0000000..4f7feb9 --- /dev/null +++ b/SOURCES/0203-commands-search-Fix-bug-stopping-iteration-when-no-f.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Tue, 8 Feb 2022 08:39:10 +0100 +Subject: [PATCH] commands/search: Fix bug stopping iteration when --no-floppy + is used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When using --no-floppy and a floppy was encountered, iterate_device() +was returning 1, causing the iteration to stop instead of continuing. + +Signed-off-by: Renaud Métrich +Reviewed-by: Daniel Kiper +(cherry picked from commit 68ba54c2298604146be83cae144dafd1cfd1fe2d) +Signed-off-by: Robbie Harwood +--- + grub-core/commands/search.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c +index ed090b3af8..51656e361c 100644 +--- a/grub-core/commands/search.c ++++ b/grub-core/commands/search.c +@@ -64,7 +64,7 @@ iterate_device (const char *name, void *data) + /* Skip floppy drives when requested. */ + if (ctx->no_floppy && + name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') +- return 1; ++ return 0; + + #ifdef DO_SEARCH_FS_UUID + #define compare_fn grub_strcasecmp diff --git a/SOURCES/0204-Fix-disabling-grub-rpm-sort.patch b/SOURCES/0204-Fix-disabling-grub-rpm-sort.patch deleted file mode 100644 index dccde3c..0000000 --- a/SOURCES/0204-Fix-disabling-grub-rpm-sort.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tim Landscheidt -Date: Fri, 11 Jun 2021 13:02:37 +0200 -Subject: [PATCH] Fix disabling grub-rpm-sort - -Currently, grub-rpm-sort is unconditionally compiled whether -./configure has been called with --disable-rpm-sort or not. This adds -the necessary logic to configure.ac and Makefile.util.def and some -debug output to ./configure and fixes #44. ---- - configure.ac | 8 ++++++++ - Makefile.util.def | 1 + - 2 files changed, 9 insertions(+) - -diff --git a/configure.ac b/configure.ac -index d5d2a28b4ef..c7842ec29d8 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1936,6 +1936,8 @@ AC_ARG_ENABLE([rpm-sort], - [enable native rpm sorting of kernels in grub (default=guessed)])]) - if test x"$enable_rpm_sort" = xno ; then - rpm_sort_excuse="explicitly disabled" -+else -+ enable_rpm_sort=yes - fi - - if test x"$rpm_sort_excuse" = x ; then -@@ -2200,6 +2202,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) - AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) - AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) - AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes]) -+AM_CONDITIONAL([COND_GRUB_RPM_SORT], [test x$enable_rpm_sort = xyes]) - AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) - if test x$FONT_SOURCE != x ; then - HAVE_FONT_SOURCE=1 -@@ -2328,6 +2331,11 @@ echo grub-mount: Yes - else - echo grub-mount: No "($grub_mount_excuse)" - fi -+if [ x"$rpm_sort_excuse" = x ]; then -+echo grub-rpm-sort: Yes -+else -+echo grub-rpm-sort: No "($rpm_sort_excuse)" -+fi - if [ x"$starfield_excuse" = x ]; then - echo starfield theme: Yes - echo With DejaVuSans font from $DJVU_FONT_SOURCE -diff --git a/Makefile.util.def b/Makefile.util.def -index 8cfbe69a76e..3f191aa8095 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -774,6 +774,7 @@ program = { - ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; - ldadd = '$(LIBDEVMAPPER) $(LIBRPM)'; -+ condition = COND_GRUB_RPM_SORT; - }; - - script = { diff --git a/SOURCES/0204-search-new-efidisk-only-option-on-EFI-systems.patch b/SOURCES/0204-search-new-efidisk-only-option-on-EFI-systems.patch new file mode 100644 index 0000000..3f6194a --- /dev/null +++ b/SOURCES/0204-search-new-efidisk-only-option-on-EFI-systems.patch @@ -0,0 +1,168 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Tue, 8 Feb 2022 08:39:11 +0100 +Subject: [PATCH] search: new --efidisk-only option on EFI systems +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When using 'search' on EFI systems, we sometimes want to exclude devices +that are not EFI disks (e.g. md, lvm). +This is typically used when wanting to chainload when having a software +raid (md) for EFI partition: +with no option, 'search --file /EFI/redhat/shimx64.efi' sets root envvar +to 'md/boot_efi' which cannot be used for chainloading since there is no +effective EFI device behind. + +This commit also refactors handling of --no-floppy option. + +Signed-off-by: Renaud Métrich +[rharwood: apply rmetrich's flags initialization fix] +Signed-off-by: Robbie Harwood +--- + grub-core/commands/search.c | 27 +++++++++++++++++++++++---- + grub-core/commands/search_wrap.c | 18 ++++++++++++------ + include/grub/search.h | 15 ++++++++++++--- + 3 files changed, 47 insertions(+), 13 deletions(-) + +diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c +index 51656e361c..57d26ced8a 100644 +--- a/grub-core/commands/search.c ++++ b/grub-core/commands/search.c +@@ -47,7 +47,7 @@ struct search_ctx + { + const char *key; + const char *var; +- int no_floppy; ++ enum search_flags flags; + char **hints; + unsigned nhints; + int count; +@@ -62,10 +62,29 @@ iterate_device (const char *name, void *data) + int found = 0; + + /* Skip floppy drives when requested. */ +- if (ctx->no_floppy && ++ if (ctx->flags & SEARCH_FLAGS_NO_FLOPPY && + name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') + return 0; + ++ /* Limit to EFI disks when requested. */ ++ if (ctx->flags & SEARCH_FLAGS_EFIDISK_ONLY) ++ { ++ grub_device_t dev; ++ dev = grub_device_open (name); ++ if (! dev) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ if (! dev->disk || dev->disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID) ++ { ++ grub_device_close (dev); ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ grub_device_close (dev); ++ } ++ + #ifdef DO_SEARCH_FS_UUID + #define compare_fn grub_strcasecmp + #else +@@ -261,13 +280,13 @@ try (struct search_ctx *ctx) + } + + void +-FUNC_NAME (const char *key, const char *var, int no_floppy, ++FUNC_NAME (const char *key, const char *var, enum search_flags flags, + char **hints, unsigned nhints) + { + struct search_ctx ctx = { + .key = key, + .var = var, +- .no_floppy = no_floppy, ++ .flags = flags, + .hints = hints, + .nhints = nhints, + .count = 0, +diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c +index 47fc8eb996..0b62acf853 100644 +--- a/grub-core/commands/search_wrap.c ++++ b/grub-core/commands/search_wrap.c +@@ -40,6 +40,7 @@ static const struct grub_arg_option options[] = + N_("Set a variable to the first device found."), N_("VARNAME"), + ARG_TYPE_STRING}, + {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, ++ {"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0}, + {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, +@@ -73,6 +74,7 @@ enum options + SEARCH_FS_UUID, + SEARCH_SET, + SEARCH_NO_FLOPPY, ++ SEARCH_EFIDISK_ONLY, + SEARCH_HINT, + SEARCH_HINT_IEEE1275, + SEARCH_HINT_BIOS, +@@ -89,6 +91,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) + const char *id = 0; + int i = 0, j = 0, nhints = 0; + char **hints = NULL; ++ enum search_flags flags = 0; + + if (state[SEARCH_HINT].set) + for (i = 0; state[SEARCH_HINT].args[i]; i++) +@@ -180,15 +183,18 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) + goto out; + } + ++ if (state[SEARCH_NO_FLOPPY].set) ++ flags |= SEARCH_FLAGS_NO_FLOPPY; ++ ++ if (state[SEARCH_EFIDISK_ONLY].set) ++ flags |= SEARCH_FLAGS_EFIDISK_ONLY; ++ + if (state[SEARCH_LABEL].set) +- grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, +- hints, nhints); ++ grub_search_label (id, var, flags, hints, nhints); + else if (state[SEARCH_FS_UUID].set) +- grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set, +- hints, nhints); ++ grub_search_fs_uuid (id, var, flags, hints, nhints); + else if (state[SEARCH_FILE].set) +- grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, +- hints, nhints); ++ grub_search_fs_file (id, var, flags, hints, nhints); + else + grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); + +diff --git a/include/grub/search.h b/include/grub/search.h +index d80347df34..4190aeb2cb 100644 +--- a/include/grub/search.h ++++ b/include/grub/search.h +@@ -19,11 +19,20 @@ + #ifndef GRUB_SEARCH_HEADER + #define GRUB_SEARCH_HEADER 1 + +-void grub_search_fs_file (const char *key, const char *var, int no_floppy, ++enum search_flags ++ { ++ SEARCH_FLAGS_NO_FLOPPY = 1, ++ SEARCH_FLAGS_EFIDISK_ONLY = 2 ++ }; ++ ++void grub_search_fs_file (const char *key, const char *var, ++ enum search_flags flags, + char **hints, unsigned nhints); +-void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, ++void grub_search_fs_uuid (const char *key, const char *var, ++ enum search_flags flags, + char **hints, unsigned nhints); +-void grub_search_label (const char *key, const char *var, int no_floppy, ++void grub_search_label (const char *key, const char *var, ++ enum search_flags flags, + char **hints, unsigned nhints); + + #endif diff --git a/SOURCES/0205-Don-t-check-for-rpmvercmp-in-librpm.patch b/SOURCES/0205-Don-t-check-for-rpmvercmp-in-librpm.patch deleted file mode 100644 index c21dca4..0000000 --- a/SOURCES/0205-Don-t-check-for-rpmvercmp-in-librpm.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Fri, 11 Jun 2021 13:13:27 +0200 -Subject: [PATCH] Don't check for rpmvercmp in librpm - -The rpmvercmp() function was moved from librpm to librpmio. The configure -option had some logic to first check if the symbol is in librpm and then -librpmio if this check didn't succeed. - -But the logic wasn't working and rpm sorting was always disabled. Instead -of trying to fix this logic, let's just remove since the function already -moved and there's no need to check librpm anymore. Now it's enabled again: - - GRUB2 will be compiled with following components: - ... - grub-rpm-sort: Yes - ... - -Signed-off-by: Javier Martinez Canillas ---- - configure.ac | 19 +++++-------------- - 1 file changed, 5 insertions(+), 14 deletions(-) - -diff --git a/configure.ac b/configure.ac -index c7842ec29d8..3c808a72230 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1947,24 +1947,15 @@ if test x"$rpm_sort_excuse" = x ; then - fi - - if test x"$rpm_sort_excuse" = x ; then -- # Check for rpm library. -- AC_CHECK_LIB([rpm], [rpmvercmp], [], -- [rpm_sort_excuse="rpmlib missing rpmvercmp"]) --fi -- --if test x"$rpm_sort_excuse" = x ; then -- LIBRPM="-lrpm"; -- AC_DEFINE([HAVE_RPM], [1], -- [Define to 1 if you have the rpm library.]) --fi -- --if test x"$LIBRPM" = x ; then -- # Check for rpm library. -+ # Check for rpmio library. - AC_CHECK_LIB([rpmio], [rpmvercmp], [], - [rpm_sort_excuse="rpmio missing rpmvercmp"]) -+fi -+ -+if test x"$rpm_sort_excuse" = x ; then - LIBRPM="-lrpmio"; - AC_DEFINE([HAVE_RPMIO], [1], -- [Define to 1 if you have the rpm library.]) -+ [Define to 1 if you have the rpmio library.]) - fi - - AC_SUBST([LIBRPM]) diff --git a/SOURCES/0205-efi-new-connectefi-command.patch b/SOURCES/0205-efi-new-connectefi-command.patch new file mode 100644 index 0000000..f80de22 --- /dev/null +++ b/SOURCES/0205-efi-new-connectefi-command.patch @@ -0,0 +1,395 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Tue, 15 Feb 2022 14:05:22 +0100 +Subject: [PATCH] efi: new 'connectefi' command +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When efi.quickboot is enabled on VMWare (which is the default for +hardware release 16 and later), it may happen that not all EFI devices +are connected. Due to this, browsing the devices in make_devices() just +fails to find devices, in particular disks or partitions for a given +disk. +This typically happens when network booting, then trying to chainload to +local disk (this is used in deployment tools such as Red Hat Satellite), +which is done through using the following grub.cfg snippet: +-------- 8< ---------------- 8< ---------------- 8< -------- +unset prefix +search --file --set=prefix /EFI/redhat/grubx64.efi +if [ -n "$prefix" ]; then + chainloader ($prefix)/EFI/redhat/grubx64/efi +... +-------- 8< ---------------- 8< ---------------- 8< -------- + +With efi.quickboot, none of the devices are connected, causing "search" +to fail. Sometimes devices are connected but not the partition of the +disk matching $prefix, causing partition to not be found by +"chainloader". + +This patch introduces a new "connectefi pciroot|scsi" command which +recursively connects all EFI devices starting from a given controller +type: +- if 'pciroot' is specified, recursion is performed for all PCI root + handles +- if 'scsi' is specified, recursion is performed for all SCSI I/O + handles (recommended usage to avoid connecting unwanted handles which + may impact Grub performances) + +Typical grub.cfg snippet would then be: +-------- 8< ---------------- 8< ---------------- 8< -------- +connectefi scsi +unset prefix +search --file --set=prefix /EFI/redhat/grubx64.efi +if [ -n "$prefix" ]; then + chainloader ($prefix)/EFI/redhat/grubx64/efi +... +-------- 8< ---------------- 8< ---------------- 8< -------- + +The code is easily extensible to handle other arguments in the future if +needed. + +Signed-off-by: Renaud Métrich +Signed-off-by: Robbie Harwood +--- + grub-core/Makefile.core.def | 6 ++ + grub-core/commands/efi/connectefi.c | 205 ++++++++++++++++++++++++++++++++++++ + grub-core/commands/efi/lsefi.c | 1 + + grub-core/disk/efi/efidisk.c | 13 +++ + grub-core/kern/efi/efi.c | 13 +++ + include/grub/efi/disk.h | 2 + + include/grub/efi/efi.h | 5 + + NEWS | 2 +- + 8 files changed, 246 insertions(+), 1 deletion(-) + create mode 100644 grub-core/commands/efi/connectefi.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index ec1ec5083b..741a033978 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -836,6 +836,12 @@ module = { + enable = efi; + }; + ++module = { ++ name = connectefi; ++ common = commands/efi/connectefi.c; ++ enable = efi; ++}; ++ + module = { + name = blocklist; + common = commands/blocklist.c; +diff --git a/grub-core/commands/efi/connectefi.c b/grub-core/commands/efi/connectefi.c +new file mode 100644 +index 0000000000..8ab75bd51b +--- /dev/null ++++ b/grub-core/commands/efi/connectefi.c +@@ -0,0 +1,205 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++typedef struct handle_list ++{ ++ grub_efi_handle_t handle; ++ struct handle_list *next; ++} handle_list_t; ++ ++static handle_list_t *already_handled = NULL; ++ ++static grub_err_t ++add_handle (grub_efi_handle_t handle) ++{ ++ handle_list_t *e; ++ e = grub_malloc (sizeof (*e)); ++ if (! e) ++ return grub_errno; ++ e->handle = handle; ++ e->next = already_handled; ++ already_handled = e; ++ return GRUB_ERR_NONE; ++} ++ ++static int ++is_in_list (grub_efi_handle_t handle) ++{ ++ handle_list_t *e; ++ for (e = already_handled; e != NULL; e = e->next) ++ if (e->handle == handle) ++ return 1; ++ return 0; ++} ++ ++static void ++free_handle_list (void) ++{ ++ handle_list_t *e; ++ while ((e = already_handled) != NULL) ++ { ++ already_handled = already_handled->next; ++ grub_free (e); ++ } ++} ++ ++typedef enum searched_item_flag ++{ ++ SEARCHED_ITEM_FLAG_LOOP = 1, ++ SEARCHED_ITEM_FLAG_RECURSIVE = 2 ++} searched_item_flags; ++ ++typedef struct searched_item ++{ ++ grub_efi_guid_t guid; ++ const char *name; ++ searched_item_flags flags; ++} searched_items; ++ ++static grub_err_t ++grub_cmd_connectefi (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char **args) ++{ ++ unsigned s; ++ searched_items pciroot_items[] = ++ { ++ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", SEARCHED_ITEM_FLAG_RECURSIVE } ++ }; ++ searched_items scsi_items[] = ++ { ++ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", 0 }, ++ { GRUB_EFI_PCI_IO_GUID, "PCI", SEARCHED_ITEM_FLAG_LOOP }, ++ { GRUB_EFI_SCSI_IO_PROTOCOL_GUID, "SCSI I/O", SEARCHED_ITEM_FLAG_RECURSIVE } ++ }; ++ searched_items *items = NULL; ++ unsigned nitems = 0; ++ grub_err_t grub_err = GRUB_ERR_NONE; ++ unsigned total_connected = 0; ++ ++ if (argc != 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); ++ ++ if (grub_strcmp(args[0], N_("pciroot")) == 0) ++ { ++ items = pciroot_items; ++ nitems = ARRAY_SIZE (pciroot_items); ++ } ++ else if (grub_strcmp(args[0], N_("scsi")) == 0) ++ { ++ items = scsi_items; ++ nitems = ARRAY_SIZE (scsi_items); ++ } ++ else ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("unexpected argument `%s'"), args[0]); ++ ++ for (s = 0; s < nitems; s++) ++ { ++ grub_efi_handle_t *handles; ++ grub_efi_uintn_t num_handles; ++ unsigned i, connected = 0, loop = 0; ++ ++loop: ++ loop++; ++ grub_dprintf ("efi", "step '%s' loop %d:\n", items[s].name, loop); ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, ++ &items[s].guid, 0, &num_handles); ++ ++ if (!handles) ++ continue; ++ ++ for (i = 0; i < num_handles; i++) ++ { ++ grub_efi_handle_t handle = handles[i]; ++ grub_efi_status_t status; ++ unsigned j; ++ ++ /* Skip already handled handles */ ++ if (is_in_list (handle)) ++ { ++ grub_dprintf ("efi", " handle %p: already processed\n", ++ handle); ++ continue; ++ } ++ ++ status = grub_efi_connect_controller(handle, NULL, NULL, ++ items[s].flags & SEARCHED_ITEM_FLAG_RECURSIVE ? 1 : 0); ++ if (status == GRUB_EFI_SUCCESS) ++ { ++ connected++; ++ total_connected++; ++ grub_dprintf ("efi", " handle %p: connected\n", handle); ++ } ++ else ++ grub_dprintf ("efi", " handle %p: failed to connect (%d)\n", ++ handle, (grub_efi_int8_t) status); ++ ++ if ((grub_err = add_handle (handle)) != GRUB_ERR_NONE) ++ break; /* fatal */ ++ } ++ ++ grub_free (handles); ++ if (grub_err != GRUB_ERR_NONE) ++ break; /* fatal */ ++ ++ if (items[s].flags & SEARCHED_ITEM_FLAG_LOOP && connected) ++ { ++ connected = 0; ++ goto loop; ++ } ++ ++ free_handle_list (); ++ } ++ ++ free_handle_list (); ++ ++ if (total_connected) ++ grub_efidisk_reenumerate_disks (); ++ ++ return grub_err; ++} ++ ++static grub_command_t cmd; ++ ++GRUB_MOD_INIT(connectefi) ++{ ++ cmd = grub_register_command ("connectefi", grub_cmd_connectefi, ++ N_("pciroot|scsi"), ++ N_("Connect EFI handles." ++ " If 'pciroot' is specified, connect PCI" ++ " root EFI handles recursively." ++ " If 'scsi' is specified, connect SCSI" ++ " I/O EFI handles recursively.")); ++} ++ ++GRUB_MOD_FINI(connectefi) ++{ ++ grub_unregister_command (cmd); ++} +diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c +index d1ce99af43..f2d2430e66 100644 +--- a/grub-core/commands/efi/lsefi.c ++++ b/grub-core/commands/efi/lsefi.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c +index fe8ba6e6c9..062143dfff 100644 +--- a/grub-core/disk/efi/efidisk.c ++++ b/grub-core/disk/efi/efidisk.c +@@ -396,6 +396,19 @@ enumerate_disks (void) + free_devices (devices); + } + ++void ++grub_efidisk_reenumerate_disks (void) ++{ ++ free_devices (fd_devices); ++ free_devices (hd_devices); ++ free_devices (cd_devices); ++ fd_devices = 0; ++ hd_devices = 0; ++ cd_devices = 0; ++ ++ enumerate_disks (); ++} ++ + static int + grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 14bc10eb56..7fcca69c17 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -95,6 +95,19 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, + return buffer; + } + ++grub_efi_status_t ++grub_efi_connect_controller (grub_efi_handle_t controller_handle, ++ grub_efi_handle_t *driver_image_handle, ++ grub_efi_device_path_protocol_t *remaining_device_path, ++ grub_efi_boolean_t recursive) ++{ ++ grub_efi_boot_services_t *b; ++ ++ b = grub_efi_system_table->boot_services; ++ return efi_call_4 (b->connect_controller, controller_handle, ++ driver_image_handle, remaining_device_path, recursive); ++} ++ + void * + grub_efi_open_protocol (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, +diff --git a/include/grub/efi/disk.h b/include/grub/efi/disk.h +index 254475c842..6845c2f1fd 100644 +--- a/include/grub/efi/disk.h ++++ b/include/grub/efi/disk.h +@@ -27,6 +27,8 @@ grub_efi_handle_t + EXPORT_FUNC(grub_efidisk_get_device_handle) (grub_disk_t disk); + char *EXPORT_FUNC(grub_efidisk_get_device_name) (grub_efi_handle_t *handle); + ++void EXPORT_FUNC(grub_efidisk_reenumerate_disks) (void); ++ + void grub_efidisk_init (void); + void grub_efidisk_fini (void); + +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 8dfc89a33b..ec52083c49 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -41,6 +41,11 @@ EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type, + grub_efi_guid_t *protocol, + void *search_key, + grub_efi_uintn_t *num_handles); ++grub_efi_status_t ++EXPORT_FUNC(grub_efi_connect_controller) (grub_efi_handle_t controller_handle, ++ grub_efi_handle_t *driver_image_handle, ++ grub_efi_device_path_protocol_t *remaining_device_path, ++ grub_efi_boolean_t recursive); + void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle, + grub_efi_guid_t *protocol, + grub_efi_uint32_t attributes); +diff --git a/NEWS b/NEWS +index 73b8492bc4..d7c1d23aed 100644 +--- a/NEWS ++++ b/NEWS +@@ -98,7 +98,7 @@ New in 2.02: + * Prefer pmtimer for TSC calibration. + + * New/improved platform support: +- * New `efifwsetup' and `lsefi' commands on EFI platforms. ++ * New `efifwsetup', `lsefi' and `connectefi` commands on EFI platforms. + * New `cmosdump' and `cmosset' commands on platforms with CMOS support. + * New command `pcidump' for PCI platforms. + * Improve opcode parsing in ACPI halt implementation. diff --git a/SOURCES/0206-Allow-chainloading-EFI-apps-from-loop-mounts.patch b/SOURCES/0206-Allow-chainloading-EFI-apps-from-loop-mounts.patch deleted file mode 100644 index e48f102..0000000 --- a/SOURCES/0206-Allow-chainloading-EFI-apps-from-loop-mounts.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dimitri John Ledkov -Date: Fri, 11 Jun 2021 13:51:20 +0200 -Subject: [PATCH] Allow chainloading EFI apps from loop mounts. - ---- - grub-core/disk/loopback.c | 9 +-------- - grub-core/loader/efi/chainloader.c | 23 +++++++++++++++++++++++ - include/grub/loopback.h | 30 ++++++++++++++++++++++++++++++ - 3 files changed, 54 insertions(+), 8 deletions(-) - create mode 100644 include/grub/loopback.h - -diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c -index 41bebd14fe3..99f47924ec2 100644 ---- a/grub-core/disk/loopback.c -+++ b/grub-core/disk/loopback.c -@@ -21,20 +21,13 @@ - #include - #include - #include -+#include - #include - #include - #include - - GRUB_MOD_LICENSE ("GPLv3+"); - --struct grub_loopback --{ -- char *devname; -- grub_file_t file; -- struct grub_loopback *next; -- unsigned long id; --}; -- - static struct grub_loopback *loopback_list; - static unsigned long last_id = 0; - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index d41e8ea14a8..3af6b122926 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -901,6 +902,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_efi_status_t status; - grub_efi_boot_services_t *b; - grub_device_t dev = 0; -+ grub_device_t orig_dev = 0; - grub_efi_device_path_t *dp = 0; - char *filename; - void *boot_image = 0; -@@ -958,6 +960,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - if (! dev) - goto fail; - -+ /* if device is loopback, use underlying dev */ -+ if (dev->disk->dev->id == GRUB_DISK_DEVICE_LOOPBACK_ID) -+ { -+ struct grub_loopback *d; -+ orig_dev = dev; -+ d = dev->disk->data; -+ dev = d->file->device; -+ } -+ - if (dev->disk) - dev_handle = grub_efidisk_get_device_handle (dev->disk); - else if (dev->net && dev->net->server) -@@ -1065,6 +1076,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -+ if (orig_dev) -+ { -+ dev = orig_dev; -+ orig_dev = 0; -+ } -+ - rc = grub_linuxefi_secure_validate((void *)(unsigned long)address, fsize); - grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); - if (rc > 0) -@@ -1087,6 +1104,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - // -1 fall-through to fail - - fail: -+ if (orig_dev) -+ { -+ dev = orig_dev; -+ orig_dev = 0; -+ } -+ - if (dev) - grub_device_close (dev); - -diff --git a/include/grub/loopback.h b/include/grub/loopback.h -new file mode 100644 -index 00000000000..3b9a9e32e80 ---- /dev/null -+++ b/include/grub/loopback.h -@@ -0,0 +1,30 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2019 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_LOOPBACK_HEADER -+#define GRUB_LOOPBACK_HEADER 1 -+ -+struct grub_loopback -+{ -+ char *devname; -+ grub_file_t file; -+ struct grub_loopback *next; -+ unsigned long id; -+}; -+ -+#endif /* ! GRUB_LOOPBACK_HEADER */ diff --git a/SOURCES/0206-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch b/SOURCES/0206-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch new file mode 100644 index 0000000..4fe8adf --- /dev/null +++ b/SOURCES/0206-grub-core-loader-i386-efi-linux.c-do-not-validate-ke.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Thu, 3 Mar 2022 13:10:56 +0100 +Subject: [PATCH] grub-core/loader/i386/efi/linux.c: do not validate kernels + twice + +On codebases that have shim-lock-verifier built into the grub core +(like 2.06 upstream), shim-lock-verifier is in enforcing mode when +booted with secureboot. It means that grub_cmd_linux() command +attempts to perform shim validate upon opening linux kernel image, +including kernel measurement. And the verifier correctly returns file +open error when shim validate protocol is not present or shim fails to +validate the kernel. + +This makes the call to grub_linuxefi_secure_validate() redundant, but +also harmful. As validating the kernel image twice, extends the PCRs +with the same measurement twice. Which breaks existing sealing +policies when upgrading from grub2.04+rhboot+sb+linuxefi to +grub2.06+rhboot+sb+linuxefi builds. It is also incorrect to measure +the kernel twice. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +This patch is tested to ensure that unsigned kernels are not possible +to boot in secureboot mode when shim rejects kernel, or shim protocol +is missing, and that the measurements become stable once again. The +above also ensures that CVE-2020-15705 is not reintroduced. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/i386/efi/linux.c | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 3cf0f9b330..941df6400b 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -30,7 +30,6 @@ + #include + #include + #include +-#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -278,7 +277,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_ssize_t start, filelen; + void *kernel = NULL; + int setup_header_end_offset; +- int rc; + + grub_dl_ref (my_mod); + +@@ -308,17 +306,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) +- { +- rc = grub_linuxefi_secure_validate (kernel, filelen); +- if (rc <= 0) +- { +- grub_error (GRUB_ERR_INVALID_COMMAND, +- N_("%s has invalid signature"), argv[0]); +- goto fail; +- } +- } +- + lh = (struct linux_i386_kernel_header *)kernel; + grub_dprintf ("linux", "original lh is at %p\n", kernel); + diff --git a/SOURCES/0207-efinet-Add-DHCP-proxy-support.patch b/SOURCES/0207-efinet-Add-DHCP-proxy-support.patch deleted file mode 100644 index a8755a3..0000000 --- a/SOURCES/0207-efinet-Add-DHCP-proxy-support.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ian Page Hands -Date: Tue, 8 Jun 2021 13:48:56 -0400 -Subject: [PATCH] efinet: Add DHCP proxy support - -If a proxyDHCP configuration is used, the server name, server IP and boot -file values should be taken from the DHCP proxy offer instead of the DHCP -server ack packet. Currently that case is not handled, add support for it. ---- - grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++-- - 1 file changed, 23 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c -index e11d759f19a..1a24f38a21a 100644 ---- a/grub-core/net/drivers/efi/efinet.c -+++ b/grub-core/net/drivers/efi/efinet.c -@@ -850,10 +850,31 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, - else - { - grub_dprintf ("efinet", "using ipv4 and dhcp\n"); -+ -+ struct grub_net_bootp_packet *dhcp_ack = &pxe_mode->dhcp_ack; -+ -+ if (pxe_mode->proxy_offer_received) -+ { -+ grub_dprintf ("efinet", "proxy offer receive"); -+ struct grub_net_bootp_packet *proxy_offer = &pxe_mode->proxy_offer; -+ -+ if (proxy_offer && dhcp_ack->boot_file[0] == '\0') -+ { -+ grub_dprintf ("efinet", "setting values from proxy offer"); -+ /* Here we got a proxy offer and the dhcp_ack has a nil boot_file -+ * Copy the proxy DHCP offer details into the bootp_packet we are -+ * sending forward as they are the deatils we need. -+ */ -+ *dhcp_ack->server_name = *proxy_offer->server_name; -+ *dhcp_ack->boot_file = *proxy_offer->boot_file; -+ dhcp_ack->server_ip = proxy_offer->server_ip; -+ } -+ } -+ - grub_net_configure_by_dhcp_ack (card->name, card, 0, - (struct grub_net_bootp_packet *) -- packet_buf, -- packet_bufsz, -+ &pxe_mode->dhcp_ack, -+ sizeof (pxe_mode->dhcp_ack), - 1, device, path); - grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); - } diff --git a/SOURCES/0207-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch b/SOURCES/0207-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch new file mode 100644 index 0000000..5b450f9 --- /dev/null +++ b/SOURCES/0207-grub-core-loader-arm64-linux.c-do-not-validate-kerne.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 4 Mar 2022 11:29:31 +0100 +Subject: [PATCH] grub-core/loader/arm64/linux.c: do not validate kernel twice + +Call to grub_file_open(, GRUB_FILE_TYPE_LINUX_KERNEL) already passes +the kernel file through shim-lock verifier when secureboot is on. Thus +there is no need to validate the kernel image again. And when doing so +again, duplicate PCR measurement is performed, breaking measurements +compatibility with 2.04+linuxefi. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/arm64/linux.c | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index f18d90bd74..d2af47c2c0 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -341,7 +340,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_off_t filelen; + grub_uint32_t align; + void *kernel = NULL; +- int rc; + + grub_dl_ref (my_mod); + +@@ -370,17 +368,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) +- { +- rc = grub_linuxefi_secure_validate (kernel, filelen); +- if (rc <= 0) +- { +- grub_error (GRUB_ERR_INVALID_COMMAND, +- N_("%s has invalid signature"), argv[0]); +- goto fail; +- } +- } +- + if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) + goto fail; + if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) diff --git a/SOURCES/0208-fs-ext2-Ignore-checksum-seed-incompat-feature.patch b/SOURCES/0208-fs-ext2-Ignore-checksum-seed-incompat-feature.patch deleted file mode 100644 index b4a5fd4..0000000 --- a/SOURCES/0208-fs-ext2-Ignore-checksum-seed-incompat-feature.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Fri, 11 Jun 2021 00:01:29 +0200 -Subject: [PATCH] fs/ext2: Ignore checksum seed incompat feature - -This incompat feature is used to denote that the filesystem stored its -metadata checksum seed in the superblock. This is used to allow tune2fs -to change the UUID on a mounted metadata_csum filesystem without having -to rewrite all the disk metadata. - -But GRUB doesn't use the metadata checksum in anyway, so can just ignore -this feature if is enabled. This is consistent with GRUB filesystem code -in general which just does a best effort to access the filesystem's data. - -It may be removed from the ignored list in the future if supports to do -metadata checksumming verification is added to the read-only FS driver. - -Suggested-by: Eric Sandeen -Suggested-by: Lukas Czerner -Signed-off-by: Javier Martinez Canillas ---- - grub-core/fs/ext2.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c -index e7dd78e6635..731d346f886 100644 ---- a/grub-core/fs/ext2.c -+++ b/grub-core/fs/ext2.c -@@ -103,6 +103,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 - #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 - #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 -+#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000 - #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 - - /* The set of back-incompatible features this driver DOES support. Add (OR) -@@ -123,9 +124,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); - * mmp: Not really back-incompatible - was added as such to - * avoid multiple read-write mounts. Safe to ignore for this - * RO driver. -+ * checksum seed: Not really back-incompatible - was added to allow tools -+ * such as tune2fs to change the UUID on a mounted metadata -+ * checksummed filesystem. Safe to ignore for now since the -+ * driver doesn't support checksum verification. But it must -+ * be removed from this list if that support is added later. -+ * - */ - #define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \ -- | EXT4_FEATURE_INCOMPAT_MMP) -+ | EXT4_FEATURE_INCOMPAT_MMP \ -+ | EXT4_FEATURE_INCOMPAT_CSUM_SEED) - - - #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U diff --git a/SOURCES/0208-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch b/SOURCES/0208-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch new file mode 100644 index 0000000..4c56d60 --- /dev/null +++ b/SOURCES/0208-grub-core-loader-efi-chainloader.c-do-not-validate-c.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 4 Mar 2022 09:31:43 +0100 +Subject: [PATCH] grub-core/loader/efi/chainloader.c: do not validate + chainloader twice + +On secureboot systems, with shimlock verifier, call to +grub_file_open(, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE) will already +pass the chainloader target through shim-lock protocol verify +call. And create a TPM measurement. If verification fails, +grub_cmd_chainloader will fail at file open time. + +This makes previous code paths for negative, and zero return codes +from grub_linuxefi_secure_validate unreachable under secureboot. But +also breaking measurements compatibility with 2.04+linuxefi codebases, +as the chainloader file is passed through shim_lock->verify() twice +(via verifier & direct call to grub_linuxefi_secure_validate) +extending the PCRs twice. + +This reduces grub_loader options to perform +grub_secureboot_chainloader when secureboot is on, and otherwise +attempt grub_chainloader_boot. + +It means that booting with secureboot off, yet still with shim (which +always verifies things successfully), will stop choosing +grub_secureboot_chainloader, and opting for a more regular +loadimage/startimage codepath. If we want to use the +grub_secureboot_chainloader codepath in such scenarios we should adapt +the code to simply check for shim_lock protocol presence / +shim_lock->context() success?! But I am not sure if that is necessary. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/efi/chainloader.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 3af6b12292..644cd2e56f 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -906,7 +906,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_device_path_t *dp = 0; + char *filename; + void *boot_image = 0; +- int rc; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -1082,9 +1081,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + orig_dev = 0; + } + +- rc = grub_linuxefi_secure_validate((void *)(unsigned long)address, fsize); +- grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); +- if (rc > 0) ++ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { + grub_file_close (file); + grub_device_close (dev); +@@ -1092,7 +1089,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_secureboot_chainloader_unload, 0); + return 0; + } +- else if (rc == 0) ++ else + { + grub_load_and_start_image(boot_image); + grub_file_close (file); +@@ -1101,7 +1098,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + return 0; + } +- // -1 fall-through to fail + + fail: + if (orig_dev) diff --git a/SOURCES/0209-Don-t-update-the-cmdline-when-generating-legacy-menu.patch b/SOURCES/0209-Don-t-update-the-cmdline-when-generating-legacy-menu.patch deleted file mode 100644 index c55b7e3..0000000 --- a/SOURCES/0209-Don-t-update-the-cmdline-when-generating-legacy-menu.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Thu, 17 Jun 2021 14:31:42 +0200 -Subject: [PATCH] Don't update the cmdline when generating legacy menuentry - commands - -On OPAL ppc64le machines with an old petitboot version that doesn't have -support to parse BLS snippets, the grub2-mkconfig script is executed to -generate menuentry commands from the BLS snippets. - -In this case, the script is executed with the --no-grubenv-update option -that indicates that no side effects should happen when running the script. - -But the options field in the BLS snippets are updated regardless, only do -the update if --no-grubenv-update was not used. - -Signed-off-by: Javier Martinez Canillas ---- - util/grub.d/10_linux.in | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 68adb55d893..c9296154f51 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -261,7 +261,9 @@ if [ -z "\${kernelopts}" ]; then - fi - EOF - -- update_bls_cmdline -+ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then -+ update_bls_cmdline -+ fi - - if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then - populate_menu diff --git a/SOURCES/0209-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch b/SOURCES/0209-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch new file mode 100644 index 0000000..c683fcb --- /dev/null +++ b/SOURCES/0209-grub-core-loader-efi-linux.c-drop-now-unused-grub_li.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Fri, 4 Mar 2022 11:36:09 +0100 +Subject: [PATCH] grub-core/loader/efi/linux.c: drop now unused + grub_linuxefi_secure_validate + +Drop the now unused grub_linuxefi_secure_validate() as all prior users +of this API now rely on the shim-lock-verifier codepath instead. + +This patch must not be ported to older editions of grub code bases +that do not have verifiers framework, or it is not builtin, or +shim-lock-verifier is an optional module. + +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/efi/linux.c | 40 ---------------------------------------- + include/grub/efi/linux.h | 2 -- + 2 files changed, 42 deletions(-) + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 9260731c10..9265cf4200 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -24,46 +24,6 @@ + #include + #include + +-#define SHIM_LOCK_GUID \ +- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } +- +-struct grub_efi_shim_lock +-{ +- grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); +-}; +-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; +- +-// Returns 1 on success, -1 on error, 0 when not available +-int +-grub_linuxefi_secure_validate (void *data, grub_uint32_t size) +-{ +- grub_efi_guid_t guid = SHIM_LOCK_GUID; +- grub_efi_shim_lock_t *shim_lock; +- grub_efi_status_t status; +- +- shim_lock = grub_efi_locate_protocol(&guid, NULL); +- grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); +- if (!shim_lock) +- { +- grub_dprintf ("secureboot", "shim not available\n"); +- return 0; +- } +- +- grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n"); +- status = shim_lock->verify (data, size); +- grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", (long int)status); +- if (status == GRUB_EFI_SUCCESS) +- { +- grub_dprintf ("secureboot", "Kernel signature verification passed\n"); +- return 1; +- } +- +- grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n", +- (unsigned long) status); +- +- return -1; +-} +- + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + +diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h +index 0033d9305a..887b02fd9f 100644 +--- a/include/grub/efi/linux.h ++++ b/include/grub/efi/linux.h +@@ -22,8 +22,6 @@ + #include + #include + +-int +-EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); + grub_err_t + EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, + void *kernel_param); diff --git a/SOURCES/0210-Suppress-gettext-error-message.patch b/SOURCES/0210-Suppress-gettext-error-message.patch deleted file mode 100644 index c57e7ff..0000000 --- a/SOURCES/0210-Suppress-gettext-error-message.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paulo Flabiano Smorigo -Date: Tue, 29 Jun 2021 13:17:42 +0200 -Subject: [PATCH] Suppress gettext error message - -Colin Watson's patch from comment #11 on the upstream bug: -https://savannah.gnu.org/bugs/?35880#comment11 - -Resolves: rhbz#1592124 - -Signed-off-by: Paulo Flabiano Smorigo ---- - grub-core/gettext/gettext.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c -index 84d520cd494..87a912ac6e5 100644 ---- a/grub-core/gettext/gettext.c -+++ b/grub-core/gettext/gettext.c -@@ -424,6 +424,13 @@ grub_gettext_init_ext (struct grub_gettext_context *ctx, - grub_free (lang); - } - -+ /* If no translations are available, fall back to untranslated text. */ -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ - if (locale[0] == 'e' && locale[1] == 'n' - && (locale[2] == '\0' || locale[2] == '_')) - grub_errno = err = GRUB_ERR_NONE; diff --git a/SOURCES/0210-powerpc-prefix-detection-support-device-names-with-c.patch b/SOURCES/0210-powerpc-prefix-detection-support-device-names-with-c.patch new file mode 100644 index 0000000..1c16fd3 --- /dev/null +++ b/SOURCES/0210-powerpc-prefix-detection-support-device-names-with-c.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 24 Mar 2022 14:34:32 +1100 +Subject: [PATCH] powerpc: prefix detection: support device names with commas + +Frustratingly, the device name itself can contain an embedded comma: +e.g /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b + +So my previous approach was wrong: we cannot rely upon the presence +of a comma to say that a partition has been specified! + +It turns out for prefixes like (,gpt2)/grub2 we really want to make +up a full (device,partition)/patch prefix, because root discovery code +in 10_linux will reset the root variable and use search to fill it again. +If you have run grub-install, you probably don't have search built in, +and if you don't have prefix containing (device,partition), grub will +construct ($root)$prefix/powerpc-ieee1275/search.mod - but because $root +has just been changed, this will no longer work, and the boot will fail! + +Retain the gist of the logic, but instead of looking for a comma, look for +a leading '('. This matches the earlier code better anyway. + +There's certainly a better fix to be had. But any time you chose to build +with a bare prefix like '/grub2', you're almost certainly going to build in +search anyway, so this will do. + +Signed-off-by: Daniel Axtens +--- + grub-core/kern/main.c | 27 +++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 993b8a8598..e94a2f78fb 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -242,14 +242,29 @@ grub_set_prefix_and_root (void) + what sorts of paths represent disks with partition tables and those + without partition tables. + +- So we act unless there is a comma in the device, which would indicate +- a partition has already been specified. ++ - Frustratingly, the device name itself can contain an embedded comma: ++ /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b ++ So we cannot even rely upon the presence of a comma to say that a ++ partition has been specified! + +- (If we only have a path, the code in normal to discover config files +- will try both without partitions and then with any partitions so we +- will cover both CDs and HDs.) ++ If we only have a path in $prefix, the code in normal to discover ++ config files will try all disks, both without partitions and then with ++ any partitions so we will cover both CDs and HDs. ++ ++ However, it doesn't then set the prefix to be something like ++ (discovered partition)/path, and so it is fragile against runtime ++ changes to $root. For example some of the stuff done in 10_linux to ++ reload $root sets root differently and then uses search to find it ++ again. If the search module is not built in, when we change root, grub ++ will look in (new root)/path/powerpc-ieee1275, that won't work, and we ++ will not be able to load the search module and the boot will fail. ++ ++ This is particularly likely to hit us in the grub-install ++ (,msdos2)/grub2 case, so we act unless the supplied prefix starts with ++ '(', which would likely indicate a partition has already been ++ specified. + */ +- if (grub_strchr (device, ',') == NULL) ++ if (prefix && prefix[0] != '(') + grub_env_set ("prefix", path); + else + #endif diff --git a/SOURCES/0211-grub-boot-success.timer-Only-run-if-not-in-a-contain.patch b/SOURCES/0211-grub-boot-success.timer-Only-run-if-not-in-a-contain.patch deleted file mode 100644 index 61d0f6d..0000000 --- a/SOURCES/0211-grub-boot-success.timer-Only-run-if-not-in-a-contain.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gena Makhomed -Date: Thu, 1 Jul 2021 01:07:46 +0200 -Subject: [PATCH] grub-boot-success.timer: Only run if not in a container - -The grub-boot-success.timer should be disabled inside a container since it -leads to the following error: - -Jan 09 22:56:38 test sshd[8786]: pam_unix(sshd:session): session opened for user www(uid=1000) by (uid=0) -Jan 09 22:58:39 test systemd[8857]: Starting Mark boot as successful... -Jan 09 22:58:39 test systemd[8857]: grub-boot-success.service: Main process exited, code=exited, status=1/FAILURE -Jan 09 22:58:39 test systemd[8857]: grub-boot-success.service: Failed with result 'exit-code'. -Jan 09 22:58:39 test systemd[8857]: Failed to start Mark boot as successful. -Jan 09 22:58:39 test grub2-set-bootflag[10034]: Error canonicalizing /boot/grub2/grubenv filename: No such file or directory - -Resolves: rhbz#1914571 ---- - docs/grub-boot-success.timer | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/docs/grub-boot-success.timer b/docs/grub-boot-success.timer -index 5d8fcba21aa..406f1720056 100644 ---- a/docs/grub-boot-success.timer -+++ b/docs/grub-boot-success.timer -@@ -1,6 +1,7 @@ - [Unit] - Description=Mark boot as successful after the user session has run 2 minutes - ConditionUser=!@system -+ConditionVirtualization=!container - - [Timer] - OnActiveSec=2min diff --git a/SOURCES/0211-make-ofdisk_retries-optional.patch b/SOURCES/0211-make-ofdisk_retries-optional.patch new file mode 100644 index 0000000..fce9702 --- /dev/null +++ b/SOURCES/0211-make-ofdisk_retries-optional.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Thu, 24 Mar 2022 13:14:42 -0400 +Subject: [PATCH] make ofdisk_retries optional + +The feature Retry on Fail added to GRUB can cause a LPM to take +longer if the SAN is slow. + +When a LPM to external site occur, the path of the disk can change +and thus the disk search function on grub can take some time since +it is used as a hint. This can cause the Retry on Fail feature to +try to access the disk 20x times (since this is hardcoded number) +and, if the SAN is slow, the boot time can increase a lot. +In some situations not acceptable. + +The following patch enables a configuration at user space of the +maximum number of retries we want for this feature. + +The variable ofdisk_retries should be set using grub2-editenv +and will be checked by retry function. If the variable is not set, +so the default number of retries will be used instead. +--- + include/grub/ieee1275/ofdisk.h | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h +index 7d2d540930..0074d55eee 100644 +--- a/include/grub/ieee1275/ofdisk.h ++++ b/include/grub/ieee1275/ofdisk.h +@@ -25,7 +25,12 @@ extern void grub_ofdisk_fini (void); + #define MAX_RETRIES 20 + + +-#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ ++#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) \ ++ unsigned max_retries = MAX_RETRIES; \ ++ if(grub_env_get("ofdisk_retries") != NULL) \ ++ max_retries = grub_strtoul(grub_env_get("ofdisk_retries"), 0, 10)+1; \ ++ grub_dprintf("ofdisk","MAX_RETRIES set to %u\n",max_retries); \ ++ unsigned retry_i=0;for(retry_i=0; retry_i < max_retries; retry_i++){ \ + if(!grub_ieee1275_open(device, last_ihandle)) \ + break; \ + grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } diff --git a/SOURCES/0212-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch b/SOURCES/0212-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch deleted file mode 100644 index 7ecea22..0000000 --- a/SOURCES/0212-grub-set-password-Always-use-boot-grub2-user.cfg-as-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 5 Jul 2021 18:24:22 +0200 -Subject: [PATCH] grub-set-password: Always use /boot/grub2/user.cfg as - password default - -The GRUB configuration file is always placed in /boot/grub2/ now, even for -EFI. But the tool is still creating the user.cfg in the ESP and not there. - -Resolves: rhbz#1955294 - -Signed-off-by: Javier Martinez Canillas ---- - util/grub-set-password.in | 9 +-------- - 1 file changed, 1 insertion(+), 8 deletions(-) - -diff --git a/util/grub-set-password.in b/util/grub-set-password.in -index c0b5ebbfdc5..d8005e5a142 100644 ---- a/util/grub-set-password.in -+++ b/util/grub-set-password.in -@@ -1,11 +1,6 @@ - #!/bin/sh -e - --EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g') --if [ -d /sys/firmware/efi/efivars/ ]; then -- grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` --else -- grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` --fi -+grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` - - PACKAGE_VERSION="@PACKAGE_VERSION@" - PACKAGE_NAME="@PACKAGE_NAME@" -@@ -116,8 +111,6 @@ if [ -z "${MYPASS}" ]; then - exit 1 - fi - --# on the ESP, these will fail to set the permissions, but it's okay because --# the directory is protected. - install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : - chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : - echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" diff --git a/SOURCES/0212-loader-efi-chainloader-grub_load_and_start_image-doe.patch b/SOURCES/0212-loader-efi-chainloader-grub_load_and_start_image-doe.patch new file mode 100644 index 0000000..f61ed28 --- /dev/null +++ b/SOURCES/0212-loader-efi-chainloader-grub_load_and_start_image-doe.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Thu, 28 Apr 2022 21:53:36 +0100 +Subject: [PATCH] loader/efi/chainloader: grub_load_and_start_image doesn't + load and start + +grub_load_and_start_image only loads an image - it still requires the +caller to start it. This renames it to grub_load_image. + +It's called from 2 places: +- grub_cmd_chainloader when not using the shim protocol. +- grub_secureboot_chainloader_boot if handle_image returns an error. +In this case, the image is loaded and then nothing else happens which +seems strange. I assume the intention is that it falls back to LoadImage +and StartImage if handle_image fails, so I've made it do that. + +Signed-off-by: Chris Coulson +(cherry picked from commit b4d70820a65c00561045856b7b8355461a9545f6) +--- + grub-core/loader/efi/chainloader.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 644cd2e56f..d3bf02ed8a 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -841,7 +841,7 @@ grub_secureboot_chainloader_unload (void) + } + + static grub_err_t +-grub_load_and_start_image(void *boot_image) ++grub_load_image(void *boot_image) + { + grub_efi_boot_services_t *b; + grub_efi_status_t status; +@@ -883,13 +883,23 @@ grub_load_and_start_image(void *boot_image) + static grub_err_t + grub_secureboot_chainloader_boot (void) + { ++ grub_efi_boot_services_t *b; + int rc; ++ + rc = handle_image ((void *)(unsigned long)address, fsize); + if (rc == 0) + { +- grub_load_and_start_image((void *)(unsigned long)address); ++ /* We weren't able to attempt to execute the image, so fall back ++ * to LoadImage / StartImage. ++ */ ++ rc = grub_load_image((void *)(unsigned long)address); ++ if (rc == 0) ++ grub_chainloader_boot (); + } + ++ b = grub_efi_system_table->boot_services; ++ efi_call_1 (b->unload_image, image_handle); ++ + grub_loader_unset (); + return grub_errno; + } +@@ -1091,7 +1101,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + else + { +- grub_load_and_start_image(boot_image); ++ grub_load_image(boot_image); + grub_file_close (file); + grub_device_close (dev); + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); diff --git a/SOURCES/0213-Remove-outdated-URL-for-BLS-document.patch b/SOURCES/0213-Remove-outdated-URL-for-BLS-document.patch deleted file mode 100644 index d380fe8..0000000 --- a/SOURCES/0213-Remove-outdated-URL-for-BLS-document.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 5 Jul 2021 19:00:25 +0200 -Subject: [PATCH] Remove outdated URL for BLS document - -The document was moved to https://systemd.io/BOOT_LOADER_SPECIFICATION/, -update the URL accordingly to point to the current location. - -Resolves: rhbz#1926453 - -Signed-off-by: Javier Martinez Canillas ---- - util/grub.d/10_linux.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index c9296154f51..6ee0a2cf3d0 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -96,7 +96,7 @@ cat < +Date: Fri, 29 Apr 2022 21:13:08 +0100 +Subject: [PATCH] loader/efi/chainloader: simplify the loader state + +When not using the shim lock protocol, the chainloader command retains +the source buffer and device path passed to LoadImage, requiring the +unload hook passed to grub_loader_set to free them. It isn't required +to retain this state though - they aren't required by StartImage or +anything else in the boot hook, so clean them up before +grub_cmd_chainloader finishes. + +This also wraps the loader state when using the shim lock protocol +inside a struct. + +Signed-off-by: Chris Coulson +(cherry picked from commit fa39862933b3be1553a580a3a5c28073257d8046) +[rharwood: fix unitialized handle and double-frees of file/dev] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/efi/chainloader.c | 160 +++++++++++++++++++++++-------------- + 1 file changed, 102 insertions(+), 58 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index d3bf02ed8a..3342492ff1 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -48,38 +48,21 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; + +-static grub_efi_physical_address_t address; +-static grub_efi_uintn_t pages; +-static grub_ssize_t fsize; +-static grub_efi_device_path_t *file_path; + static grub_efi_handle_t image_handle; +-static grub_efi_char16_t *cmdline; +-static grub_ssize_t cmdline_len; +-static grub_efi_handle_t dev_handle; + +-static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); ++struct grub_secureboot_chainloader_context { ++ grub_efi_physical_address_t address; ++ grub_efi_uintn_t pages; ++ grub_ssize_t fsize; ++ grub_efi_device_path_t *file_path; ++ grub_efi_char16_t *cmdline; ++ grub_ssize_t cmdline_len; ++ grub_efi_handle_t dev_handle; ++}; ++static struct grub_secureboot_chainloader_context *sb_context; + + static grub_err_t +-grub_chainloader_unload (void) +-{ +- grub_efi_boot_services_t *b; +- +- b = grub_efi_system_table->boot_services; +- efi_call_1 (b->unload_image, image_handle); +- grub_efi_free_pages (address, pages); +- +- grub_free (file_path); +- grub_free (cmdline); +- cmdline = 0; +- file_path = 0; +- dev_handle = 0; +- +- grub_dl_unref (my_mod); +- return GRUB_ERR_NONE; +-} +- +-static grub_err_t +-grub_chainloader_boot (void) ++grub_start_image (grub_efi_handle_t handle) + { + grub_efi_boot_services_t *b; + grub_efi_status_t status; +@@ -87,7 +70,7 @@ grub_chainloader_boot (void) + grub_efi_char16_t *exit_data = NULL; + + b = grub_efi_system_table->boot_services; +- status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data); ++ status = efi_call_3 (b->start_image, handle, &exit_data_size, &exit_data); + if (status != GRUB_EFI_SUCCESS) + { + if (exit_data) +@@ -111,11 +94,37 @@ grub_chainloader_boot (void) + if (exit_data) + grub_efi_free_pool (exit_data); + +- grub_loader_unset (); +- + return grub_errno; + } + ++static grub_err_t ++grub_chainloader_unload (void) ++{ ++ grub_efi_loaded_image_t *loaded_image; ++ grub_efi_boot_services_t *b; ++ ++ loaded_image = grub_efi_get_loaded_image (image_handle); ++ if (loaded_image != NULL) ++ grub_free (loaded_image->load_options); ++ ++ b = grub_efi_system_table->boot_services; ++ efi_call_1 (b->unload_image, image_handle); ++ ++ grub_dl_unref (my_mod); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_chainloader_boot (void) ++{ ++ grub_err_t err; ++ ++ err = grub_start_image (image_handle); ++ ++ grub_loader_unset (); ++ return err; ++} ++ + static grub_err_t + copy_file_path (grub_efi_file_path_device_path_t *fp, + const char *str, grub_efi_uint16_t len) +@@ -150,7 +159,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) + char *dir_start; + char *dir_end; + grub_size_t size; +- grub_efi_device_path_t *d; ++ grub_efi_device_path_t *d, *file_path; + + dir_start = grub_strchr (filename, ')'); + if (! dir_start) +@@ -526,10 +535,12 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp) + } + + static grub_efi_boolean_t +-handle_image (void *data, grub_efi_uint32_t datasize) ++handle_image (struct grub_secureboot_chainloader_context *load_context) + { + grub_efi_loaded_image_t *li, li_bak; + grub_efi_status_t efi_status; ++ void *data = (void *)(unsigned long)load_context->address; ++ grub_efi_uint32_t datasize = load_context->fsize; + void *buffer = NULL; + char *buffer_aligned = NULL; + grub_efi_uint32_t i; +@@ -540,6 +551,7 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_uint32_t buffer_size; + int found_entry_point = 0; + int rc; ++ grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); + + rc = read_header (data, datasize, &context); + if (rc < 0) +@@ -797,10 +809,10 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); + li->image_base = buffer_aligned; + li->image_size = context.image_size; +- li->load_options = cmdline; +- li->load_options_size = cmdline_len; +- li->file_path = grub_efi_get_media_file_path (file_path); +- li->device_handle = dev_handle; ++ li->load_options = load_context->cmdline; ++ li->load_options_size = load_context->cmdline_len; ++ li->file_path = grub_efi_get_media_file_path (load_context->file_path); ++ li->device_handle = load_context->dev_handle; + if (!li->file_path) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); +@@ -829,19 +841,22 @@ error_exit: + static grub_err_t + grub_secureboot_chainloader_unload (void) + { +- grub_efi_free_pages (address, pages); +- grub_free (file_path); +- grub_free (cmdline); +- cmdline = 0; +- file_path = 0; +- dev_handle = 0; ++ grub_efi_free_pages (sb_context->address, sb_context->pages); ++ grub_free (sb_context->file_path); ++ grub_free (sb_context->cmdline); ++ grub_free (sb_context); ++ ++ sb_context = 0; + + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; + } + + static grub_err_t +-grub_load_image(void *boot_image) ++grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, ++ grub_efi_uintn_t image_size, grub_efi_handle_t dev_handle, ++ grub_efi_char16_t *cmdline, grub_ssize_t cmdline_len, ++ grub_efi_handle_t *image_handle_out) + { + grub_efi_boot_services_t *b; + grub_efi_status_t status; +@@ -850,7 +865,7 @@ grub_load_image(void *boot_image) + b = grub_efi_system_table->boot_services; + + status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, +- boot_image, fsize, &image_handle); ++ boot_image, image_size, image_handle_out); + if (status != GRUB_EFI_SUCCESS) + { + if (status == GRUB_EFI_OUT_OF_RESOURCES) +@@ -863,7 +878,7 @@ grub_load_image(void *boot_image) + /* LoadImage does not set a device handler when the image is + loaded from memory, so it is necessary to set it explicitly here. + This is a mess. */ +- loaded_image = grub_efi_get_loaded_image (image_handle); ++ loaded_image = grub_efi_get_loaded_image (*image_handle_out); + if (! loaded_image) + { + grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); +@@ -885,20 +900,25 @@ grub_secureboot_chainloader_boot (void) + { + grub_efi_boot_services_t *b; + int rc; ++ grub_efi_handle_t handle = 0; + +- rc = handle_image ((void *)(unsigned long)address, fsize); ++ rc = handle_image (sb_context); + if (rc == 0) + { + /* We weren't able to attempt to execute the image, so fall back + * to LoadImage / StartImage. + */ +- rc = grub_load_image((void *)(unsigned long)address); ++ rc = grub_load_image(sb_context->file_path, ++ (void *)(unsigned long)sb_context->address, ++ sb_context->fsize, sb_context->dev_handle, ++ sb_context->cmdline, sb_context->cmdline_len, ++ &handle); + if (rc == 0) +- grub_chainloader_boot (); ++ grub_start_image (handle); + } + + b = grub_efi_system_table->boot_services; +- efi_call_1 (b->unload_image, image_handle); ++ efi_call_1 (b->unload_image, handle); + + grub_loader_unset (); + return grub_errno; +@@ -913,9 +933,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_boot_services_t *b; + grub_device_t dev = 0; + grub_device_t orig_dev = 0; +- grub_efi_device_path_t *dp = 0; ++ grub_efi_device_path_t *dp = 0, *file_path = 0; + char *filename; + void *boot_image = 0; ++ grub_efi_physical_address_t address = 0; ++ grub_ssize_t fsize; ++ grub_efi_uintn_t pages = 0; ++ grub_efi_char16_t *cmdline = 0; ++ grub_ssize_t cmdline_len = 0; ++ grub_efi_handle_t dev_handle = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -923,12 +949,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + grub_dl_ref (my_mod); + +- /* Initialize some global variables. */ +- address = 0; +- image_handle = 0; +- file_path = 0; +- dev_handle = 0; +- + b = grub_efi_system_table->boot_services; + + if (argc > 1) +@@ -1093,17 +1113,35 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { ++ sb_context = grub_malloc (sizeof (*sb_context)); ++ if (sb_context == NULL) ++ goto fail; ++ sb_context->address = address; ++ sb_context->fsize = fsize; ++ sb_context->pages = pages; ++ sb_context->file_path = file_path; ++ sb_context->cmdline = cmdline; ++ sb_context->cmdline_len = cmdline_len; ++ sb_context->dev_handle = dev_handle; ++ + grub_file_close (file); + grub_device_close (dev); ++ + grub_loader_set (grub_secureboot_chainloader_boot, + grub_secureboot_chainloader_unload, 0); + return 0; + } + else + { +- grub_load_image(boot_image); ++ grub_load_image(file_path, boot_image, fsize, dev_handle, cmdline, ++ cmdline_len, &image_handle); + grub_file_close (file); + grub_device_close (dev); ++ ++ /* We're finished with the source image buffer and file path now */ ++ efi_call_2 (b->free_pages, address, pages); ++ grub_free (file_path); ++ + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); + + return 0; +@@ -1130,6 +1168,12 @@ fail: + if (cmdline) + grub_free (cmdline); + ++ if (image_handle != 0) ++ { ++ efi_call_1 (b->unload_image, image_handle); ++ image_handle = 0; ++ } ++ + grub_dl_unref (my_mod); + + return grub_errno; diff --git a/SOURCES/0214-commands-boot-Add-API-to-pass-context-to-loader.patch b/SOURCES/0214-commands-boot-Add-API-to-pass-context-to-loader.patch new file mode 100644 index 0000000..63a2d76 --- /dev/null +++ b/SOURCES/0214-commands-boot-Add-API-to-pass-context-to-loader.patch @@ -0,0 +1,158 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Fri, 29 Apr 2022 21:16:02 +0100 +Subject: [PATCH] commands/boot: Add API to pass context to loader + +Loaders rely on global variables for saving context which is consumed +in the boot hook and freed in the unload hook. In the case where a loader +command is executed twice, calling grub_loader_set a second time executes +the unload hook, but in some cases this runs when the loader's global +context has already been updated, resulting in the updated context being +freed and potential use-after-free bugs when the boot hook is subsequently +called. + +This adds a new API (grub_loader_set_ex) which allows a loader to specify +context that is passed to its boot and unload hooks. This is an alternative +to requiring that loaders call grub_loader_unset before mutating their +global context. + +Signed-off-by: Chris Coulson +(cherry picked from commit 4322a64dde7e8fedb58e50b79408667129d45dd3) +--- + grub-core/commands/boot.c | 66 +++++++++++++++++++++++++++++++++++++++++------ + include/grub/loader.h | 5 ++++ + 2 files changed, 63 insertions(+), 8 deletions(-) + +diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c +index bbca81e947..53691a62d9 100644 +--- a/grub-core/commands/boot.c ++++ b/grub-core/commands/boot.c +@@ -27,10 +27,20 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + +-static grub_err_t (*grub_loader_boot_func) (void); +-static grub_err_t (*grub_loader_unload_func) (void); ++static grub_err_t (*grub_loader_boot_func) (void *); ++static grub_err_t (*grub_loader_unload_func) (void *); ++static void *grub_loader_context; + static int grub_loader_flags; + ++struct grub_simple_loader_hooks ++{ ++ grub_err_t (*boot) (void); ++ grub_err_t (*unload) (void); ++}; ++ ++/* Don't heap allocate this to avoid making grub_loader_set fallible. */ ++static struct grub_simple_loader_hooks simple_loader_hooks; ++ + struct grub_preboot + { + grub_err_t (*preboot_func) (int); +@@ -44,6 +54,29 @@ static int grub_loader_loaded; + static struct grub_preboot *preboots_head = 0, + *preboots_tail = 0; + ++static grub_err_t ++grub_simple_boot_hook (void *context) ++{ ++ struct grub_simple_loader_hooks *hooks; ++ ++ hooks = (struct grub_simple_loader_hooks *) context; ++ return hooks->boot (); ++} ++ ++static grub_err_t ++grub_simple_unload_hook (void *context) ++{ ++ struct grub_simple_loader_hooks *hooks; ++ grub_err_t ret; ++ ++ hooks = (struct grub_simple_loader_hooks *) context; ++ ++ ret = hooks->unload (); ++ grub_memset (hooks, 0, sizeof (*hooks)); ++ ++ return ret; ++} ++ + int + grub_loader_is_loaded (void) + { +@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) + } + + void +-grub_loader_set (grub_err_t (*boot) (void), +- grub_err_t (*unload) (void), +- int flags) ++grub_loader_set_ex (grub_err_t (*boot) (void *), ++ grub_err_t (*unload) (void *), ++ void *context, ++ int flags) + { + if (grub_loader_loaded && grub_loader_unload_func) +- grub_loader_unload_func (); ++ grub_loader_unload_func (grub_loader_context); + + grub_loader_boot_func = boot; + grub_loader_unload_func = unload; ++ grub_loader_context = context; + grub_loader_flags = flags; + + grub_loader_loaded = 1; + } + ++void ++grub_loader_set (grub_err_t (*boot) (void), ++ grub_err_t (*unload) (void), ++ int flags) ++{ ++ grub_loader_set_ex (grub_simple_boot_hook, ++ grub_simple_unload_hook, ++ &simple_loader_hooks, ++ flags); ++ ++ simple_loader_hooks.boot = boot; ++ simple_loader_hooks.unload = unload; ++} ++ + void + grub_loader_unset(void) + { + if (grub_loader_loaded && grub_loader_unload_func) +- grub_loader_unload_func (); ++ grub_loader_unload_func (grub_loader_context); + + grub_loader_boot_func = 0; + grub_loader_unload_func = 0; ++ grub_loader_context = 0; + + grub_loader_loaded = 0; + } +@@ -158,7 +208,7 @@ grub_loader_boot (void) + return err; + } + } +- err = (grub_loader_boot_func) (); ++ err = (grub_loader_boot_func) (grub_loader_context); + + for (cur = preboots_tail; cur; cur = cur->prev) + if (! err) +diff --git a/include/grub/loader.h b/include/grub/loader.h +index b208642821..1846fa6c5f 100644 +--- a/include/grub/loader.h ++++ b/include/grub/loader.h +@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), + grub_err_t (*unload) (void), + int flags); + ++void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *), ++ grub_err_t (*unload) (void *), ++ void *context, ++ int flags); ++ + /* Unset current loader, if any. */ + void EXPORT_FUNC (grub_loader_unset) (void); + diff --git a/SOURCES/0214-templates-Check-for-EFI-at-runtime-instead-of-config.patch b/SOURCES/0214-templates-Check-for-EFI-at-runtime-instead-of-config.patch deleted file mode 100644 index e36afa1..0000000 --- a/SOURCES/0214-templates-Check-for-EFI-at-runtime-instead-of-config.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 6 Jul 2021 00:38:40 +0200 -Subject: [PATCH] templates: Check for EFI at runtime instead of config - generation time - -The 30_uefi-firmware template checks if an OsIndicationsSupported UEFI var -exists and EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, to decide whether -a "fwsetup" menu entry would be added or not to the GRUB menu. - -But this has the problem that it will only work if the configuration file -was created on an UEFI machine that supports booting to a firmware UI. - -This for example doesn't support creating GRUB config files when executing -on systems that support both UEFI and legacy BIOS booting. Since creating -the config file from legacy BIOS wouldn't allow to access the firmware UI. - -To prevent this, make the template to unconditionally create the grub.cfg -snippet but check at runtime if was booted through UEFI to decide if this -entry should be added. That way it won't be added when booting with BIOS. - -There's no need to check if EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit is set, -since that's already done by the "fwsetup" command when is executed. - -Resolves: rhbz#1823864 - -Signed-off-by: Javier Martinez Canillas ---- - util/grub.d/30_uefi-firmware.in | 21 ++++++++------------- - 1 file changed, 8 insertions(+), 13 deletions(-) - -diff --git a/util/grub.d/30_uefi-firmware.in b/util/grub.d/30_uefi-firmware.in -index d344d3883d7..b6041b55e2a 100644 ---- a/util/grub.d/30_uefi-firmware.in -+++ b/util/grub.d/30_uefi-firmware.in -@@ -26,19 +26,14 @@ export TEXTDOMAINDIR="@localedir@" - - . "$pkgdatadir/grub-mkconfig_lib" - --EFI_VARS_DIR=/sys/firmware/efi/efivars --EFI_GLOBAL_VARIABLE=8be4df61-93ca-11d2-aa0d-00e098032b8c --OS_INDICATIONS="$EFI_VARS_DIR/OsIndicationsSupported-$EFI_GLOBAL_VARIABLE" -+LABEL="UEFI Firmware Settings" - --if [ -e "$OS_INDICATIONS" ] && \ -- [ "$(( $(printf 0x%x \'"$(cat $OS_INDICATIONS | cut -b5)"\') & 1 ))" = 1 ]; then -- LABEL="UEFI Firmware Settings" -+gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 - -- gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2 -- -- cat << EOF --menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { -- fwsetup --} --EOF -+cat << EOF -+if [ "\$grub_platform" = "efi" ]; then -+ menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' { -+ fwsetup -+ } - fi -+EOF diff --git a/SOURCES/0215-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch b/SOURCES/0215-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch deleted file mode 100644 index 65b4aec..0000000 --- a/SOURCES/0215-efi-Print-an-error-if-boot-to-firmware-setup-is-not-.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Tue, 6 Jul 2021 01:10:18 +0200 -Subject: [PATCH] efi: Print an error if boot to firmware setup is not - supported - -The "fwsetup" command is only registered if the firmware supports booting -to the firmware setup UI. But it could be possible that the GRUB config -already contains a "fwsetup" entry, because it was generated in a machine -that has support for this feature. - -To prevent users getting a "can't find command `fwsetup`" error if it is -not supported by the firmware, let's just always register the command but -print a more accurate message if the firmware doesn't support this option. - -Resolves: rhbz#1823864 - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/commands/efi/efifwsetup.c | 43 ++++++++++++++++++++----------------- - 1 file changed, 23 insertions(+), 20 deletions(-) - -diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c -index eaca0328388..328c45e82e0 100644 ---- a/grub-core/commands/efi/efifwsetup.c -+++ b/grub-core/commands/efi/efifwsetup.c -@@ -27,6 +27,25 @@ - - GRUB_MOD_LICENSE ("GPLv3+"); - -+static grub_efi_boolean_t -+efifwsetup_is_supported (void) -+{ -+ grub_efi_uint64_t *os_indications_supported = NULL; -+ grub_size_t oi_size = 0; -+ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; -+ -+ grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, -+ (void **) &os_indications_supported); -+ -+ if (!os_indications_supported) -+ return 0; -+ -+ if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) -+ return 1; -+ -+ return 0; -+} -+ - static grub_err_t - grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), -@@ -38,6 +57,10 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), - grub_size_t oi_size; - grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; - -+ if (!efifwsetup_is_supported ()) -+ return grub_error (GRUB_ERR_INVALID_COMMAND, -+ N_("Reboot to firmware setup is not supported")); -+ - grub_efi_get_variable ("OsIndications", &global, &oi_size, - (void **) &old_os_indications); - -@@ -56,28 +79,8 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), - - static grub_command_t cmd = NULL; - --static grub_efi_boolean_t --efifwsetup_is_supported (void) --{ -- grub_efi_uint64_t *os_indications_supported = NULL; -- grub_size_t oi_size = 0; -- grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; -- -- grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, -- (void **) &os_indications_supported); -- -- if (!os_indications_supported) -- return 0; -- -- if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) -- return 1; -- -- return 0; --} -- - GRUB_MOD_INIT (efifwsetup) - { -- if (efifwsetup_is_supported ()) - cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, - N_("Reboot into firmware setup menu.")); - diff --git a/SOURCES/0215-loader-efi-chainloader-Use-grub_loader_set_ex.patch b/SOURCES/0215-loader-efi-chainloader-Use-grub_loader_set_ex.patch new file mode 100644 index 0000000..fc15b84 --- /dev/null +++ b/SOURCES/0215-loader-efi-chainloader-Use-grub_loader_set_ex.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Fri, 29 Apr 2022 21:30:56 +0100 +Subject: [PATCH] loader/efi/chainloader: Use grub_loader_set_ex + +This ports the EFI chainloader to use grub_loader_set_ex in order to fix +a use-after-free bug that occurs when grub_cmd_chainloader is executed +more than once before a boot attempt is performed. + +Signed-off-by: Chris Coulson +(cherry picked from commit 4b7f0402b7cb0f67a93be736f2b75b818d7f44c9) +[rharwood: context sludge from other change] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/efi/chainloader.c | 38 ++++++++++++++++++++++---------------- + 1 file changed, 22 insertions(+), 16 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 3342492ff1..fb874f1855 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -48,8 +48,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; + +-static grub_efi_handle_t image_handle; +- + struct grub_secureboot_chainloader_context { + grub_efi_physical_address_t address; + grub_efi_uintn_t pages; +@@ -59,7 +57,6 @@ struct grub_secureboot_chainloader_context { + grub_ssize_t cmdline_len; + grub_efi_handle_t dev_handle; + }; +-static struct grub_secureboot_chainloader_context *sb_context; + + static grub_err_t + grub_start_image (grub_efi_handle_t handle) +@@ -98,11 +95,14 @@ grub_start_image (grub_efi_handle_t handle) + } + + static grub_err_t +-grub_chainloader_unload (void) ++grub_chainloader_unload (void *context) + { ++ grub_efi_handle_t image_handle; + grub_efi_loaded_image_t *loaded_image; + grub_efi_boot_services_t *b; + ++ image_handle = (grub_efi_handle_t) context; ++ + loaded_image = grub_efi_get_loaded_image (image_handle); + if (loaded_image != NULL) + grub_free (loaded_image->load_options); +@@ -115,10 +115,12 @@ grub_chainloader_unload (void) + } + + static grub_err_t +-grub_chainloader_boot (void) ++grub_chainloader_boot (void *context) + { ++ grub_efi_handle_t image_handle; + grub_err_t err; + ++ image_handle = (grub_efi_handle_t) context; + err = grub_start_image (image_handle); + + grub_loader_unset (); +@@ -839,15 +841,17 @@ error_exit: + } + + static grub_err_t +-grub_secureboot_chainloader_unload (void) ++grub_secureboot_chainloader_unload (void *context) + { ++ struct grub_secureboot_chainloader_context *sb_context; ++ ++ sb_context = (struct grub_secureboot_chainloader_context *) context; ++ + grub_efi_free_pages (sb_context->address, sb_context->pages); + grub_free (sb_context->file_path); + grub_free (sb_context->cmdline); + grub_free (sb_context); + +- sb_context = 0; +- + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; + } +@@ -896,12 +900,15 @@ grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, + } + + static grub_err_t +-grub_secureboot_chainloader_boot (void) ++grub_secureboot_chainloader_boot (void *context) + { ++ struct grub_secureboot_chainloader_context *sb_context; + grub_efi_boot_services_t *b; + int rc; + grub_efi_handle_t handle = 0; + ++ sb_context = (struct grub_secureboot_chainloader_context *) context; ++ + rc = handle_image (sb_context); + if (rc == 0) + { +@@ -942,6 +949,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_char16_t *cmdline = 0; + grub_ssize_t cmdline_len = 0; + grub_efi_handle_t dev_handle = 0; ++ grub_efi_handle_t image_handle = 0; ++ struct grub_secureboot_chainloader_context *sb_context = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -1127,8 +1136,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_file_close (file); + grub_device_close (dev); + +- grub_loader_set (grub_secureboot_chainloader_boot, +- grub_secureboot_chainloader_unload, 0); ++ grub_loader_set_ex (grub_secureboot_chainloader_boot, ++ grub_secureboot_chainloader_unload, sb_context, 0); + return 0; + } + else +@@ -1142,7 +1151,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + efi_call_2 (b->free_pages, address, pages); + grub_free (file_path); + +- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); ++ grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0); + + return 0; + } +@@ -1169,10 +1178,7 @@ fail: + grub_free (cmdline); + + if (image_handle != 0) +- { +- efi_call_1 (b->unload_image, image_handle); +- image_handle = 0; +- } ++ efi_call_1 (b->unload_image, image_handle); + + grub_dl_unref (my_mod); + diff --git a/SOURCES/0216-arm64-Fix-EFI-loader-kernel-image-allocation.patch b/SOURCES/0216-arm64-Fix-EFI-loader-kernel-image-allocation.patch deleted file mode 100644 index 600b461..0000000 --- a/SOURCES/0216-arm64-Fix-EFI-loader-kernel-image-allocation.patch +++ /dev/null @@ -1,189 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Herrenschmidt -Date: Mon, 2 Aug 2021 23:10:01 +1000 -Subject: [PATCH] arm64: Fix EFI loader kernel image allocation - -We are currently allocating just enough memory for the file size, -which means that the kernel BSS is in limbo (and not even zeroed). - -We are also not honoring the alignment specified in the image -PE header. - -This makes us use the PE optional header in which the kernel puts the -actual size it needs, including BSS, and make sure we clear it, and -honors the specified alignment for the image. - -Signed-off-by: Benjamin Herrenschmidt ---- - grub-core/loader/arm64/linux.c | 100 +++++++++++++++++++++++++++-------------- - 1 file changed, 66 insertions(+), 34 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index 47f8cf0d84b..4a252d5e7e9 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -41,6 +41,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); - static grub_dl_t my_mod; - static int loaded; - -+static void *kernel_alloc_addr; -+static grub_uint32_t kernel_alloc_pages; - static void *kernel_addr; - static grub_uint64_t kernel_size; - static grub_uint32_t handover_offset; -@@ -204,9 +206,8 @@ grub_linux_unload (void) - GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start)); - initrd_start = initrd_end = 0; - grub_free (linux_args); -- if (kernel_addr) -- grub_efi_free_pages ((grub_addr_t) kernel_addr, -- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -+ if (kernel_alloc_addr) -+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); - grub_fdt_unload (); - return GRUB_ERR_NONE; - } -@@ -311,14 +312,35 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - return grub_errno; - } - -+static grub_err_t -+parse_pe_header (void *kernel, grub_uint64_t *total_size, -+ grub_uint32_t *entry_offset, -+ grub_uint32_t *alignment) -+{ -+ struct linux_arch_kernel_header *lh = kernel; -+ struct grub_armxx_linux_pe_header *pe; -+ -+ pe = (void *)((unsigned long)kernel + lh->hdr_offset); -+ -+ if (pe->opt.magic != GRUB_PE32_PE64_MAGIC) -+ return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic"); -+ -+ *total_size = pe->opt.image_size; -+ *entry_offset = pe->opt.entry_addr; -+ *alignment = pe->opt.section_alignment; -+ -+ return GRUB_ERR_NONE; -+} -+ - static grub_err_t - grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) - { - grub_file_t file = 0; -- struct linux_arch_kernel_header lh; -- struct grub_armxx_linux_pe_header *pe; - grub_err_t err; -+ grub_off_t filelen; -+ grub_uint32_t align; -+ void *kernel = NULL; - int rc; - - grub_dl_ref (my_mod); -@@ -333,40 +355,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - if (!file) - goto fail; - -- kernel_size = grub_file_size (file); -- -- if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) -- return grub_errno; -- -- if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) -- goto fail; -- -- grub_loader_unset(); -- -- grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size); -- kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -- grub_dprintf ("linux", "kernel numpages: %lld\n", -- (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -- if (!kernel_addr) -+ filelen = grub_file_size (file); -+ kernel = grub_malloc(filelen); -+ if (!kernel) - { -- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel load buffer")); - goto fail; - } - -- grub_file_seek (file, 0); -- if (grub_file_read (file, kernel_addr, kernel_size) -- < (grub_int64_t) kernel_size) -+ if (grub_file_read (file, kernel, filelen) < (grub_ssize_t)filelen) - { -- if (!grub_errno) -- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); -+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), -+ argv[0]); - goto fail; - } - -- grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); -- - if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) - { -- rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); -+ rc = grub_linuxefi_secure_validate (kernel, filelen); - if (rc <= 0) - { - grub_error (GRUB_ERR_INVALID_COMMAND, -@@ -375,8 +381,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - } - -- pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); -- handover_offset = pe->opt.entry_addr; -+ if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) -+ goto fail; -+ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) -+ goto fail; -+ grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); -+ grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); -+ grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); -+ -+ grub_loader_unset(); -+ -+ kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); -+ kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages); -+ grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages); -+ if (!kernel_alloc_addr) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); -+ goto fail; -+ } -+ kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); -+ -+ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); -+ grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); -+ if (kernel_size > filelen) -+ grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); -+ grub_free(kernel); -+ kernel = NULL; - - cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); - linux_args = grub_malloc (cmdline_size); -@@ -400,6 +430,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - - fail: -+ if (kernel) -+ grub_free (kernel); -+ - if (file) - grub_file_close (file); - -@@ -412,9 +445,8 @@ fail: - if (linux_args && !loaded) - grub_free (linux_args); - -- if (kernel_addr && !loaded) -- grub_efi_free_pages ((grub_addr_t) kernel_addr, -- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); -+ if (kernel_alloc_addr && !loaded) -+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); - - return grub_errno; - } diff --git a/SOURCES/0216-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch b/SOURCES/0216-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch new file mode 100644 index 0000000..b79c78c --- /dev/null +++ b/SOURCES/0216-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Mon, 2 May 2022 14:39:31 +0200 +Subject: [PATCH] loader/i386/efi/linux: Avoid a use-after-free in the linuxefi + loader + +In some error paths in grub_cmd_linux, the pointer to lh may be +dereferenced after the buffer it points to has been freed. There aren't +any security implications from this because nothing else uses the +allocator after the buffer is freed and before the pointer is +dereferenced, but fix it anyway. + +Signed-off-by: Chris Coulson +(cherry picked from commit 8224f5a71af94bec8697de17e7e579792db9f9e2) +--- + grub-core/loader/i386/efi/linux.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 941df6400b..27bc2aa161 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -465,9 +465,6 @@ fail: + if (file) + grub_file_close (file); + +- if (kernel) +- grub_free (kernel); +- + if (grub_errno != GRUB_ERR_NONE) + { + grub_dl_unref (my_mod); +@@ -483,6 +480,8 @@ fail: + kernel_free (params, sizeof(*params)); + } + ++ grub_free (kernel); ++ + return grub_errno; + } + diff --git a/SOURCES/0217-loader-i386-efi-linux-Use-grub_loader_set_ex.patch b/SOURCES/0217-loader-i386-efi-linux-Use-grub_loader_set_ex.patch new file mode 100644 index 0000000..1a129db --- /dev/null +++ b/SOURCES/0217-loader-i386-efi-linux-Use-grub_loader_set_ex.patch @@ -0,0 +1,296 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Mon, 2 May 2022 17:04:23 +0200 +Subject: [PATCH] loader/i386/efi/linux: Use grub_loader_set_ex + +This ports the linuxefi loader to use grub_loader_set_ex in order to fix +a use-after-fre bug that occurs when grub_cmd_linux is executed more than +once before a boot attempt is performed. + +This is more complicated than for the chainloader command, as the initrd +command needs access to the loader state. To solve this, the linuxefi +module registers a dummy initrd command at startup that returns an error. +The linuxefi command then registers a proper initrd command with a higher +priority that is passed the loader state. + +Signed-off-by: Chris Coulson +(cherry picked from commit 7cf736436b4c934df5ddfa6f44b46a7e07d99fdc) +[rharwood/pjones: set kernel_size in context] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/i386/efi/linux.c | 146 +++++++++++++++++++++++--------------- + 1 file changed, 87 insertions(+), 59 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 27bc2aa161..e3c2d6fe0b 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -34,13 +34,19 @@ + GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; +-static int loaded; +-static void *kernel_mem; +-static grub_uint64_t kernel_size; +-static void *initrd_mem; +-static grub_uint32_t handover_offset; +-struct linux_kernel_params *params; +-static char *linux_cmdline; ++ ++static grub_command_t cmd_linux, cmd_initrd; ++static grub_command_t cmd_linuxefi, cmd_initrdefi; ++ ++struct grub_linuxefi_context { ++ void *kernel_mem; ++ grub_uint64_t kernel_size; ++ grub_uint32_t handover_offset; ++ struct linux_kernel_params *params; ++ char *cmdline; ++ ++ void *initrd_mem; ++}; + + #define MIN(a, b) \ + ({ typeof (a) _a = (a); \ +@@ -123,25 +129,32 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) + } + + static grub_err_t +-grub_linuxefi_boot (void) ++grub_linuxefi_boot (void *data) + { ++ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; ++ + asm volatile ("cli"); + +- return grub_efi_linux_boot ((char *)kernel_mem, +- handover_offset, +- params); ++ return grub_efi_linux_boot ((char *)context->kernel_mem, ++ context->handover_offset, ++ context->params); + } + + static grub_err_t +-grub_linuxefi_unload (void) ++grub_linuxefi_unload (void *data) + { ++ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; ++ struct linux_kernel_params *params = context->params; ++ + grub_dl_unref (my_mod); +- loaded = 0; + +- kernel_free(initrd_mem, params->ramdisk_size); +- kernel_free(linux_cmdline, params->cmdline_size + 1); +- kernel_free(kernel_mem, kernel_size); +- kernel_free(params, sizeof(*params)); ++ kernel_free (context->initrd_mem, params->ramdisk_size); ++ kernel_free (context->cmdline, params->cmdline_size + 1); ++ kernel_free (context->kernel_mem, context->kernel_size); ++ kernel_free (params, sizeof(*params)); ++ cmd_initrd->data = 0; ++ cmd_initrdefi->data = 0; ++ grub_free (context); + + return GRUB_ERR_NONE; + } +@@ -188,13 +201,14 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) + #define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull)) + + static grub_err_t +-grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), +- int argc, char *argv[]) ++grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + { + grub_file_t *files = 0; + int i, nfiles = 0; + grub_size_t size = 0; + grub_uint8_t *ptr; ++ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; ++ struct linux_kernel_params *params; + + if (argc == 0) + { +@@ -202,12 +216,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (!loaded) ++ if (!context) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); + goto fail; + } + ++ params = context->params; ++ + files = grub_calloc (argc, sizeof (files[0])); + if (!files) + goto fail; +@@ -225,19 +241,19 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + } + } + +- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); +- if (initrd_mem == NULL) ++ context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); ++ if (context->initrd_mem == NULL) + goto fail; +- grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); ++ grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); + + params->ramdisk_size = LOW_U32(size); +- params->ramdisk_image = LOW_U32(initrd_mem); ++ params->ramdisk_image = LOW_U32(context->initrd_mem); + #if defined(__x86_64__) + params->ext_ramdisk_size = HIGH_U32(size); +- params->ext_ramdisk_image = HIGH_U32(initrd_mem); ++ params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); + #endif + +- ptr = initrd_mem; ++ ptr = context->initrd_mem; + + for (i = 0; i < nfiles; i++) + { +@@ -261,8 +277,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_file_close (files[i]); + grub_free (files); + +- if (initrd_mem && grub_errno) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, ++ if (context->initrd_mem && grub_errno) ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, + BYTES_TO_PAGES(size)); + + return grub_errno; +@@ -277,6 +293,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_ssize_t start, filelen; + void *kernel = NULL; + int setup_header_end_offset; ++ void *kernel_mem = 0; ++ grub_uint64_t kernel_size = 0; ++ grub_uint32_t handover_offset; ++ struct linux_kernel_params *params = 0; ++ char *cmdline = 0; ++ struct grub_linuxefi_context *context = 0; + + grub_dl_ref (my_mod); + +@@ -390,27 +412,27 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "new lh is at %p\n", lh); + + grub_dprintf ("linux", "setting up cmdline\n"); +- linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); +- if (!linux_cmdline) ++ cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); ++ if (!cmdline) + goto fail; +- grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline); ++ grub_dprintf ("linux", "cmdline = %p\n", cmdline); + +- grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); ++ grub_memcpy (cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + grub_create_loader_cmdline (argc, argv, +- linux_cmdline + sizeof (LINUX_IMAGE) - 1, ++ cmdline + sizeof (LINUX_IMAGE) - 1, + lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1), + GRUB_VERIFY_KERNEL_CMDLINE); + +- grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); ++ grub_dprintf ("linux", "cmdline:%s\n", cmdline); + grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", +- LOW_U32(linux_cmdline)); +- lh->cmd_line_ptr = LOW_U32(linux_cmdline); ++ LOW_U32(cmdline)); ++ lh->cmd_line_ptr = LOW_U32(cmdline); + #if defined(__x86_64__) +- if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull) ++ if ((grub_efi_uintn_t)cmdline > 0xffffffffull) + { + grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n", +- HIGH_U32(linux_cmdline)); +- params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline); ++ HIGH_U32(cmdline)); ++ params->ext_cmd_line_ptr = HIGH_U32(cmdline); + } + #endif + +@@ -435,16 +457,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; +- kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); ++ kernel_size = lh->init_size; ++ kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) + goto fail; + grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); + +- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); +- +- loaded = 1; +- + grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n", + LOW_U32(kernel_mem)); + lh->code32_start = LOW_U32(kernel_mem); +@@ -461,33 +480,42 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n", + params->ext_loader_type, params->ext_loader_ver); + ++ context = grub_zalloc (sizeof (*context)); ++ if (!context) ++ goto fail; ++ context->kernel_mem = kernel_mem; ++ context->kernel_size = kernel_size; ++ context->handover_offset = handover_offset; ++ context->params = params; ++ context->cmdline = cmdline; ++ ++ grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); ++ ++ cmd_initrd->data = context; ++ cmd_initrdefi->data = context; ++ ++ grub_file_close (file); ++ grub_free (kernel); ++ return 0; ++ + fail: + if (file) + grub_file_close (file); + +- if (grub_errno != GRUB_ERR_NONE) +- { +- grub_dl_unref (my_mod); +- loaded = 0; +- } ++ grub_dl_unref (my_mod); + +- if (!loaded) +- { +- if (lh) +- kernel_free (linux_cmdline, lh->cmdline_size + 1); ++ if (lh) ++ kernel_free (cmdline, lh->cmdline_size + 1); + +- kernel_free (kernel_mem, kernel_size); +- kernel_free (params, sizeof(*params)); +- } ++ kernel_free (kernel_mem, kernel_size); ++ kernel_free (params, sizeof(*params)); + ++ grub_free (context); + grub_free (kernel); + + return grub_errno; + } + +-static grub_command_t cmd_linux, cmd_initrd; +-static grub_command_t cmd_linuxefi, cmd_initrdefi; +- + GRUB_MOD_INIT(linux) + { + cmd_linux = diff --git a/SOURCES/0217-normal-main-Discover-the-device-to-read-the-config-f.patch b/SOURCES/0217-normal-main-Discover-the-device-to-read-the-config-f.patch deleted file mode 100644 index cf12fd6..0000000 --- a/SOURCES/0217-normal-main-Discover-the-device-to-read-the-config-f.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Mon, 30 Aug 2021 12:31:18 +0200 -Subject: [PATCH] normal/main: Discover the device to read the config from as a - fallback - -The GRUB core.img is generated locally, when this is done the grub2-probe -tool figures out the device and partition that needs to be read to parse -the GRUB configuration file. - -But in some cases the core.img can't be generated on the host and instead -has to be done at package build time. For example, if needs to get signed -with a key that's only available on the package building infrastructure. - -If that's the case, the prefix variable won't have a device and partition -but only a directory path. So there's no way for GRUB to know from which -device has to read the configuration file. - -To allow GRUB to continue working on that scenario, fallback to iterating -over all the available devices, if reading the config failed when using -the prefix and fw_path variables. - -Signed-off-by: Javier Martinez Canillas ---- - grub-core/normal/main.c | 58 +++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 51 insertions(+), 7 deletions(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 155bf366da2..f9ccca502ee 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -339,18 +339,13 @@ grub_enter_normal_mode (const char *config) - } - - static grub_err_t --grub_try_normal (const char *variable) -+grub_try_normal_prefix (const char *prefix) - { - char *config; -- const char *prefix; - grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; - const char *net_search_cfg; - int disable_net_search = 0; - -- prefix = grub_env_get (variable); -- if (!prefix) -- return GRUB_ERR_FILE_NOT_FOUND; -- - net_search_cfg = grub_env_get ("feature_net_search_cfg"); - if (net_search_cfg && net_search_cfg[0] == 'n') - disable_net_search = 1; -@@ -364,7 +359,7 @@ grub_try_normal (const char *variable) - config = grub_malloc (config_len); - - if (! config) -- return GRUB_ERR_FILE_NOT_FOUND; -+ return err; - - grub_snprintf (config, config_len, "%s/grub.cfg", prefix); - err = grub_net_search_config_file (config); -@@ -393,6 +388,53 @@ grub_try_normal (const char *variable) - return err; - } - -+static int -+grub_try_normal_dev (const char *name, void *data) -+{ -+ grub_err_t err; -+ const char *prefix = grub_xasprintf ("(%s)%s", name, (char *)data); -+ -+ if (!prefix) -+ return 0; -+ -+ err = grub_try_normal_prefix (prefix); -+ if (err == GRUB_ERR_NONE) -+ return 1; -+ -+ return 0; -+} -+ -+static grub_err_t -+grub_try_normal_discover (void) -+{ -+ char *prefix = grub_env_get ("prefix"); -+ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; -+ -+ if (!prefix) -+ return err; -+ -+ if (grub_device_iterate (grub_try_normal_dev, (void *)prefix)) -+ return GRUB_ERR_NONE; -+ -+ return err; -+} -+ -+static grub_err_t -+grub_try_normal (const char *variable) -+{ -+ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; -+ const char *prefix; -+ -+ if (!variable) -+ return err; -+ -+ prefix = grub_env_get (variable); -+ if (!prefix) -+ return err; -+ -+ return grub_try_normal_prefix (prefix); -+} -+ - /* Enter normal mode from rescue mode. */ - static grub_err_t - grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), -@@ -407,6 +449,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), - err = grub_try_normal ("fw_path"); - if (err == GRUB_ERR_FILE_NOT_FOUND) - err = grub_try_normal ("prefix"); -+ if (err == GRUB_ERR_FILE_NOT_FOUND) -+ err = grub_try_normal_discover (); - if (err == GRUB_ERR_FILE_NOT_FOUND) - grub_enter_normal_mode (0); - } diff --git a/SOURCES/0218-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch b/SOURCES/0218-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch new file mode 100644 index 0000000..51953fd --- /dev/null +++ b/SOURCES/0218-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Tue, 3 May 2022 09:47:35 +0200 +Subject: [PATCH] loader/i386/efi/linux: Fix a memory leak in the initrd + command + +Subsequent invocations of the initrd command result in the previous +initrd being leaked, so fix that. + +Signed-off-by: Chris Coulson +(cherry picked from commit d98af31ce1e31bb22163960d53f5eb28c66582a0) +--- + grub-core/loader/i386/efi/linux.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index e3c2d6fe0b..9e5c11ac69 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -209,6 +209,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + grub_uint8_t *ptr; + struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; + struct linux_kernel_params *params; ++ void *initrd_mem = 0; + + if (argc == 0) + { +@@ -241,19 +242,19 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + } + +- context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); +- if (context->initrd_mem == NULL) ++ initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); ++ if (initrd_mem == NULL) + goto fail; +- grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); ++ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); + + params->ramdisk_size = LOW_U32(size); +- params->ramdisk_image = LOW_U32(context->initrd_mem); ++ params->ramdisk_image = LOW_U32(initrd_mem); + #if defined(__x86_64__) + params->ext_ramdisk_size = HIGH_U32(size); +- params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); ++ params->ext_ramdisk_image = HIGH_U32(initrd_mem); + #endif + +- ptr = context->initrd_mem; ++ ptr = initrd_mem; + + for (i = 0; i < nfiles; i++) + { +@@ -270,6 +271,9 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + ptr += ALIGN_UP_OVERHEAD (cursize, 4); + } + ++ kernel_free(context->initrd_mem, params->ramdisk_size); ++ ++ context->initrd_mem = initrd_mem; + params->ramdisk_size = size; + + fail: +@@ -277,9 +281,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + grub_file_close (files[i]); + grub_free (files); + +- if (context->initrd_mem && grub_errno) +- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, +- BYTES_TO_PAGES(size)); ++ if (initrd_mem && grub_errno) ++ kernel_free (initrd_mem, size); + + return grub_errno; + } diff --git a/SOURCES/0218-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch b/SOURCES/0218-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch deleted file mode 100644 index 70b021d..0000000 --- a/SOURCES/0218-powerpc-adjust-setting-of-prefix-for-signed-binary-c.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 19 Jul 2021 14:35:55 +1000 -Subject: [PATCH] powerpc: adjust setting of prefix for signed binary case - -On RHEL-signed powerpc grub, we sign a grub with -p /grub2 and expect -that there's a boot partition. - -Unfortunately grub_set_prefix_and_root tries to convert this to -($fwdevice)/grub2. This ends up being (ieee1275/disk)/grub2 and that -falls apart pretty quickly - there's no file-system on ieee1275/disk, -and it makes the search routine try things like -(ieee1275/disk,msdos2)(ieee1275/disk)/grub2 which also doesn't work. - -Detect if we would be about to create (ieee1275/disk)/path and don't: -preserve a prefix of /path instead and hope the search later finds us. - -Related: rhbz#1899864 - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/main.c | 38 +++++++++++++++++++++++++++++++++----- - 1 file changed, 33 insertions(+), 5 deletions(-) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index 0285e95a2bb..e809a5edec1 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -216,13 +216,41 @@ grub_set_prefix_and_root (void) - if (device) - { - char *prefix_set; -- -- prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); -- if (prefix_set) -+ -+#ifdef __powerpc__ -+ /* We have to be careful here on powerpc-ieee1275 + signed grub. We -+ will have signed something with a prefix that doesn't have a device -+ because we cannot know in advance what partition we're on. -+ -+ We will have had !device earlier, so we will have set device=fwdevice -+ However, we want to make sure we do not end up setting prefix to be -+ ($fwdevice)/path, because we will then end up trying to boot or search -+ based on a prefix of (ieee1275/disk)/path, which will not work because -+ it's missing a partition. -+ -+ Also: -+ - You can end up with a device with an FS directly on it, without -+ a partition, e.g. ieee1275/cdrom. -+ -+ - powerpc-ieee1275 + grub-install sets e.g. prefix=(,gpt2)/path, -+ which will have now been extended to device=$fwdisk,partition -+ and path=/path -+ -+ So we only need to act if device = ieee1275/disk exactly. -+ */ -+ if (grub_strncmp (device, "ieee1275/disk", 14) == 0) -+ grub_env_set ("prefix", path); -+ else -+#endif - { -- grub_env_set ("prefix", prefix_set); -- grub_free (prefix_set); -+ prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); -+ if (prefix_set) -+ { -+ grub_env_set ("prefix", prefix_set); -+ grub_free (prefix_set); -+ } - } -+ - grub_env_set ("root", device); - } - diff --git a/SOURCES/0219-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch b/SOURCES/0219-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch new file mode 100644 index 0000000..715e6e1 --- /dev/null +++ b/SOURCES/0219-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Julian Andres Klode +Date: Thu, 2 Dec 2021 15:03:53 +0100 +Subject: [PATCH] kern/efi/sb: Reject non-kernel files in the shim_lock + verifier + +We must not allow other verifiers to pass things like the GRUB modules. +Instead of maintaining a blocklist, maintain an allowlist of things +that we do not care about. + +This allowlist really should be made reusable, and shared by the +lockdown verifier, but this is the minimal patch addressing +security concerns where the TPM verifier was able to mark modules +as verified (or the OpenPGP verifier for that matter), when it +should not do so on shim-powered secure boot systems. + +Fixes: CVE-2022-28735 + +Signed-off-by: Julian Andres Klode +Reviewed-by: Daniel Kiper +(cherry picked from commit fa61ad69861c1cb3f68bf853d78fae7fd93986a0) +--- + grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++--- + include/grub/verify.h | 1 + + 2 files changed, 37 insertions(+), 3 deletions(-) + +diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c +index c52ec6226a..89c4bb3fd1 100644 +--- a/grub-core/kern/efi/sb.c ++++ b/grub-core/kern/efi/sb.c +@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + void **context __attribute__ ((unused)), + enum grub_verify_flags *flags) + { +- *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; ++ *flags = GRUB_VERIFY_FLAGS_NONE; + + switch (type & GRUB_FILE_TYPE_MASK) + { ++ /* Files we check. */ + case GRUB_FILE_TYPE_LINUX_KERNEL: + case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: + case GRUB_FILE_TYPE_BSD_KERNEL: +@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + case GRUB_FILE_TYPE_PLAN9_KERNEL: + case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: + *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; ++ return GRUB_ERR_NONE; + +- /* Fall through. */ ++ /* Files that do not affect secureboot state. */ ++ case GRUB_FILE_TYPE_NONE: ++ case GRUB_FILE_TYPE_LOOPBACK: ++ case GRUB_FILE_TYPE_LINUX_INITRD: ++ case GRUB_FILE_TYPE_OPENBSD_RAMDISK: ++ case GRUB_FILE_TYPE_XNU_RAMDISK: ++ case GRUB_FILE_TYPE_SIGNATURE: ++ case GRUB_FILE_TYPE_PUBLIC_KEY: ++ case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST: ++ case GRUB_FILE_TYPE_PRINT_BLOCKLIST: ++ case GRUB_FILE_TYPE_TESTLOAD: ++ case GRUB_FILE_TYPE_GET_SIZE: ++ case GRUB_FILE_TYPE_FONT: ++ case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: ++ case GRUB_FILE_TYPE_CAT: ++ case GRUB_FILE_TYPE_HEXCAT: ++ case GRUB_FILE_TYPE_CMP: ++ case GRUB_FILE_TYPE_HASHLIST: ++ case GRUB_FILE_TYPE_TO_HASH: ++ case GRUB_FILE_TYPE_KEYBOARD_LAYOUT: ++ case GRUB_FILE_TYPE_PIXMAP: ++ case GRUB_FILE_TYPE_GRUB_MODULE_LIST: ++ case GRUB_FILE_TYPE_CONFIG: ++ case GRUB_FILE_TYPE_THEME: ++ case GRUB_FILE_TYPE_GETTEXT_CATALOG: ++ case GRUB_FILE_TYPE_FS_SEARCH: ++ case GRUB_FILE_TYPE_LOADENV: ++ case GRUB_FILE_TYPE_SAVEENV: ++ case GRUB_FILE_TYPE_VERIFY_SIGNATURE: ++ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; ++ return GRUB_ERR_NONE; + ++ /* Other files. */ + default: +- return GRUB_ERR_NONE; ++ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy")); + } + } + +diff --git a/include/grub/verify.h b/include/grub/verify.h +index cd129c398f..672ae16924 100644 +--- a/include/grub/verify.h ++++ b/include/grub/verify.h +@@ -24,6 +24,7 @@ + + enum grub_verify_flags + { ++ GRUB_VERIFY_FLAGS_NONE = 0, + GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1, + GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2, + /* Defer verification to another authority. */ diff --git a/SOURCES/0219-powerpc-fix-prefix-signed-grub-special-case-for-Powe.patch b/SOURCES/0219-powerpc-fix-prefix-signed-grub-special-case-for-Powe.patch deleted file mode 100644 index 1cb21ef..0000000 --- a/SOURCES/0219-powerpc-fix-prefix-signed-grub-special-case-for-Powe.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 16 Aug 2021 16:01:47 +1000 -Subject: [PATCH] powerpc: fix prefix + signed grub special case for PowerVM - -Mea culpa: when testing the PowerPC special case for signed grub, I -assumed qemu and PowerVM would behave identically. This was wrong, and -with hindsight a pretty dumb error. - -This fixes it. This time, I am actually testing on PowerVM. - -Signed-off-by: Daniel Axtens ---- - grub-core/kern/main.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index e809a5edec1..2d0d2bbd4cf 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -236,9 +236,20 @@ grub_set_prefix_and_root (void) - which will have now been extended to device=$fwdisk,partition - and path=/path - -- So we only need to act if device = ieee1275/disk exactly. -+ - PowerVM will give us device names like -+ ieee1275//vdevice/v-scsi@3000006c/disk@8100000000000000 -+ and we don't want to try to encode some sort of truth table about -+ what sorts of paths represent disks with partition tables and those -+ without partition tables. -+ -+ So we act unless there is a comma in the device, which would indicate -+ a partition has already been specified. -+ -+ (If we only have a path, the code in normal to discover config files -+ will try both without partitions and then with any partitions so we -+ will cover both CDs and HDs.) - */ -- if (grub_strncmp (device, "ieee1275/disk", 14) == 0) -+ if (grub_strchr (device, ',') == NULL) - grub_env_set ("prefix", path); - else - #endif diff --git a/SOURCES/0220-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch b/SOURCES/0220-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch deleted file mode 100644 index 8b5170b..0000000 --- a/SOURCES/0220-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 9 Sep 2021 10:59:28 -0400 -Subject: [PATCH] Arm: check for the PE magic for the compiled arch - -In "arm64: Fix EFI loader kernel image allocation", Ben fixed the kernel -alignment to match the alignment given in the PE header. In doing so, a -check for valid PE magic was added, which was hard-coded to the value -seen on Aarch64 (GRUB_PE32_PE64_MAGIC). - -Unfortunately, this code is shared between 64-bit and 32-bit, and so -that value broke 32-bit Arm systems. - -This patch adds a constant definition for GRUB_PE32_PEXX_MAGIC, which is -either GRUB_PE32_PE64_MAGIC or GRUB_PE32_PE32_MAGIC, depending on which -platform is being built, and uses it in the header magic check. - -Resolves: rhbz#2000756 - -Signed-off-by: Peter Jones ---- - grub-core/loader/arm64/linux.c | 2 +- - include/grub/arm/linux.h | 1 + - include/grub/arm64/linux.h | 1 + - 3 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index 4a252d5e7e9..f18d90bd749 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -322,7 +322,7 @@ parse_pe_header (void *kernel, grub_uint64_t *total_size, - - pe = (void *)((unsigned long)kernel + lh->hdr_offset); - -- if (pe->opt.magic != GRUB_PE32_PE64_MAGIC) -+ if (pe->opt.magic != GRUB_PE32_PEXX_MAGIC) - return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic"); - - *total_size = pe->opt.image_size; -diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h -index b582f67f661..966a5074f53 100644 ---- a/include/grub/arm/linux.h -+++ b/include/grub/arm/linux.h -@@ -44,6 +44,7 @@ struct grub_arm_linux_pe_header - - #if defined(__arm__) - # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE -+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE32_MAGIC - # define linux_arch_kernel_header linux_arm_kernel_header - # define grub_armxx_linux_pe_header grub_arm_linux_pe_header - #endif -diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h -index ea030312df3..422bf2bf24b 100644 ---- a/include/grub/arm64/linux.h -+++ b/include/grub/arm64/linux.h -@@ -48,6 +48,7 @@ struct grub_arm64_linux_pe_header - - #if defined(__aarch64__) - # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE -+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE64_MAGIC - # define linux_arch_kernel_header linux_arm64_kernel_header - # define grub_armxx_linux_pe_header grub_arm64_linux_pe_header - #endif diff --git a/SOURCES/0220-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch b/SOURCES/0220-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch new file mode 100644 index 0000000..59f9471 --- /dev/null +++ b/SOURCES/0220-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Fri, 25 Jun 2021 02:19:05 +1000 +Subject: [PATCH] kern/file: Do not leak device_name on error in + grub_file_open() + +If we have an error in grub_file_open() before we free device_name, we +will leak it. + +Free device_name in the error path and null out the pointer in the good +path once we free it there. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 1499a5068839fa37cb77ecef4b5bdacbd1ed12ea) +--- + grub-core/kern/file.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c +index ec10e54fc0..db938e099d 100644 +--- a/grub-core/kern/file.c ++++ b/grub-core/kern/file.c +@@ -84,6 +84,7 @@ grub_file_open (const char *name, enum grub_file_type type) + + device = grub_device_open (device_name); + grub_free (device_name); ++ device_name = NULL; + if (! device) + goto fail; + +@@ -138,6 +139,7 @@ grub_file_open (const char *name, enum grub_file_type type) + return file; + + fail: ++ grub_free (device_name); + if (device) + grub_device_close (device); + diff --git a/SOURCES/0221-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch b/SOURCES/0221-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch deleted file mode 100644 index 893d8b4..0000000 --- a/SOURCES/0221-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Erwan Velu -Date: Wed, 25 Aug 2021 15:31:52 +0200 -Subject: [PATCH] fs/xfs: Fix unreadable filesystem with v4 superblock - -The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) -introduced the bigtime support by adding some features in v3 inodes. -This change extended grub_xfs_inode struct by 76 bytes but also changed -the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this -commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes -XFS_V2_INODE_SIZE becomes 16 bytes too small. - -As a result, the data structures aren't properly aligned and the GRUB -generates "attempt to read or write outside of partition" errors when -trying to read the XFS filesystem: - - GNU GRUB version 2.11 - .... - grub> set debug=efi,gpt,xfs - grub> insmod part_gpt - grub> ls (hd0,gpt1)/ - partmap/gpt.c:93: Read a valid GPT header - partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 - fs/xfs.c:931: Reading sb - fs/xfs.c:270: Validating superblock - fs/xfs.c:295: XFS v4 superblock detected - fs/xfs.c:962: Reading root ino 128 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840 - error: attempt to read or write outside of partition. - -This commit change the XFS_V2_INODE_SIZE computation by subtracting 76 -bytes instead of 92 bytes from the actual size of grub_xfs_inode struct. -This 76 bytes value comes from added members: - 20 grub_uint8_t unused5 - 1 grub_uint64_t flags2 - 48 grub_uint8_t unused6 - -This patch explicitly splits the v2 and v3 parts of the structure. -The unused4 is still ending of the v2 structures and the v3 starts -at unused5. Thanks to this we will avoid future corruptions of v2 -or v3 inodes. - -The XFS_V2_INODE_SIZE is returning to its expected size and the -filesystem is back to a readable state: - - GNU GRUB version 2.11 - .... - grub> set debug=efi,gpt,xfs - grub> insmod part_gpt - grub> ls (hd0,gpt1)/ - partmap/gpt.c:93: Read a valid GPT header - partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125 - fs/xfs.c:931: Reading sb - fs/xfs.c:270: Validating superblock - fs/xfs.c:295: XFS v4 superblock detected - fs/xfs.c:962: Reading root ino 128 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:931: Reading sb - fs/xfs.c:270: Validating superblock - fs/xfs.c:295: XFS v4 superblock detected - fs/xfs.c:962: Reading root ino 128 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (128) - 64, 0 - fs/xfs.c:515: Reading inode (131) - 64, 768 - efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0 - grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024 - grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816 - grub> - -Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support) - -Signed-off-by: Erwan Velu -Tested-by: Carlos Maiolino -Reviewed-by: Daniel Kiper -(cherry picked from commit a4b495520e4dc41a896a8b916a64eda9970c50ea) ---- - grub-core/fs/xfs.c | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c -index 0f524c3a8a6..e3816d1ec4a 100644 ---- a/grub-core/fs/xfs.c -+++ b/grub-core/fs/xfs.c -@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy - grub_uint32_t nanosec; - } GRUB_PACKED; - -+/* -+ * The struct grub_xfs_inode layout was taken from the -+ * struct xfs_dinode_core which is described here: -+ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf -+ */ - struct grub_xfs_inode - { - grub_uint8_t magic[2]; -@@ -208,14 +213,15 @@ struct grub_xfs_inode - grub_uint32_t nextents; - grub_uint16_t unused3; - grub_uint8_t fork_offset; -- grub_uint8_t unused4[37]; -+ grub_uint8_t unused4[17]; /* Last member of inode v2. */ -+ grub_uint8_t unused5[20]; /* First member of inode v3. */ - grub_uint64_t flags2; -- grub_uint8_t unused5[48]; -+ grub_uint8_t unused6[48]; /* Last member of inode v3. */ - } GRUB_PACKED; - - #define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) --/* Size of struct grub_xfs_inode until fork_offset (included). */ --#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) -+/* Size of struct grub_xfs_inode v2, up to unused4 member included. */ -+#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) - - struct grub_xfs_dirblock_tail - { diff --git a/SOURCES/0221-video-readers-png-Abort-sooner-if-a-read-operation-f.patch b/SOURCES/0221-video-readers-png-Abort-sooner-if-a-read-operation-f.patch new file mode 100644 index 0000000..385d3ed --- /dev/null +++ b/SOURCES/0221-video-readers-png-Abort-sooner-if-a-read-operation-f.patch @@ -0,0 +1,198 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 14:02:55 +1000 +Subject: [PATCH] video/readers/png: Abort sooner if a read operation fails + +Fuzzing revealed some inputs that were taking a long time, potentially +forever, because they did not bail quickly upon encountering an I/O error. + +Try to catch I/O errors sooner and bail out. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 882be97d1df6449b9fd4d593f0cb70005fde3494) +--- + grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++++++++------- + 1 file changed, 47 insertions(+), 8 deletions(-) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index 0157ff7420..e2a6b1cf3c 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -142,6 +142,7 @@ static grub_uint8_t + grub_png_get_byte (struct grub_png_data *data) + { + grub_uint8_t r; ++ grub_ssize_t bytes_read = 0; + + if ((data->inside_idat) && (data->idat_remain == 0)) + { +@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data) + } + + r = 0; +- grub_file_read (data->file, &r, 1); ++ bytes_read = grub_file_read (data->file, &r, 1); ++ ++ if (bytes_read != 1) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: unexpected end of data"); ++ return 0; ++ } + + if (data->inside_idat) + data->idat_remain--; +@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data, + if (len == 0) + return GRUB_ERR_NONE; + +- for (i = 0; 3 * i < len && i < 256; i++) ++ grub_errno = GRUB_ERR_NONE; ++ for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++) + for (j = 0; j < 3; j++) + data->palette[i][j] = grub_png_get_byte (data); +- for (i *= 3; i < len; i++) ++ for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++) + grub_png_get_byte (data); + + grub_png_get_dword (data); + +- return GRUB_ERR_NONE; ++ return grub_errno; + } + + static grub_err_t +@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size"); + + color_bits = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + data->is_16bit = (color_bits == 16); + + color_type = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + /* According to PNG spec, no other types are valid. */ + if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR)) +@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data) + if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: compression method not supported"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: filter method not supported"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if (grub_png_get_byte (data) != PNG_INTERLACE_NONE) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: interlace method not supported"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + /* Skip crc checksum. */ + grub_png_get_dword (data); +@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht) + int code, i; + + code = 0; +- for (i = 0; i < ht->max_length; i++) ++ for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++) + { + code = (code << 1) + grub_png_get_bits (data, 1); + if (code < ht->maxval[i]) +@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data) + grub_uint8_t lens[DEFLATE_HCLEN_MAX]; + + nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) || + (nb > DEFLATE_HCLEN_MAX)) +@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data) + data->dist_offset); + + prev = 0; +- for (i = 0; i < nl + nd; i++) ++ for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++) + { + int n, code; + struct huff_table *ht; +@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data) + len = cplens[n]; + if (cplext[n]) + len += grub_png_get_bits (data, cplext[n]); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + n = grub_png_get_huff_code (data, &data->dist_table); + dist = cpdist[n]; + if (cpdext[n]) + dist += grub_png_get_bits (data, cpdext[n]); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + pos = data->wp - dist; + if (pos < 0) + pos += WSIZE; + +- while (len > 0) ++ while (len > 0 && grub_errno == GRUB_ERR_NONE) + { + data->slide[data->wp] = data->slide[pos]; + grub_png_output_byte (data, data->slide[data->wp]); +@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data) + int final; + + cmf = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + flg = grub_png_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if ((cmf & 0xF) != Z_DEFLATED) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, +@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data) + int block_type; + + final = grub_png_get_bits (data, 1); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + block_type = grub_png_get_bits (data, 2); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + switch (block_type) + { +@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data) + grub_png_get_byte (data); + grub_png_get_byte (data); + +- for (i = 0; i < len; i++) ++ for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++) + grub_png_output_byte (data, grub_png_get_byte (data)); + + break; +@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data) + + len = grub_png_get_dword (data); + type = grub_png_get_dword (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ break; + data->next_offset = data->file->offset + len + 4; + + switch (type) diff --git a/SOURCES/0222-Print-module-name-on-license-check-failure.patch b/SOURCES/0222-Print-module-name-on-license-check-failure.patch deleted file mode 100644 index c4b9a13..0000000 --- a/SOURCES/0222-Print-module-name-on-license-check-failure.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Tue, 12 Oct 2021 12:34:23 -0400 -Subject: [PATCH] Print module name on license check failure - -At the very least, this will make it easier to track down the problem -module - or, if something else has gone wrong, provide more information -for debugging. - -Signed-off-by: Robbie Harwood ---- - grub-core/kern/dl.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 9557254035e..f3044945742 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -528,14 +528,16 @@ grub_dl_find_section_index (Elf_Ehdr *e, const char *name) - Be sure to understand your license obligations. - */ - static grub_err_t --grub_dl_check_license (Elf_Ehdr *e) -+grub_dl_check_license (grub_dl_t mod, Elf_Ehdr *e) - { - Elf_Shdr *s = grub_dl_find_section (e, ".module_license"); - if (s && (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)) - return GRUB_ERR_NONE; -- return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); -+ return grub_error (GRUB_ERR_BAD_MODULE, -+ "incompatible license in module %s: %s", mod->name, -+ (char *) e + s->sh_offset); - } - - static grub_err_t -@@ -743,8 +745,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) - constitutes linking) and GRUB core being licensed under GPLv3+. - Be sure to understand your license obligations. - */ -- if (grub_dl_check_license (e) -- || grub_dl_resolve_name (mod, e) -+ if (grub_dl_resolve_name (mod, e) -+ || grub_dl_check_license (mod, e) - || grub_dl_resolve_dependencies (mod, e) - || grub_dl_load_segments (mod, e) - || grub_dl_resolve_symbols (mod, e) diff --git a/SOURCES/0222-video-readers-png-Refuse-to-handle-multiple-image-he.patch b/SOURCES/0222-video-readers-png-Refuse-to-handle-multiple-image-he.patch new file mode 100644 index 0000000..9168fe5 --- /dev/null +++ b/SOURCES/0222-video-readers-png-Refuse-to-handle-multiple-image-he.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 14:13:40 +1000 +Subject: [PATCH] video/readers/png: Refuse to handle multiple image headers + +This causes the bitmap to be leaked. Do not permit multiple image headers. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 8ce433557adeadbc46429aabb9f850b02ad2bdfb) +--- + grub-core/video/readers/png.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index e2a6b1cf3c..8955b8ecfd 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data) + int color_bits; + enum grub_video_blit_format blt; + ++ if (data->image_width || data->image_height) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found"); ++ + data->image_width = grub_png_get_dword (data); + data->image_height = grub_png_get_dword (data); + diff --git a/SOURCES/0223-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch b/SOURCES/0223-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch deleted file mode 100644 index a80727e..0000000 --- a/SOURCES/0223-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 22 Oct 2021 09:53:15 +1100 -Subject: [PATCH] powerpc-ieee1275: load grub at 4MB, not 2MB - -This was first reported under PFW but reproduces under SLOF. - - - The core.elf was 2126152 = 0x207148 bytes in size with the following - program headers (per readelf): - -Entry point 0x200000 -There are 4 program headers, starting at offset 52 - -Program Headers: - Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align - LOAD 0x000160 0x00200000 0x00200000 0x21f98 0x2971c RWE 0x8 - GNU_STACK 0x0220f8 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 - LOAD 0x0220f8 0x00232000 0x00232000 0x1e4e50 0x1e4e50 RWE 0x4 - NOTE 0x206f48 0x00000000 0x00000000 0x00200 0x00000 R 0x4 - - - SLOF places the ELF file at 0x4000 (after the reserved space for - interrupt handlers etc.) upwards. The image was 2126152 = 0x207148 - bytes in size, so it runs from 0x4000 - 0x20b148. We'll call 0x4000 the - load address. - -0x0 0x4000 0x20b148 - |----------|--------------| - | reserved | ELF contents | - - - SLOF then copies the first LOAD program header (for .text). That runs - for 0x21f98 bytes. It runs from - (load addr + 0x160) to (load addr + 0x160 + 0x21f98) - = 0x4160 to 0x260f8 - and we copy it to 0x200000 to 0x221f98. This overwrites the end of the - image: - -0x0 0x4000 0x200000 0x221f98 - |----------|------------|---------------| - | reserved | ELF cont.. | .text section | - - - SLOF zeros the bss up to PhysAddr + MemSize = 0x22971c - -0x0 0x4000 0x200000 0x221f98 0x22971c - |----------|------------|---------------|--------| - | reserved | ELF cont.. | .text section | bss 0s | - - - SLOF then goes to fulfil the next LOAD header (for mods), which is - for 0x1e4e50 bytes. We copy from - (load addr + 0x220f8) to (load addr + 0x220f8 + 0x1e4e50) - = 0x260f8 to 0x20af48 - and we copy it to 0x232000 to 0x416e50: - -0x0 0x4000 0x200000 0x221f98 0x22971c - |----------|------------|---------------|--------| - | reserved | ELF cont.. | .text section | bss 0s | - |-------------| - | copied area | - 0x260f8 0x20af48 - - This goes poorly: - -0x0 0x4000 0x200000 0x221f98 0x22971c 0x232000 0x40bf08 0x416e50 - |----------|------------|---------------|--------|-----|-----------|-------------| - | reserved | ELF cont.. | .text section | bss 0s | pad | some mods | .text start | - -This matches the observations on the running system - 0x40bf08 was where -the contents of memory no longer matched the contents of the ELF file. - -This was reported as a license verification failure on SLOF as the -last module's .module_license section fell past where the corruption -began. - -Signed-off-by: Daniel Axtens -[rharwood@redhat.com: trim very detailed commit message] -Signed-off-by: Robbie Harwood ---- - grub-core/Makefile.core.def | 2 +- - include/grub/offsets.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 3f3459b2c70..6b00eb55575 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -89,7 +89,7 @@ kernel = { - i386_xen_pvh_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x100000'; - - mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; -- powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; -+ powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x400000'; - sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; - mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; - mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; -diff --git a/include/grub/offsets.h b/include/grub/offsets.h -index 871e1cd4c38..69211aa798b 100644 ---- a/include/grub/offsets.h -+++ b/include/grub/offsets.h -@@ -63,7 +63,7 @@ - #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 - - #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 --#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000 -+#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x400000 - - #define GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR 0x80200000 - diff --git a/SOURCES/0223-video-readers-png-Drop-greyscale-support-to-fix-heap.patch b/SOURCES/0223-video-readers-png-Drop-greyscale-support-to-fix-heap.patch new file mode 100644 index 0000000..4529cb8 --- /dev/null +++ b/SOURCES/0223-video-readers-png-Drop-greyscale-support-to-fix-heap.patch @@ -0,0 +1,170 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 18:51:35 +1000 +Subject: [PATCH] video/readers/png: Drop greyscale support to fix heap + out-of-bounds write + +A 16-bit greyscale PNG without alpha is processed in the following loop: + + for (i = 0; i < (data->image_width * data->image_height); + i++, d1 += 4, d2 += 2) + { + d1[R3] = d2[1]; + d1[G3] = d2[1]; + d1[B3] = d2[1]; + } + +The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration, +but there are only 3 bytes allocated for storage. This means that image +data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes +out of every 4 following the end of the image. + +This has existed since greyscale support was added in 2013 in commit +3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale). + +Saving starfield.png as a 16-bit greyscale image without alpha in the gimp +and attempting to load it causes grub-emu to crash - I don't think this code +has ever worked. + +Delete all PNG greyscale support. + +Fixes: CVE-2021-3695 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 0e1d163382669bd734439d8864ee969616d971d9) +[rharwood: context conflict] +Signed-off-by: Robbie Harwood +--- + grub-core/video/readers/png.c | 85 +++---------------------------------------- + 1 file changed, 6 insertions(+), 79 deletions(-) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index 8955b8ecfd..a3161e25b6 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -100,7 +100,7 @@ struct grub_png_data + + unsigned image_width, image_height; + int bpp, is_16bit; +- int raw_bytes, is_gray, is_alpha, is_palette; ++ int raw_bytes, is_alpha, is_palette; + int row_bytes, color_bits; + grub_uint8_t *image_data; + +@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data) + data->bpp = 3; + else + { +- data->is_gray = 1; +- data->bpp = 1; ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: color type not supported"); + } + + if ((color_bits != 8) && (color_bits != 16) + && (color_bits != 4 +- || !(data->is_gray || data->is_palette))) ++ || !data->is_palette)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "png: bit depth must be 8 or 16"); + +@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data) + } + + #ifndef GRUB_CPU_WORDS_BIGENDIAN +- if (data->is_16bit || data->is_gray || data->is_palette) ++ if (data->is_16bit || data->is_palette) + #endif + { + data->image_data = grub_calloc (data->image_height, data->row_bytes); +@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data) + int shift; + int mask = (1 << data->color_bits) - 1; + unsigned j; +- if (data->is_gray) +- { +- /* Generic formula is +- (0xff * i) / ((1U << data->color_bits) - 1) +- but for allowed bit depth of 1, 2 and for it's +- equivalent to +- (0xff / ((1U << data->color_bits) - 1)) * i +- Precompute the multipliers to avoid division. +- */ + +- const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 }; +- for (i = 0; i < (1U << data->color_bits); i++) +- { +- grub_uint8_t col = multipliers[data->color_bits] * i; +- palette[i][0] = col; +- palette[i][1] = col; +- palette[i][2] = col; +- } +- } +- else +- grub_memcpy (palette, data->palette, 3 << data->color_bits); ++ grub_memcpy (palette, data->palette, 3 << data->color_bits); + d1c = d1; + d2c = d2; + for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3, +@@ -956,60 +937,6 @@ grub_png_convert_image (struct grub_png_data *data) + } + return; + } +- +- if (data->is_gray) +- { +- switch (data->bpp) +- { +- case 4: +- /* 16-bit gray with alpha. */ +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 4, d2 += 4) +- { +- d1[R4] = d2[3]; +- d1[G4] = d2[3]; +- d1[B4] = d2[3]; +- d1[A4] = d2[1]; +- } +- break; +- case 2: +- if (data->is_16bit) +- /* 16-bit gray without alpha. */ +- { +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 4, d2 += 2) +- { +- d1[R3] = d2[1]; +- d1[G3] = d2[1]; +- d1[B3] = d2[1]; +- } +- } +- else +- /* 8-bit gray with alpha. */ +- { +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 4, d2 += 2) +- { +- d1[R4] = d2[1]; +- d1[G4] = d2[1]; +- d1[B4] = d2[1]; +- d1[A4] = d2[0]; +- } +- } +- break; +- /* 8-bit gray without alpha. */ +- case 1: +- for (i = 0; i < (data->image_width * data->image_height); +- i++, d1 += 3, d2++) +- { +- d1[R3] = d2[0]; +- d1[G3] = d2[0]; +- d1[B3] = d2[0]; +- } +- break; +- } +- return; +- } + + { + /* Only copy the upper 8 bit. */ diff --git a/SOURCES/0224-grub-mkconfig-restore-umask-for-grub.cfg.patch b/SOURCES/0224-grub-mkconfig-restore-umask-for-grub.cfg.patch deleted file mode 100644 index bd1bd0c..0000000 --- a/SOURCES/0224-grub-mkconfig-restore-umask-for-grub.cfg.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michael Chang via Grub-devel -Date: Fri, 3 Dec 2021 16:13:28 +0800 -Subject: [PATCH] grub-mkconfig: restore umask for grub.cfg - -Since commit: - - ab2e53c8a grub-mkconfig: Honor a symlink when generating configuration -by grub-mkconfig - -has inadvertently discarded umask for creating grub.cfg in the process -of grub-mkconfig. The resulting wrong permission (0644) would allow -unprivileged users to read grub's configuration file content. This -presents a low confidentiality risk as grub.cfg may contain non-secured -plain-text passwords. - -This patch restores the missing umask and set the file mode of creation -to 0600 preventing unprivileged access. - -Fixes: CVE-2021-3981 - -Signed-off-by: Michael Chang -(cherry picked from commit 2acad06610da1488bfa387f56a847119ab758766) ---- - util/grub-mkconfig.in | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in -index f55339a3f64..520a672cd2c 100644 ---- a/util/grub-mkconfig.in -+++ b/util/grub-mkconfig.in -@@ -311,7 +311,9 @@ and /etc/grub.d/* files or please file a bug report with - exit 1 - else - # none of the children aborted with error, install the new grub.cfg -+ oldumask=$(umask); umask 077 - cat ${grub_cfg}.new > ${grub_cfg} -+ umask $oldumask - rm -f ${grub_cfg}.new - fi - fi diff --git a/SOURCES/0224-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch b/SOURCES/0224-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch new file mode 100644 index 0000000..51dddfe --- /dev/null +++ b/SOURCES/0224-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 23:25:07 +1000 +Subject: [PATCH] video/readers/png: Avoid heap OOB R/W inserting huff table + items + +In fuzzing we observed crashes where a code would attempt to be inserted +into a huffman table before the start, leading to a set of heap OOB reads +and writes as table entries with negative indices were shifted around and +the new code written in. + +Catch the case where we would underflow the array and bail. + +Fixes: CVE-2021-3696 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 1ae9a91d42cb40da8a6f11fac65541858e340afa) +--- + grub-core/video/readers/png.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index a3161e25b6..d7ed5aa6cf 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len) + for (i = len; i < ht->max_length; i++) + n += ht->maxval[i]; + ++ if (n > ht->num_values) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: out of range inserting huffman table item"); ++ return; ++ } ++ + for (i = 0; i < n; i++) + ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1]; + diff --git a/SOURCES/0225-commands-search-Fix-bug-stopping-iteration-when-no-f.patch b/SOURCES/0225-commands-search-Fix-bug-stopping-iteration-when-no-f.patch deleted file mode 100644 index c5971ac..0000000 --- a/SOURCES/0225-commands-search-Fix-bug-stopping-iteration-when-no-f.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Tue, 8 Feb 2022 08:39:10 +0100 -Subject: [PATCH] commands/search: Fix bug stopping iteration when --no-floppy - is used -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When using --no-floppy and a floppy was encountered, iterate_device() -was returning 1, causing the iteration to stop instead of continuing. - -Signed-off-by: Renaud Métrich -Reviewed-by: Daniel Kiper -(cherry picked from commit 68ba54c2298604146be83cae144dafd1cfd1fe2d) -Signed-off-by: Robbie Harwood -(cherry picked from commit 7ada55e3fcd16e00773d3918955b2b945b7f063a) ---- - grub-core/commands/search.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c -index ed090b3af8b..51656e361cc 100644 ---- a/grub-core/commands/search.c -+++ b/grub-core/commands/search.c -@@ -64,7 +64,7 @@ iterate_device (const char *name, void *data) - /* Skip floppy drives when requested. */ - if (ctx->no_floppy && - name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') -- return 1; -+ return 0; - - #ifdef DO_SEARCH_FS_UUID - #define compare_fn grub_strcasecmp diff --git a/SOURCES/0225-video-readers-png-Sanity-check-some-huffman-codes.patch b/SOURCES/0225-video-readers-png-Sanity-check-some-huffman-codes.patch new file mode 100644 index 0000000..c9cef25 --- /dev/null +++ b/SOURCES/0225-video-readers-png-Sanity-check-some-huffman-codes.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 6 Jul 2021 19:19:11 +1000 +Subject: [PATCH] video/readers/png: Sanity check some huffman codes + +ASAN picked up two OOB global reads: we weren't checking if some code +values fit within the cplens or cpdext arrays. Check and throw an error +if not. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit c3a8ab0cbd24153ec7b1f84a96ddfdd72ef8d117) +--- + grub-core/video/readers/png.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index d7ed5aa6cf..7f2ba7849b 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) + int len, dist, pos; + + n -= 257; ++ if (((unsigned int) n) >= ARRAY_SIZE (cplens)) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: invalid huff code"); + len = cplens[n]; + if (cplext[n]) + len += grub_png_get_bits (data, cplext[n]); +@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) + return grub_errno; + + n = grub_png_get_huff_code (data, &data->dist_table); ++ if (((unsigned int) n) >= ARRAY_SIZE (cpdist)) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "png: invalid huff code"); + dist = cpdist[n]; + if (cpdext[n]) + dist += grub_png_get_bits (data, cpdext[n]); diff --git a/SOURCES/0226-search-new-efidisk-only-option-on-EFI-systems.patch b/SOURCES/0226-search-new-efidisk-only-option-on-EFI-systems.patch deleted file mode 100644 index 8e24dac..0000000 --- a/SOURCES/0226-search-new-efidisk-only-option-on-EFI-systems.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Tue, 8 Feb 2022 08:39:11 +0100 -Subject: [PATCH] search: new --efidisk-only option on EFI systems -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When using 'search' on EFI systems, we sometimes want to exclude devices -that are not EFI disks (e.g. md, lvm). -This is typically used when wanting to chainload when having a software -raid (md) for EFI partition: -with no option, 'search --file /EFI/redhat/shimx64.efi' sets root envvar -to 'md/boot_efi' which cannot be used for chainloading since there is no -effective EFI device behind. - -This commit also refactors handling of --no-floppy option. - -Signed-off-by: Renaud Métrich -[rharwood: apply rmetrich's flags initialization fix] -Signed-off-by: Robbie Harwood -(cherry picked from commit fdd8396f4fa750bbbabd4298f2593942f2b84710) ---- - grub-core/commands/search.c | 27 +++++++++++++++++++++++---- - grub-core/commands/search_wrap.c | 18 ++++++++++++------ - include/grub/search.h | 15 ++++++++++++--- - 3 files changed, 47 insertions(+), 13 deletions(-) - -diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c -index 51656e361cc..57d26ced8a8 100644 ---- a/grub-core/commands/search.c -+++ b/grub-core/commands/search.c -@@ -47,7 +47,7 @@ struct search_ctx - { - const char *key; - const char *var; -- int no_floppy; -+ enum search_flags flags; - char **hints; - unsigned nhints; - int count; -@@ -62,10 +62,29 @@ iterate_device (const char *name, void *data) - int found = 0; - - /* Skip floppy drives when requested. */ -- if (ctx->no_floppy && -+ if (ctx->flags & SEARCH_FLAGS_NO_FLOPPY && - name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') - return 0; - -+ /* Limit to EFI disks when requested. */ -+ if (ctx->flags & SEARCH_FLAGS_EFIDISK_ONLY) -+ { -+ grub_device_t dev; -+ dev = grub_device_open (name); -+ if (! dev) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ if (! dev->disk || dev->disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID) -+ { -+ grub_device_close (dev); -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } -+ grub_device_close (dev); -+ } -+ - #ifdef DO_SEARCH_FS_UUID - #define compare_fn grub_strcasecmp - #else -@@ -261,13 +280,13 @@ try (struct search_ctx *ctx) - } - - void --FUNC_NAME (const char *key, const char *var, int no_floppy, -+FUNC_NAME (const char *key, const char *var, enum search_flags flags, - char **hints, unsigned nhints) - { - struct search_ctx ctx = { - .key = key, - .var = var, -- .no_floppy = no_floppy, -+ .flags = flags, - .hints = hints, - .nhints = nhints, - .count = 0, -diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c -index 47fc8eb9966..0b62acf8535 100644 ---- a/grub-core/commands/search_wrap.c -+++ b/grub-core/commands/search_wrap.c -@@ -40,6 +40,7 @@ static const struct grub_arg_option options[] = - N_("Set a variable to the first device found."), N_("VARNAME"), - ARG_TYPE_STRING}, - {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, -+ {"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0}, - {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, - N_("First try the device HINT. If HINT ends in comma, " - "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, -@@ -73,6 +74,7 @@ enum options - SEARCH_FS_UUID, - SEARCH_SET, - SEARCH_NO_FLOPPY, -+ SEARCH_EFIDISK_ONLY, - SEARCH_HINT, - SEARCH_HINT_IEEE1275, - SEARCH_HINT_BIOS, -@@ -89,6 +91,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) - const char *id = 0; - int i = 0, j = 0, nhints = 0; - char **hints = NULL; -+ enum search_flags flags = 0; - - if (state[SEARCH_HINT].set) - for (i = 0; state[SEARCH_HINT].args[i]; i++) -@@ -180,15 +183,18 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) - goto out; - } - -+ if (state[SEARCH_NO_FLOPPY].set) -+ flags |= SEARCH_FLAGS_NO_FLOPPY; -+ -+ if (state[SEARCH_EFIDISK_ONLY].set) -+ flags |= SEARCH_FLAGS_EFIDISK_ONLY; -+ - if (state[SEARCH_LABEL].set) -- grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, -- hints, nhints); -+ grub_search_label (id, var, flags, hints, nhints); - else if (state[SEARCH_FS_UUID].set) -- grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set, -- hints, nhints); -+ grub_search_fs_uuid (id, var, flags, hints, nhints); - else if (state[SEARCH_FILE].set) -- grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, -- hints, nhints); -+ grub_search_fs_file (id, var, flags, hints, nhints); - else - grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); - -diff --git a/include/grub/search.h b/include/grub/search.h -index d80347df34b..4190aeb2cbf 100644 ---- a/include/grub/search.h -+++ b/include/grub/search.h -@@ -19,11 +19,20 @@ - #ifndef GRUB_SEARCH_HEADER - #define GRUB_SEARCH_HEADER 1 - --void grub_search_fs_file (const char *key, const char *var, int no_floppy, -+enum search_flags -+ { -+ SEARCH_FLAGS_NO_FLOPPY = 1, -+ SEARCH_FLAGS_EFIDISK_ONLY = 2 -+ }; -+ -+void grub_search_fs_file (const char *key, const char *var, -+ enum search_flags flags, - char **hints, unsigned nhints); --void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, -+void grub_search_fs_uuid (const char *key, const char *var, -+ enum search_flags flags, - char **hints, unsigned nhints); --void grub_search_label (const char *key, const char *var, int no_floppy, -+void grub_search_label (const char *key, const char *var, -+ enum search_flags flags, - char **hints, unsigned nhints); - - #endif diff --git a/SOURCES/0226-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch b/SOURCES/0226-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch new file mode 100644 index 0000000..5491816 --- /dev/null +++ b/SOURCES/0226-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch @@ -0,0 +1,255 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 28 Jun 2021 14:16:14 +1000 +Subject: [PATCH] video/readers/jpeg: Abort sooner if a read operation fails + +Fuzzing revealed some inputs that were taking a long time, potentially +forever, because they did not bail quickly upon encountering an I/O error. + +Try to catch I/O errors sooner and bail out. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit ab2e5d2e4bff488bbb557ed435a61ae102ef9f0c) +--- + grub-core/video/readers/jpeg.c | 86 ++++++++++++++++++++++++++++++++++-------- + 1 file changed, 70 insertions(+), 16 deletions(-) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index e31602f766..10225abd53 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -109,9 +109,17 @@ static grub_uint8_t + grub_jpeg_get_byte (struct grub_jpeg_data *data) + { + grub_uint8_t r; ++ grub_ssize_t bytes_read; + + r = 0; +- grub_file_read (data->file, &r, 1); ++ bytes_read = grub_file_read (data->file, &r, 1); ++ ++ if (bytes_read != 1) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: unexpected end of data"); ++ return 0; ++ } + + return r; + } +@@ -120,9 +128,17 @@ static grub_uint16_t + grub_jpeg_get_word (struct grub_jpeg_data *data) + { + grub_uint16_t r; ++ grub_ssize_t bytes_read; + + r = 0; +- grub_file_read (data->file, &r, sizeof (grub_uint16_t)); ++ bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t)); ++ ++ if (bytes_read != sizeof (grub_uint16_t)) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: unexpected end of data"); ++ return 0; ++ } + + return grub_be_to_cpu16 (r); + } +@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) + if (data->bit_mask == 0) + { + data->bit_save = grub_jpeg_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: file read error"); ++ return 0; ++ } + if (data->bit_save == JPEG_ESC_CHAR) + { + if (grub_jpeg_get_byte (data) != 0) +@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) + "jpeg: invalid 0xFF in data stream"); + return 0; + } ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error"); ++ return 0; ++ } + } + data->bit_mask = 0x80; + } +@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num) + return 0; + + msb = value = grub_jpeg_get_bit (data); +- for (i = 1; i < num; i++) ++ for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++) + value = (value << 1) + (grub_jpeg_get_bit (data) != 0); + if (!msb) + value += 1 - (1 << num); +@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) + while (data->file->offset + sizeof (count) + 1 <= next_marker) + { + id = grub_jpeg_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + ac = (id >> 4) & 1; + id &= 0xF; + if (id > 1) +@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) + + next_marker = data->file->offset; + next_marker += grub_jpeg_get_word (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + + if (next_marker > data->file->size) + { +@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) + <= next_marker) + { + id = grub_jpeg_get_byte (data); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (id >= 0x10) /* Upper 4-bit is precision. */ + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: only 8-bit precision is supported"); +@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) + next_marker = data->file->offset; + next_marker += grub_jpeg_get_word (data); + ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ + if (grub_jpeg_get_byte (data) != 8) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: only 8-bit precision is supported"); +@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); + + ss = grub_jpeg_get_byte (data); /* Sampling factor. */ ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (!id) + { + grub_uint8_t vs, hs; +@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du) + } + } + +-static void ++static grub_err_t + grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + { + int h1, h2, qt; +@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + data->dc_value[id] += + grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1)); + ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ + du[0] = data->dc_value[id] * (int) data->quan_table[qt][0]; + pos = 1; + while (pos < ARRAY_SIZE (data->quan_table[qt])) +@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + num >>= 4; + pos += num; + ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; ++ + if (pos >= ARRAY_SIZE (jpeg_zigzag_order)) + { +- grub_error (GRUB_ERR_BAD_FILE_TYPE, +- "jpeg: invalid position in zigzag order!?"); +- return; ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: invalid position in zigzag order!?"); + } + + du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos]; +@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) + } + + grub_jpeg_idct_transform (du); ++ return GRUB_ERR_NONE; + } + + static void +@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + data_offset += grub_jpeg_get_word (data); + + cc = grub_jpeg_get_byte (data); +- ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (cc != 3 && cc != 1) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: component count must be 1 or 3"); +@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + id = grub_jpeg_get_byte (data) - 1; + if ((id < 0) || (id >= 3)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); +- ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + ht = grub_jpeg_get_byte (data); + data->comp_index[id][1] = (ht >> 4); + data->comp_index[id][2] = (ht & 0xF) + 2; +@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) || + (data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index"); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + } + + grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */ + grub_jpeg_get_word (data); +- ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_errno; + if (data->file->offset != data_offset) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); + +@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + { + unsigned c1, vb, hb, nr1, nc1; + int rst = data->dri; ++ grub_err_t err = GRUB_ERR_NONE; + + vb = 8 << data->log_vs; + hb = 8 << data->log_hs; +@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + + for (r2 = 0; r2 < (1U << data->log_vs); r2++) + for (c2 = 0; c2 < (1U << data->log_hs); c2++) +- grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); ++ { ++ err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } + + if (data->color_components >= 3) + { +- grub_jpeg_decode_du (data, 1, data->cbdu); +- grub_jpeg_decode_du (data, 2, data->crdu); ++ err = grub_jpeg_decode_du (data, 1, data->cbdu); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ err = grub_jpeg_decode_du (data, 2, data->crdu); ++ if (err != GRUB_ERR_NONE) ++ return err; + } + +- if (grub_errno) +- return grub_errno; +- + nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb; + nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb; + diff --git a/SOURCES/0227-efi-new-connectefi-command.patch b/SOURCES/0227-efi-new-connectefi-command.patch deleted file mode 100644 index abb6f6f..0000000 --- a/SOURCES/0227-efi-new-connectefi-command.patch +++ /dev/null @@ -1,396 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Renaud=20M=C3=A9trich?= -Date: Tue, 15 Feb 2022 14:05:22 +0100 -Subject: [PATCH] efi: new 'connectefi' command -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When efi.quickboot is enabled on VMWare (which is the default for -hardware release 16 and later), it may happen that not all EFI devices -are connected. Due to this, browsing the devices in make_devices() just -fails to find devices, in particular disks or partitions for a given -disk. -This typically happens when network booting, then trying to chainload to -local disk (this is used in deployment tools such as Red Hat Satellite), -which is done through using the following grub.cfg snippet: --------- 8< ---------------- 8< ---------------- 8< -------- -unset prefix -search --file --set=prefix /EFI/redhat/grubx64.efi -if [ -n "$prefix" ]; then - chainloader ($prefix)/EFI/redhat/grubx64/efi -... --------- 8< ---------------- 8< ---------------- 8< -------- - -With efi.quickboot, none of the devices are connected, causing "search" -to fail. Sometimes devices are connected but not the partition of the -disk matching $prefix, causing partition to not be found by -"chainloader". - -This patch introduces a new "connectefi pciroot|scsi" command which -recursively connects all EFI devices starting from a given controller -type: -- if 'pciroot' is specified, recursion is performed for all PCI root - handles -- if 'scsi' is specified, recursion is performed for all SCSI I/O - handles (recommended usage to avoid connecting unwanted handles which - may impact Grub performances) - -Typical grub.cfg snippet would then be: --------- 8< ---------------- 8< ---------------- 8< -------- -connectefi scsi -unset prefix -search --file --set=prefix /EFI/redhat/grubx64.efi -if [ -n "$prefix" ]; then - chainloader ($prefix)/EFI/redhat/grubx64/efi -... --------- 8< ---------------- 8< ---------------- 8< -------- - -The code is easily extensible to handle other arguments in the future if -needed. - -Signed-off-by: Renaud Métrich -Signed-off-by: Robbie Harwood -(cherry picked from commit cc972c27314c841f80ab0fe8318fae06f078c680) ---- - grub-core/Makefile.core.def | 6 ++ - grub-core/commands/efi/connectefi.c | 205 ++++++++++++++++++++++++++++++++++++ - grub-core/commands/efi/lsefi.c | 1 + - grub-core/disk/efi/efidisk.c | 13 +++ - grub-core/kern/efi/efi.c | 13 +++ - include/grub/efi/disk.h | 2 + - include/grub/efi/efi.h | 5 + - NEWS | 2 +- - 8 files changed, 246 insertions(+), 1 deletion(-) - create mode 100644 grub-core/commands/efi/connectefi.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 6b00eb55575..97abc01f064 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -833,6 +833,12 @@ module = { - enable = efi; - }; - -+module = { -+ name = connectefi; -+ common = commands/efi/connectefi.c; -+ enable = efi; -+}; -+ - module = { - name = blocklist; - common = commands/blocklist.c; -diff --git a/grub-core/commands/efi/connectefi.c b/grub-core/commands/efi/connectefi.c -new file mode 100644 -index 00000000000..8ab75bd51be ---- /dev/null -+++ b/grub-core/commands/efi/connectefi.c -@@ -0,0 +1,205 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+typedef struct handle_list -+{ -+ grub_efi_handle_t handle; -+ struct handle_list *next; -+} handle_list_t; -+ -+static handle_list_t *already_handled = NULL; -+ -+static grub_err_t -+add_handle (grub_efi_handle_t handle) -+{ -+ handle_list_t *e; -+ e = grub_malloc (sizeof (*e)); -+ if (! e) -+ return grub_errno; -+ e->handle = handle; -+ e->next = already_handled; -+ already_handled = e; -+ return GRUB_ERR_NONE; -+} -+ -+static int -+is_in_list (grub_efi_handle_t handle) -+{ -+ handle_list_t *e; -+ for (e = already_handled; e != NULL; e = e->next) -+ if (e->handle == handle) -+ return 1; -+ return 0; -+} -+ -+static void -+free_handle_list (void) -+{ -+ handle_list_t *e; -+ while ((e = already_handled) != NULL) -+ { -+ already_handled = already_handled->next; -+ grub_free (e); -+ } -+} -+ -+typedef enum searched_item_flag -+{ -+ SEARCHED_ITEM_FLAG_LOOP = 1, -+ SEARCHED_ITEM_FLAG_RECURSIVE = 2 -+} searched_item_flags; -+ -+typedef struct searched_item -+{ -+ grub_efi_guid_t guid; -+ const char *name; -+ searched_item_flags flags; -+} searched_items; -+ -+static grub_err_t -+grub_cmd_connectefi (grub_command_t cmd __attribute__ ((unused)), -+ int argc, char **args) -+{ -+ unsigned s; -+ searched_items pciroot_items[] = -+ { -+ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", SEARCHED_ITEM_FLAG_RECURSIVE } -+ }; -+ searched_items scsi_items[] = -+ { -+ { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root", 0 }, -+ { GRUB_EFI_PCI_IO_GUID, "PCI", SEARCHED_ITEM_FLAG_LOOP }, -+ { GRUB_EFI_SCSI_IO_PROTOCOL_GUID, "SCSI I/O", SEARCHED_ITEM_FLAG_RECURSIVE } -+ }; -+ searched_items *items = NULL; -+ unsigned nitems = 0; -+ grub_err_t grub_err = GRUB_ERR_NONE; -+ unsigned total_connected = 0; -+ -+ if (argc != 1) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); -+ -+ if (grub_strcmp(args[0], N_("pciroot")) == 0) -+ { -+ items = pciroot_items; -+ nitems = ARRAY_SIZE (pciroot_items); -+ } -+ else if (grub_strcmp(args[0], N_("scsi")) == 0) -+ { -+ items = scsi_items; -+ nitems = ARRAY_SIZE (scsi_items); -+ } -+ else -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("unexpected argument `%s'"), args[0]); -+ -+ for (s = 0; s < nitems; s++) -+ { -+ grub_efi_handle_t *handles; -+ grub_efi_uintn_t num_handles; -+ unsigned i, connected = 0, loop = 0; -+ -+loop: -+ loop++; -+ grub_dprintf ("efi", "step '%s' loop %d:\n", items[s].name, loop); -+ -+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, -+ &items[s].guid, 0, &num_handles); -+ -+ if (!handles) -+ continue; -+ -+ for (i = 0; i < num_handles; i++) -+ { -+ grub_efi_handle_t handle = handles[i]; -+ grub_efi_status_t status; -+ unsigned j; -+ -+ /* Skip already handled handles */ -+ if (is_in_list (handle)) -+ { -+ grub_dprintf ("efi", " handle %p: already processed\n", -+ handle); -+ continue; -+ } -+ -+ status = grub_efi_connect_controller(handle, NULL, NULL, -+ items[s].flags & SEARCHED_ITEM_FLAG_RECURSIVE ? 1 : 0); -+ if (status == GRUB_EFI_SUCCESS) -+ { -+ connected++; -+ total_connected++; -+ grub_dprintf ("efi", " handle %p: connected\n", handle); -+ } -+ else -+ grub_dprintf ("efi", " handle %p: failed to connect (%d)\n", -+ handle, (grub_efi_int8_t) status); -+ -+ if ((grub_err = add_handle (handle)) != GRUB_ERR_NONE) -+ break; /* fatal */ -+ } -+ -+ grub_free (handles); -+ if (grub_err != GRUB_ERR_NONE) -+ break; /* fatal */ -+ -+ if (items[s].flags & SEARCHED_ITEM_FLAG_LOOP && connected) -+ { -+ connected = 0; -+ goto loop; -+ } -+ -+ free_handle_list (); -+ } -+ -+ free_handle_list (); -+ -+ if (total_connected) -+ grub_efidisk_reenumerate_disks (); -+ -+ return grub_err; -+} -+ -+static grub_command_t cmd; -+ -+GRUB_MOD_INIT(connectefi) -+{ -+ cmd = grub_register_command ("connectefi", grub_cmd_connectefi, -+ N_("pciroot|scsi"), -+ N_("Connect EFI handles." -+ " If 'pciroot' is specified, connect PCI" -+ " root EFI handles recursively." -+ " If 'scsi' is specified, connect SCSI" -+ " I/O EFI handles recursively.")); -+} -+ -+GRUB_MOD_FINI(connectefi) -+{ -+ grub_unregister_command (cmd); -+} -diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c -index d1ce99af438..f2d2430e666 100644 ---- a/grub-core/commands/efi/lsefi.c -+++ b/grub-core/commands/efi/lsefi.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c -index fe8ba6e6c93..062143dfffd 100644 ---- a/grub-core/disk/efi/efidisk.c -+++ b/grub-core/disk/efi/efidisk.c -@@ -396,6 +396,19 @@ enumerate_disks (void) - free_devices (devices); - } - -+void -+grub_efidisk_reenumerate_disks (void) -+{ -+ free_devices (fd_devices); -+ free_devices (hd_devices); -+ free_devices (cd_devices); -+ fd_devices = 0; -+ hd_devices = 0; -+ cd_devices = 0; -+ -+ enumerate_disks (); -+} -+ - static int - grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, - grub_disk_pull_t pull) -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index 14bc10eb564..7fcca69c17b 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -95,6 +95,19 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, - return buffer; - } - -+grub_efi_status_t -+grub_efi_connect_controller (grub_efi_handle_t controller_handle, -+ grub_efi_handle_t *driver_image_handle, -+ grub_efi_device_path_protocol_t *remaining_device_path, -+ grub_efi_boolean_t recursive) -+{ -+ grub_efi_boot_services_t *b; -+ -+ b = grub_efi_system_table->boot_services; -+ return efi_call_4 (b->connect_controller, controller_handle, -+ driver_image_handle, remaining_device_path, recursive); -+} -+ - void * - grub_efi_open_protocol (grub_efi_handle_t handle, - grub_efi_guid_t *protocol, -diff --git a/include/grub/efi/disk.h b/include/grub/efi/disk.h -index 254475c8428..6845c2f1fd8 100644 ---- a/include/grub/efi/disk.h -+++ b/include/grub/efi/disk.h -@@ -27,6 +27,8 @@ grub_efi_handle_t - EXPORT_FUNC(grub_efidisk_get_device_handle) (grub_disk_t disk); - char *EXPORT_FUNC(grub_efidisk_get_device_name) (grub_efi_handle_t *handle); - -+void EXPORT_FUNC(grub_efidisk_reenumerate_disks) (void); -+ - void grub_efidisk_init (void); - void grub_efidisk_fini (void); - -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 8dfc89a33b9..ec52083c49f 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -41,6 +41,11 @@ EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type, - grub_efi_guid_t *protocol, - void *search_key, - grub_efi_uintn_t *num_handles); -+grub_efi_status_t -+EXPORT_FUNC(grub_efi_connect_controller) (grub_efi_handle_t controller_handle, -+ grub_efi_handle_t *driver_image_handle, -+ grub_efi_device_path_protocol_t *remaining_device_path, -+ grub_efi_boolean_t recursive); - void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle, - grub_efi_guid_t *protocol, - grub_efi_uint32_t attributes); -diff --git a/NEWS b/NEWS -index 73b8492bc42..d7c1d23aed7 100644 ---- a/NEWS -+++ b/NEWS -@@ -98,7 +98,7 @@ New in 2.02: - * Prefer pmtimer for TSC calibration. - - * New/improved platform support: -- * New `efifwsetup' and `lsefi' commands on EFI platforms. -+ * New `efifwsetup', `lsefi' and `connectefi` commands on EFI platforms. - * New `cmosdump' and `cmosset' commands on platforms with CMOS support. - * New command `pcidump' for PCI platforms. - * Improve opcode parsing in ACPI halt implementation. diff --git a/SOURCES/0227-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch b/SOURCES/0227-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch new file mode 100644 index 0000000..199ec32 --- /dev/null +++ b/SOURCES/0227-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 28 Jun 2021 14:16:58 +1000 +Subject: [PATCH] video/readers/jpeg: Do not reallocate a given huff table + +Fix a memory leak where an invalid file could cause us to reallocate +memory for a huffman table we had already allocated memory for. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit bc06e12b4de55cc6f926af9f064170c82b1403e9) +--- + grub-core/video/readers/jpeg.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index 10225abd53..caa211f06d 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) + n += count[i]; + + id += ac * 2; ++ if (data->huff_value[id] != NULL) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: attempt to reallocate huffman table"); + data->huff_value[id] = grub_malloc (n); + if (grub_errno) + return grub_errno; diff --git a/SOURCES/0228-powerpc-do-CAS-in-a-more-compatible-way.patch b/SOURCES/0228-powerpc-do-CAS-in-a-more-compatible-way.patch deleted file mode 100644 index 32c06b0..0000000 --- a/SOURCES/0228-powerpc-do-CAS-in-a-more-compatible-way.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 8 Apr 2022 12:35:28 +1000 -Subject: [PATCH] powerpc: do CAS in a more compatible way - -I wrongly assumed that the most compatible way to perform CAS -negotiation was to only set the minimum number of vectors required -to ask for more memory. It turns out that this messes up booting -if the minimum VP capacity would be less than the default 10% in -vector 4. - -Linux configures the minimum capacity to be 1%, so copy it for that -and for vector 3 which we now need to specify as well. - -Signed-off-by: Daniel Axtens -(cherry picked from commit e6f02ad4e75cd995a8ee2954d28949c415b6cbfe) ---- - grub-core/kern/ieee1275/init.c | 54 ++++++++++++++++++++++++------------------ - 1 file changed, 31 insertions(+), 23 deletions(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index 9704715c83..ef55107467 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -298,33 +298,37 @@ grub_ieee1275_total_mem (grub_uint64_t *total) - - /* Based on linux - arch/powerpc/kernel/prom_init.c */ - struct option_vector2 { -- grub_uint8_t byte1; -- grub_uint16_t reserved; -- grub_uint32_t real_base; -- grub_uint32_t real_size; -- grub_uint32_t virt_base; -- grub_uint32_t virt_size; -- grub_uint32_t load_base; -- grub_uint32_t min_rma; -- grub_uint32_t min_load; -- grub_uint8_t min_rma_percent; -- grub_uint8_t max_pft_size; -+ grub_uint8_t byte1; -+ grub_uint16_t reserved; -+ grub_uint32_t real_base; -+ grub_uint32_t real_size; -+ grub_uint32_t virt_base; -+ grub_uint32_t virt_size; -+ grub_uint32_t load_base; -+ grub_uint32_t min_rma; -+ grub_uint32_t min_load; -+ grub_uint8_t min_rma_percent; -+ grub_uint8_t max_pft_size; - } __attribute__((packed)); - - struct pvr_entry { -- grub_uint32_t mask; -- grub_uint32_t entry; -+ grub_uint32_t mask; -+ grub_uint32_t entry; - }; - - struct cas_vector { -- struct { -- struct pvr_entry terminal; -- } pvr_list; -- grub_uint8_t num_vecs; -- grub_uint8_t vec1_size; -- grub_uint8_t vec1; -- grub_uint8_t vec2_size; -- struct option_vector2 vec2; -+ struct { -+ struct pvr_entry terminal; -+ } pvr_list; -+ grub_uint8_t num_vecs; -+ grub_uint8_t vec1_size; -+ grub_uint8_t vec1; -+ grub_uint8_t vec2_size; -+ struct option_vector2 vec2; -+ grub_uint8_t vec3_size; -+ grub_uint16_t vec3; -+ grub_uint8_t vec4_size; -+ grub_uint16_t vec4; - } __attribute__((packed)); - - /* Call ibm,client-architecture-support to try to get more RMA. -@@ -345,13 +349,17 @@ grub_ieee1275_ibm_cas (void) - } args; - struct cas_vector vector = { - .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ -- .num_vecs = 2 - 1, -+ .num_vecs = 4 - 1, - .vec1_size = 0, - .vec1 = 0x80, /* ignore */ - .vec2_size = 1 + sizeof(struct option_vector2) - 2, - .vec2 = { - 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48 - }, -+ .vec3_size = 2 - 1, -+ .vec3 = 0x00e0, // ask for FP + VMX + DFP but don't halt if unsatisfied -+ .vec4_size = 2 - 1, -+ .vec4 = 0x0001, // set required minimum capacity % to the lowest value - }; - - INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); -@@ -364,7 +372,7 @@ grub_ieee1275_ibm_cas (void) - args.ihandle = root; - args.cas_addr = (grub_ieee1275_cell_t)&vector; - -- grub_printf("Calling ibm,client-architecture-support..."); -+ grub_printf("Calling ibm,client-architecture-support from grub..."); - IEEE1275_CALL_ENTRY_FN (&args); - grub_printf("done\n"); - diff --git a/SOURCES/0228-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch b/SOURCES/0228-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch new file mode 100644 index 0000000..179238b --- /dev/null +++ b/SOURCES/0228-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 28 Jun 2021 14:25:17 +1000 +Subject: [PATCH] video/readers/jpeg: Refuse to handle multiple start of + streams + +An invalid file could contain multiple start of stream blocks, which +would cause us to reallocate and leak our bitmap. Refuse to handle +multiple start of streams. + +Additionally, fix a grub_error() call formatting. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit f3a854def3e281b7ad4bbea730cd3046de1da52f) +--- + grub-core/video/readers/jpeg.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index caa211f06d..1df1171d78 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) + if (data->file->offset != data_offset) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); + ++ if (*data->bitmap) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks"); ++ + if (grub_video_bitmap_create (data->bitmap, data->image_width, + data->image_height, + GRUB_VIDEO_BLIT_FORMAT_RGB_888)) +@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + nc1 = (data->image_width + hb - 1) >> (3 + data->log_hs); + + if (data->bitmap_ptr == NULL) +- return grub_error(GRUB_ERR_BAD_FILE_TYPE, +- "jpeg: attempted to decode data before start of stream"); ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: attempted to decode data before start of stream"); + + for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) diff --git a/SOURCES/0229-powerpc-prefix-detection-support-device-names-with-c.patch b/SOURCES/0229-powerpc-prefix-detection-support-device-names-with-c.patch deleted file mode 100644 index a0aeb10..0000000 --- a/SOURCES/0229-powerpc-prefix-detection-support-device-names-with-c.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 24 Mar 2022 14:34:32 +1100 -Subject: [PATCH] powerpc: prefix detection: support device names with commas - -Frustratingly, the device name itself can contain an embedded comma: -e.g /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b - -So my previous approach was wrong: we cannot rely upon the presence -of a comma to say that a partition has been specified! - -It turns out for prefixes like (,gpt2)/grub2 we really want to make -up a full (device,partition)/patch prefix, because root discovery code -in 10_linux will reset the root variable and use search to fill it again. -If you have run grub-install, you probably don't have search built in, -and if you don't have prefix containing (device,partition), grub will -construct ($root)$prefix/powerpc-ieee1275/search.mod - but because $root -has just been changed, this will no longer work, and the boot will fail! - -Retain the gist of the logic, but instead of looking for a comma, look for -a leading '('. This matches the earlier code better anyway. - -There's certainly a better fix to be had. But any time you chose to build -with a bare prefix like '/grub2', you're almost certainly going to build in -search anyway, so this will do. - -Signed-off-by: Daniel Axtens -(cherry picked from commit 80b6eb5e55e6d1a4c9896361e61de31c29e6939d) ---- - grub-core/kern/main.c | 27 +++++++++++++++++++++------ - 1 file changed, 21 insertions(+), 6 deletions(-) - -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index 2d0d2bbd4c..4c4e6912f9 100644 ---- a/grub-core/kern/main.c -+++ b/grub-core/kern/main.c -@@ -242,14 +242,29 @@ grub_set_prefix_and_root (void) - what sorts of paths represent disks with partition tables and those - without partition tables. - -- So we act unless there is a comma in the device, which would indicate -- a partition has already been specified. -+ - Frustratingly, the device name itself can contain an embedded comma: -+ /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b -+ So we cannot even rely upon the presence of a comma to say that a -+ partition has been specified! - -- (If we only have a path, the code in normal to discover config files -- will try both without partitions and then with any partitions so we -- will cover both CDs and HDs.) -+ If we only have a path in $prefix, the code in normal to discover -+ config files will try all disks, both without partitions and then with -+ any partitions so we will cover both CDs and HDs. -+ -+ However, it doesn't then set the prefix to be something like -+ (discovered partition)/path, and so it is fragile against runtime -+ changes to $root. For example some of the stuff done in 10_linux to -+ reload $root sets root differently and then uses search to find it -+ again. If the search module is not built in, when we change root, grub -+ will look in (new root)/path/powerpc-ieee1275, that won't work, and we -+ will not be able to load the search module and the boot will fail. -+ -+ This is particularly likely to hit us in the grub-install -+ (,msdos2)/grub2 case, so we act unless the supplied prefix starts with -+ '(', which would likely indicate a partition has already been -+ specified. - */ -- if (grub_strchr (device, ',') == NULL) -+ if (prefix && prefix[0] != '(') - grub_env_set ("prefix", path); - else - #endif diff --git a/SOURCES/0229-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch b/SOURCES/0229-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch new file mode 100644 index 0000000..99eeb62 --- /dev/null +++ b/SOURCES/0229-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Wed, 7 Jul 2021 15:38:19 +1000 +Subject: [PATCH] video/readers/jpeg: Block int underflow -> wild pointer write + +Certain 1 px wide images caused a wild pointer write in +grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(), +we have the following loop: + +for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) + +We did not check if vb * width >= hb * nc1. + +On a 64-bit platform, if that turns out to be negative, it will underflow, +be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so +we see data->bitmap_ptr jump, e.g.: + +0x6180_0000_0480 to +0x6181_0000_0498 + ^ + ~--- carry has occurred and this pointer is now far away from + any object. + +On a 32-bit platform, it will decrement the pointer, creating a pointer +that won't crash but will overwrite random data. + +Catch the underflow and error out. + +Fixes: CVE-2021-3697 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 41aeb2004db9924fecd9f2dd64bc2a5a5594a4b5) +--- + grub-core/video/readers/jpeg.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c +index 1df1171d78..2da04094b3 100644 +--- a/grub-core/video/readers/jpeg.c ++++ b/grub-core/video/readers/jpeg.c +@@ -705,6 +705,10 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: attempted to decode data before start of stream"); + ++ if (vb * data->image_width <= hb * nc1) ++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, ++ "jpeg: cannot decode image with these dimensions"); ++ + for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) + for (c1 = 0; c1 < nc1 && (!data->dri || rst); diff --git a/SOURCES/0230-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch b/SOURCES/0230-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch deleted file mode 100644 index 00cf0f7..0000000 --- a/SOURCES/0230-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch +++ /dev/null @@ -1,237 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Sun, 15 Mar 2020 12:37:10 -0400 -Subject: [PATCH] ibmvtpm: Add support for trusted boot using a vTPM 2.0 - -Add support for trusted boot using a vTPM 2.0 on the IBM IEEE1275 -PowerPC platform. With this patch grub now measures text and binary data -into the TPM's PCRs 8 and 9 in the same way as the x86_64 platform -does. - -This patch requires Daniel Axtens's patches for claiming more memory. - -For vTPM support to work on PowerVM, system driver levels 1010.30 -or 1020.00 are required. - -Note: Previous versions of firmware levels with the 2hash-ext-log -API call have a bug that, once this API call is invoked, has the -effect of disabling the vTPM driver under Linux causing an error -message to be displayed in the Linux kernel log. Those users will -have to update their machines to the firmware levels mentioned -above. - -Cc: Eric Snowberg -Signed-off-by: Stefan Berger -(cherry picked from commit d3e5a8e6ecb8b87701135d97f45d27bbfbf731a2) ---- - grub-core/Makefile.core.def | 7 ++ - grub-core/commands/ieee1275/ibmvtpm.c | 152 ++++++++++++++++++++++++++++++++++ - include/grub/ieee1275/ieee1275.h | 3 + - docs/grub.texi | 3 +- - 4 files changed, 164 insertions(+), 1 deletion(-) - create mode 100644 grub-core/commands/ieee1275/ibmvtpm.c - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 97abc01f06..407d68f917 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1172,6 +1172,13 @@ module = { - enable = powerpc_ieee1275; - }; - -+module = { -+ name = tpm; -+ common = commands/tpm.c; -+ ieee1275 = commands/ieee1275/ibmvtpm.c; -+ enable = powerpc_ieee1275; -+}; -+ - module = { - name = terminal; - common = commands/terminal.c; -diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c -new file mode 100644 -index 0000000000..e68b8448bc ---- /dev/null -+++ b/grub-core/commands/ieee1275/ibmvtpm.c -@@ -0,0 +1,152 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2021 Free Software Foundation, Inc. -+ * Copyright (C) 2021 IBM Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ * -+ * IBM vTPM support code. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static grub_ieee1275_ihandle_t tpm_ihandle; -+static grub_uint8_t tpm_version; -+ -+#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t)0) -+ -+static void -+tpm_get_tpm_version (void) -+{ -+ grub_ieee1275_phandle_t vtpm; -+ char buffer[20]; -+ -+ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) && -+ !grub_ieee1275_get_property (vtpm, "compatible", buffer, -+ sizeof (buffer), NULL) && -+ !grub_strcmp (buffer, "IBM,vtpm20")) -+ tpm_version = 2; -+} -+ -+static grub_err_t -+tpm_init (void) -+{ -+ static int init_success = 0; -+ -+ if (!init_success) -+ { -+ if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0) { -+ tpm_ihandle = IEEE1275_IHANDLE_INVALID; -+ return GRUB_ERR_UNKNOWN_DEVICE; -+ } -+ -+ init_success = 1; -+ -+ tpm_get_tpm_version (); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static int -+ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex, -+ grub_uint32_t eventtype, -+ const char *description, -+ grub_size_t description_size, -+ void *buf, grub_size_t size) -+{ -+ struct tpm_2hash_ext_log -+ { -+ struct grub_ieee1275_common_hdr common; -+ grub_ieee1275_cell_t method; -+ grub_ieee1275_cell_t ihandle; -+ grub_ieee1275_cell_t size; -+ grub_ieee1275_cell_t buf; -+ grub_ieee1275_cell_t description_size; -+ grub_ieee1275_cell_t description; -+ grub_ieee1275_cell_t eventtype; -+ grub_ieee1275_cell_t pcrindex; -+ grub_ieee1275_cell_t catch_result; -+ grub_ieee1275_cell_t rc; -+ } -+ args; -+ -+ INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2); -+ args.method = (grub_ieee1275_cell_t) "2hash-ext-log"; -+ args.ihandle = tpm_ihandle; -+ args.pcrindex = pcrindex; -+ args.eventtype = eventtype; -+ args.description = (grub_ieee1275_cell_t) description; -+ args.description_size = description_size; -+ args.buf = (grub_ieee1275_cell_t) buf; -+ args.size = (grub_ieee1275_cell_t) size; -+ -+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1) -+ return -1; -+ -+ /* -+ * catch_result is set if firmware does not support 2hash-ext-log -+ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure -+ */ -+ if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE) -+ return -1; -+ -+ return 0; -+} -+ -+static grub_err_t -+tpm2_log_event (unsigned char *buf, -+ grub_size_t size, grub_uint8_t pcr, -+ const char *description) -+{ -+ static int error_displayed = 0; -+ int err; -+ -+ err = ibmvtpm_2hash_ext_log (pcr, EV_IPL, -+ description, -+ grub_strlen(description) + 1, -+ buf, size); -+ if (err && !error_displayed) -+ { -+ error_displayed++; -+ return grub_error (GRUB_ERR_BAD_DEVICE, -+ "2HASH-EXT-LOG failed: Firmware is likely too old.\n"); -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, -+ const char *description) -+{ -+ grub_err_t err = tpm_init(); -+ -+ /* Absence of a TPM isn't a failure. */ -+ if (err != GRUB_ERR_NONE) -+ return GRUB_ERR_NONE; -+ -+ grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n", -+ pcr, size, description); -+ -+ if (tpm_version == 2) -+ return tpm2_log_event (buf, size, pcr, description); -+ -+ return GRUB_ERR_NONE; -+} -diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h -index e0a6c2ce1e..f4c85265fe 100644 ---- a/include/grub/ieee1275/ieee1275.h -+++ b/include/grub/ieee1275/ieee1275.h -@@ -24,6 +24,9 @@ - #include - #include - -+#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0) -+#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1) -+ - struct grub_ieee1275_mem_region - { - unsigned int start; -diff --git a/docs/grub.texi b/docs/grub.texi -index a4da9c2a1b..c433240f34 100644 ---- a/docs/grub.texi -+++ b/docs/grub.texi -@@ -6221,7 +6221,8 @@ tpm module is loaded. As such it is recommended that the tpm module be built - into @file{core.img} in order to avoid a potential gap in measurement between - @file{core.img} being loaded and the tpm module being loaded. - --Measured boot is currently only supported on EFI platforms. -+Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC -+platforms. - - @node Lockdown - @section Lockdown when booting on a secure setup diff --git a/SOURCES/0230-normal-charset-Fix-array-out-of-bounds-formatting-un.patch b/SOURCES/0230-normal-charset-Fix-array-out-of-bounds-formatting-un.patch new file mode 100644 index 0000000..6e64ed8 --- /dev/null +++ b/SOURCES/0230-normal-charset-Fix-array-out-of-bounds-formatting-un.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 13 Jul 2021 13:24:38 +1000 +Subject: [PATCH] normal/charset: Fix array out-of-bounds formatting unicode + for display + +In some cases attempting to display arbitrary binary strings leads +to ASAN splats reading the widthspec array out of bounds. + +Check the index. If it would be out of bounds, return a width of 1. +I don't know if that's strictly correct, but we're not really expecting +great display of arbitrary binary data, and it's certainly not worse than +an OOB read. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit fdf32abc7a3928852422c0f291d8cd1dd6b34a8d) +--- + grub-core/normal/charset.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c +index 4dfcc31078..7a5a7c153c 100644 +--- a/grub-core/normal/charset.c ++++ b/grub-core/normal/charset.c +@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c) + { + if (grub_unicode_get_comb_type (c->base)) + return 0; ++ if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec)) ++ return 1; + if (widthspec[c->base >> 3] & (1 << (c->base & 7))) + return 2; + else diff --git a/SOURCES/0231-make-ofdisk_retries-optional.patch b/SOURCES/0231-make-ofdisk_retries-optional.patch deleted file mode 100644 index ac0bb44..0000000 --- a/SOURCES/0231-make-ofdisk_retries-optional.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Thu, 24 Mar 2022 13:14:42 -0400 -Subject: [PATCH] make ofdisk_retries optional - -The feature Retry on Fail added to GRUB can cause a LPM to take -longer if the SAN is slow. - -When a LPM to external site occur, the path of the disk can change -and thus the disk search function on grub can take some time since -it is used as a hint. This can cause the Retry on Fail feature to -try to access the disk 20x times (since this is hardcoded number) -and, if the SAN is slow, the boot time can increase a lot. -In some situations not acceptable. - -The following patch enables a configuration at user space of the -maximum number of retries we want for this feature. - -The variable ofdisk_retries should be set using grub2-editenv -and will be checked by retry function. If the variable is not set, -so the default number of retries will be used instead. - -(cherry picked from commit 4c5c7563f45a6410667ca08bcbfac4ab79d7de31) ---- - include/grub/ieee1275/ofdisk.h | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h -index 7d2d540930..0074d55eee 100644 ---- a/include/grub/ieee1275/ofdisk.h -+++ b/include/grub/ieee1275/ofdisk.h -@@ -25,7 +25,12 @@ extern void grub_ofdisk_fini (void); - #define MAX_RETRIES 20 - - --#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \ -+#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) \ -+ unsigned max_retries = MAX_RETRIES; \ -+ if(grub_env_get("ofdisk_retries") != NULL) \ -+ max_retries = grub_strtoul(grub_env_get("ofdisk_retries"), 0, 10)+1; \ -+ grub_dprintf("ofdisk","MAX_RETRIES set to %u\n",max_retries); \ -+ unsigned retry_i=0;for(retry_i=0; retry_i < max_retries; retry_i++){ \ - if(!grub_ieee1275_open(device, last_ihandle)) \ - break; \ - grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); } diff --git a/SOURCES/0231-net-netbuff-Block-overly-large-netbuff-allocs.patch b/SOURCES/0231-net-netbuff-Block-overly-large-netbuff-allocs.patch new file mode 100644 index 0000000..2e10d49 --- /dev/null +++ b/SOURCES/0231-net-netbuff-Block-overly-large-netbuff-allocs.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 8 Mar 2022 23:47:46 +1100 +Subject: [PATCH] net/netbuff: Block overly large netbuff allocs + +A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment +reassembly. + +This helps avoid some bugs (and provides a spot to instrument to catch +them at their source). + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit ee9591103004cd13b4efadda671536090ca7fd57) +--- + grub-core/net/netbuff.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c +index dbeeefe478..d5e9e9a0d7 100644 +--- a/grub-core/net/netbuff.c ++++ b/grub-core/net/netbuff.c +@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len) + + COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0); + ++ /* ++ * The largest size of a TCP packet is 64 KiB, and everything else ++ * should be a lot smaller - most MTUs are 1500 or less. Cap data ++ * size at 64 KiB + a buffer. ++ */ ++ if (len > 0xffffUL + 0x1000UL) ++ { ++ grub_error (GRUB_ERR_BUG, ++ "attempted to allocate a packet that is too big"); ++ return NULL; ++ } ++ + if (len < NETBUFFMINLEN) + len = NETBUFFMINLEN; + + len = ALIGN_UP (len, NETBUFF_ALIGN); ++ + #ifdef GRUB_MACHINE_EMU + data = grub_malloc (len + sizeof (*nb)); + #else diff --git a/SOURCES/0232-loader-efi-chainloader-grub_load_and_start_image-doe.patch b/SOURCES/0232-loader-efi-chainloader-grub_load_and_start_image-doe.patch deleted file mode 100644 index 3fcd8e4..0000000 --- a/SOURCES/0232-loader-efi-chainloader-grub_load_and_start_image-doe.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Thu, 28 Apr 2022 21:53:36 +0100 -Subject: [PATCH] loader/efi/chainloader: grub_load_and_start_image doesn't - load and start - -grub_load_and_start_image only loads an image - it still requires the -caller to start it. This renames it to grub_load_image. - -It's called from 2 places: -- grub_cmd_chainloader when not using the shim protocol. -- grub_secureboot_chainloader_boot if handle_image returns an error. -In this case, the image is loaded and then nothing else happens which -seems strange. I assume the intention is that it falls back to LoadImage -and StartImage if handle_image fails, so I've made it do that. - -Signed-off-by: Chris Coulson -(cherry picked from commit b4d70820a65c00561045856b7b8355461a9545f6) -(cherry picked from commit 05b16a6be50b1910609740a66b561276fa490538) ---- - grub-core/loader/efi/chainloader.c | 16 +++++++++++++--- - 1 file changed, 13 insertions(+), 3 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 3af6b12292..39158e679e 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -841,7 +841,7 @@ grub_secureboot_chainloader_unload (void) - } - - static grub_err_t --grub_load_and_start_image(void *boot_image) -+grub_load_image(void *boot_image) - { - grub_efi_boot_services_t *b; - grub_efi_status_t status; -@@ -883,13 +883,23 @@ grub_load_and_start_image(void *boot_image) - static grub_err_t - grub_secureboot_chainloader_boot (void) - { -+ grub_efi_boot_services_t *b; - int rc; -+ - rc = handle_image ((void *)(unsigned long)address, fsize); - if (rc == 0) - { -- grub_load_and_start_image((void *)(unsigned long)address); -+ /* We weren't able to attempt to execute the image, so fall back -+ * to LoadImage / StartImage. -+ */ -+ rc = grub_load_image((void *)(unsigned long)address); -+ if (rc == 0) -+ grub_chainloader_boot (); - } - -+ b = grub_efi_system_table->boot_services; -+ efi_call_1 (b->unload_image, image_handle); -+ - grub_loader_unset (); - return grub_errno; - } -@@ -1094,7 +1104,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - } - else if (rc == 0) - { -- grub_load_and_start_image(boot_image); -+ grub_load_image(boot_image); - grub_file_close (file); - grub_device_close (dev); - grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); diff --git a/SOURCES/0232-net-ip-Do-IP-fragment-maths-safely.patch b/SOURCES/0232-net-ip-Do-IP-fragment-maths-safely.patch new file mode 100644 index 0000000..118448d --- /dev/null +++ b/SOURCES/0232-net-ip-Do-IP-fragment-maths-safely.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 20 Dec 2021 19:41:21 +1100 +Subject: [PATCH] net/ip: Do IP fragment maths safely + +This avoids an underflow and subsequent unpleasantness. + +Fixes: CVE-2022-28733 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit eb74e5743ca7e18a5e75c392fe0b21d1549a1936) +--- + grub-core/net/ip.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index ce6bdc75c6..cf74f1f794 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + + struct iphdr { +@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb, + { + rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + + (nb->tail - nb->data)); +- rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); ++ ++ if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t), ++ &rsm->total_len)) ++ { ++ grub_dprintf ("net", "IP reassembly size underflow\n"); ++ return GRUB_ERR_NONE; ++ } ++ + rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len); + if (!rsm->asm_netbuff) + { diff --git a/SOURCES/0233-loader-efi-chainloader-simplify-the-loader-state.patch b/SOURCES/0233-loader-efi-chainloader-simplify-the-loader-state.patch deleted file mode 100644 index 76c3d58..0000000 --- a/SOURCES/0233-loader-efi-chainloader-simplify-the-loader-state.patch +++ /dev/null @@ -1,332 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Fri, 29 Apr 2022 21:13:08 +0100 -Subject: [PATCH] loader/efi/chainloader: simplify the loader state - -When not using the shim lock protocol, the chainloader command retains -the source buffer and device path passed to LoadImage, requiring the -unload hook passed to grub_loader_set to free them. It isn't required -to retain this state though - they aren't required by StartImage or -anything else in the boot hook, so clean them up before -grub_cmd_chainloader finishes. - -This also wraps the loader state when using the shim lock protocol -inside a struct. - -Signed-off-by: Chris Coulson -(cherry picked from commit fa39862933b3be1553a580a3a5c28073257d8046) -(cherry picked from commit 0333343ee99c4e88f062789263c94291c057251b) -[rharwood: double-frees and uninitialized, verifying twice] -Signed-off-by: Robbie Harwood ---- - grub-core/loader/efi/chainloader.c | 160 +++++++++++++++++++++++-------------- - 1 file changed, 102 insertions(+), 58 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 39158e679e..0717ce0478 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -48,38 +48,21 @@ GRUB_MOD_LICENSE ("GPLv3+"); - - static grub_dl_t my_mod; - --static grub_efi_physical_address_t address; --static grub_efi_uintn_t pages; --static grub_ssize_t fsize; --static grub_efi_device_path_t *file_path; - static grub_efi_handle_t image_handle; --static grub_efi_char16_t *cmdline; --static grub_ssize_t cmdline_len; --static grub_efi_handle_t dev_handle; - --static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); -+struct grub_secureboot_chainloader_context { -+ grub_efi_physical_address_t address; -+ grub_efi_uintn_t pages; -+ grub_ssize_t fsize; -+ grub_efi_device_path_t *file_path; -+ grub_efi_char16_t *cmdline; -+ grub_ssize_t cmdline_len; -+ grub_efi_handle_t dev_handle; -+}; -+static struct grub_secureboot_chainloader_context *sb_context; - - static grub_err_t --grub_chainloader_unload (void) --{ -- grub_efi_boot_services_t *b; -- -- b = grub_efi_system_table->boot_services; -- efi_call_1 (b->unload_image, image_handle); -- grub_efi_free_pages (address, pages); -- -- grub_free (file_path); -- grub_free (cmdline); -- cmdline = 0; -- file_path = 0; -- dev_handle = 0; -- -- grub_dl_unref (my_mod); -- return GRUB_ERR_NONE; --} -- --static grub_err_t --grub_chainloader_boot (void) -+grub_start_image (grub_efi_handle_t handle) - { - grub_efi_boot_services_t *b; - grub_efi_status_t status; -@@ -87,7 +70,7 @@ grub_chainloader_boot (void) - grub_efi_char16_t *exit_data = NULL; - - b = grub_efi_system_table->boot_services; -- status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data); -+ status = efi_call_3 (b->start_image, handle, &exit_data_size, &exit_data); - if (status != GRUB_EFI_SUCCESS) - { - if (exit_data) -@@ -111,11 +94,37 @@ grub_chainloader_boot (void) - if (exit_data) - grub_efi_free_pool (exit_data); - -- grub_loader_unset (); -- - return grub_errno; - } - -+static grub_err_t -+grub_chainloader_unload (void) -+{ -+ grub_efi_loaded_image_t *loaded_image; -+ grub_efi_boot_services_t *b; -+ -+ loaded_image = grub_efi_get_loaded_image (image_handle); -+ if (loaded_image != NULL) -+ grub_free (loaded_image->load_options); -+ -+ b = grub_efi_system_table->boot_services; -+ efi_call_1 (b->unload_image, image_handle); -+ -+ grub_dl_unref (my_mod); -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_chainloader_boot (void) -+{ -+ grub_err_t err; -+ -+ err = grub_start_image (image_handle); -+ -+ grub_loader_unset (); -+ return err; -+} -+ - static grub_err_t - copy_file_path (grub_efi_file_path_device_path_t *fp, - const char *str, grub_efi_uint16_t len) -@@ -150,7 +159,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) - char *dir_start; - char *dir_end; - grub_size_t size; -- grub_efi_device_path_t *d; -+ grub_efi_device_path_t *d, *file_path; - - dir_start = grub_strchr (filename, ')'); - if (! dir_start) -@@ -526,10 +535,12 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp) - } - - static grub_efi_boolean_t --handle_image (void *data, grub_efi_uint32_t datasize) -+handle_image (struct grub_secureboot_chainloader_context *load_context) - { - grub_efi_loaded_image_t *li, li_bak; - grub_efi_status_t efi_status; -+ void *data = (void *)(unsigned long)load_context->address; -+ grub_efi_uint32_t datasize = load_context->fsize; - void *buffer = NULL; - char *buffer_aligned = NULL; - grub_efi_uint32_t i; -@@ -540,6 +551,7 @@ handle_image (void *data, grub_efi_uint32_t datasize) - grub_uint32_t buffer_size; - int found_entry_point = 0; - int rc; -+ grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); - - rc = read_header (data, datasize, &context); - if (rc < 0) -@@ -797,10 +809,10 @@ handle_image (void *data, grub_efi_uint32_t datasize) - grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); - li->image_base = buffer_aligned; - li->image_size = context.image_size; -- li->load_options = cmdline; -- li->load_options_size = cmdline_len; -- li->file_path = grub_efi_get_media_file_path (file_path); -- li->device_handle = dev_handle; -+ li->load_options = load_context->cmdline; -+ li->load_options_size = load_context->cmdline_len; -+ li->file_path = grub_efi_get_media_file_path (load_context->file_path); -+ li->device_handle = load_context->dev_handle; - if (!li->file_path) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); -@@ -829,19 +841,22 @@ error_exit: - static grub_err_t - grub_secureboot_chainloader_unload (void) - { -- grub_efi_free_pages (address, pages); -- grub_free (file_path); -- grub_free (cmdline); -- cmdline = 0; -- file_path = 0; -- dev_handle = 0; -+ grub_efi_free_pages (sb_context->address, sb_context->pages); -+ grub_free (sb_context->file_path); -+ grub_free (sb_context->cmdline); -+ grub_free (sb_context); -+ -+ sb_context = 0; - - grub_dl_unref (my_mod); - return GRUB_ERR_NONE; - } - - static grub_err_t --grub_load_image(void *boot_image) -+grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, -+ grub_efi_uintn_t image_size, grub_efi_handle_t dev_handle, -+ grub_efi_char16_t *cmdline, grub_ssize_t cmdline_len, -+ grub_efi_handle_t *image_handle_out) - { - grub_efi_boot_services_t *b; - grub_efi_status_t status; -@@ -850,7 +865,7 @@ grub_load_image(void *boot_image) - b = grub_efi_system_table->boot_services; - - status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, -- boot_image, fsize, &image_handle); -+ boot_image, image_size, image_handle_out); - if (status != GRUB_EFI_SUCCESS) - { - if (status == GRUB_EFI_OUT_OF_RESOURCES) -@@ -863,7 +878,7 @@ grub_load_image(void *boot_image) - /* LoadImage does not set a device handler when the image is - loaded from memory, so it is necessary to set it explicitly here. - This is a mess. */ -- loaded_image = grub_efi_get_loaded_image (image_handle); -+ loaded_image = grub_efi_get_loaded_image (*image_handle_out); - if (! loaded_image) - { - grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); -@@ -885,20 +900,25 @@ grub_secureboot_chainloader_boot (void) - { - grub_efi_boot_services_t *b; - int rc; -+ grub_efi_handle_t handle = 0; - -- rc = handle_image ((void *)(unsigned long)address, fsize); -+ rc = handle_image (sb_context); - if (rc == 0) - { - /* We weren't able to attempt to execute the image, so fall back - * to LoadImage / StartImage. - */ -- rc = grub_load_image((void *)(unsigned long)address); -+ rc = grub_load_image(sb_context->file_path, -+ (void *)(unsigned long)sb_context->address, -+ sb_context->fsize, sb_context->dev_handle, -+ sb_context->cmdline, sb_context->cmdline_len, -+ &handle); - if (rc == 0) -- grub_chainloader_boot (); -+ grub_start_image (handle); - } - - b = grub_efi_system_table->boot_services; -- efi_call_1 (b->unload_image, image_handle); -+ efi_call_1 (b->unload_image, handle); - - grub_loader_unset (); - return grub_errno; -@@ -913,10 +933,16 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_efi_boot_services_t *b; - grub_device_t dev = 0; - grub_device_t orig_dev = 0; -- grub_efi_device_path_t *dp = 0; -+ grub_efi_device_path_t *dp = 0, *file_path = 0; - char *filename; - void *boot_image = 0; - int rc; -+ grub_efi_physical_address_t address = 0; -+ grub_ssize_t fsize; -+ grub_efi_uintn_t pages = 0; -+ grub_efi_char16_t *cmdline = 0; -+ grub_ssize_t cmdline_len = 0; -+ grub_efi_handle_t dev_handle = 0; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -@@ -924,12 +950,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - - grub_dl_ref (my_mod); - -- /* Initialize some global variables. */ -- address = 0; -- image_handle = 0; -- file_path = 0; -- dev_handle = 0; -- - b = grub_efi_system_table->boot_services; - - if (argc > 1) -@@ -1096,17 +1116,35 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); - if (rc > 0) - { -+ sb_context = grub_malloc (sizeof (*sb_context)); -+ if (sb_context == NULL) -+ goto fail; -+ sb_context->address = address; -+ sb_context->fsize = fsize; -+ sb_context->pages = pages; -+ sb_context->file_path = file_path; -+ sb_context->cmdline = cmdline; -+ sb_context->cmdline_len = cmdline_len; -+ sb_context->dev_handle = dev_handle; -+ - grub_file_close (file); - grub_device_close (dev); -+ - grub_loader_set (grub_secureboot_chainloader_boot, - grub_secureboot_chainloader_unload, 0); - return 0; - } - else if (rc == 0) - { -- grub_load_image(boot_image); -+ grub_load_image(file_path, boot_image, fsize, dev_handle, cmdline, -+ cmdline_len, &image_handle); - grub_file_close (file); - grub_device_close (dev); -+ -+ /* We're finished with the source image buffer and file path now */ -+ efi_call_2 (b->free_pages, address, pages); -+ grub_free (file_path); -+ - grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); - - return 0; -@@ -1134,6 +1172,12 @@ fail: - if (cmdline) - grub_free (cmdline); - -+ if (image_handle != 0) -+ { -+ efi_call_1 (b->unload_image, image_handle); -+ image_handle = 0; -+ } -+ - grub_dl_unref (my_mod); - - return grub_errno; diff --git a/SOURCES/0233-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch b/SOURCES/0233-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch new file mode 100644 index 0000000..19701b6 --- /dev/null +++ b/SOURCES/0233-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 16 Sep 2021 01:29:54 +1000 +Subject: [PATCH] net/dns: Fix double-free addresses on corrupt DNS response + +grub_net_dns_lookup() takes as inputs a pointer to an array of addresses +("addresses") for the given name, and pointer to a number of addresses +("naddresses"). grub_net_dns_lookup() is responsible for allocating +"addresses", and the caller is responsible for freeing it if +"naddresses" > 0. + +The DNS recv_hook will sometimes set and free the addresses array, +for example if the packet is too short: + + if (ptr + 10 >= nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + +Later on the nslookup command code unconditionally frees the "addresses" +array. Normally this is fine: the array is either populated with valid +data or is NULL. But in these sorts of error cases it is neither NULL +nor valid and we get a double-free. + +Only free "addresses" if "naddresses" > 0. + +It looks like the other use of grub_net_dns_lookup() is not affected. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit eb2e69fcf51307757e43f55ee8c9354d1ee42dd1) +--- + grub-core/net/dns.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c +index 906ec7d678..135faac035 100644 +--- a/grub-core/net/dns.c ++++ b/grub-core/net/dns.c +@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)), + grub_net_addr_to_str (&addresses[i], buf); + grub_printf ("%s\n", buf); + } +- grub_free (addresses); + if (naddresses) +- return GRUB_ERR_NONE; ++ { ++ grub_free (addresses); ++ return GRUB_ERR_NONE; ++ } + return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found")); + } + diff --git a/SOURCES/0234-commands-boot-Add-API-to-pass-context-to-loader.patch b/SOURCES/0234-commands-boot-Add-API-to-pass-context-to-loader.patch deleted file mode 100644 index 65aac76..0000000 --- a/SOURCES/0234-commands-boot-Add-API-to-pass-context-to-loader.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Fri, 29 Apr 2022 21:16:02 +0100 -Subject: [PATCH] commands/boot: Add API to pass context to loader - -Loaders rely on global variables for saving context which is consumed -in the boot hook and freed in the unload hook. In the case where a loader -command is executed twice, calling grub_loader_set a second time executes -the unload hook, but in some cases this runs when the loader's global -context has already been updated, resulting in the updated context being -freed and potential use-after-free bugs when the boot hook is subsequently -called. - -This adds a new API (grub_loader_set_ex) which allows a loader to specify -context that is passed to its boot and unload hooks. This is an alternative -to requiring that loaders call grub_loader_unset before mutating their -global context. - -Signed-off-by: Chris Coulson -(cherry picked from commit 4322a64dde7e8fedb58e50b79408667129d45dd3) -(cherry picked from commit 937ad0e2159b6b8cb0d2ce3515da3a8b797c7927) ---- - grub-core/commands/boot.c | 66 +++++++++++++++++++++++++++++++++++++++++------ - include/grub/loader.h | 5 ++++ - 2 files changed, 63 insertions(+), 8 deletions(-) - -diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c -index bbca81e947..53691a62d9 100644 ---- a/grub-core/commands/boot.c -+++ b/grub-core/commands/boot.c -@@ -27,10 +27,20 @@ - - GRUB_MOD_LICENSE ("GPLv3+"); - --static grub_err_t (*grub_loader_boot_func) (void); --static grub_err_t (*grub_loader_unload_func) (void); -+static grub_err_t (*grub_loader_boot_func) (void *); -+static grub_err_t (*grub_loader_unload_func) (void *); -+static void *grub_loader_context; - static int grub_loader_flags; - -+struct grub_simple_loader_hooks -+{ -+ grub_err_t (*boot) (void); -+ grub_err_t (*unload) (void); -+}; -+ -+/* Don't heap allocate this to avoid making grub_loader_set fallible. */ -+static struct grub_simple_loader_hooks simple_loader_hooks; -+ - struct grub_preboot - { - grub_err_t (*preboot_func) (int); -@@ -44,6 +54,29 @@ static int grub_loader_loaded; - static struct grub_preboot *preboots_head = 0, - *preboots_tail = 0; - -+static grub_err_t -+grub_simple_boot_hook (void *context) -+{ -+ struct grub_simple_loader_hooks *hooks; -+ -+ hooks = (struct grub_simple_loader_hooks *) context; -+ return hooks->boot (); -+} -+ -+static grub_err_t -+grub_simple_unload_hook (void *context) -+{ -+ struct grub_simple_loader_hooks *hooks; -+ grub_err_t ret; -+ -+ hooks = (struct grub_simple_loader_hooks *) context; -+ -+ ret = hooks->unload (); -+ grub_memset (hooks, 0, sizeof (*hooks)); -+ -+ return ret; -+} -+ - int - grub_loader_is_loaded (void) - { -@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) - } - - void --grub_loader_set (grub_err_t (*boot) (void), -- grub_err_t (*unload) (void), -- int flags) -+grub_loader_set_ex (grub_err_t (*boot) (void *), -+ grub_err_t (*unload) (void *), -+ void *context, -+ int flags) - { - if (grub_loader_loaded && grub_loader_unload_func) -- grub_loader_unload_func (); -+ grub_loader_unload_func (grub_loader_context); - - grub_loader_boot_func = boot; - grub_loader_unload_func = unload; -+ grub_loader_context = context; - grub_loader_flags = flags; - - grub_loader_loaded = 1; - } - -+void -+grub_loader_set (grub_err_t (*boot) (void), -+ grub_err_t (*unload) (void), -+ int flags) -+{ -+ grub_loader_set_ex (grub_simple_boot_hook, -+ grub_simple_unload_hook, -+ &simple_loader_hooks, -+ flags); -+ -+ simple_loader_hooks.boot = boot; -+ simple_loader_hooks.unload = unload; -+} -+ - void - grub_loader_unset(void) - { - if (grub_loader_loaded && grub_loader_unload_func) -- grub_loader_unload_func (); -+ grub_loader_unload_func (grub_loader_context); - - grub_loader_boot_func = 0; - grub_loader_unload_func = 0; -+ grub_loader_context = 0; - - grub_loader_loaded = 0; - } -@@ -158,7 +208,7 @@ grub_loader_boot (void) - return err; - } - } -- err = (grub_loader_boot_func) (); -+ err = (grub_loader_boot_func) (grub_loader_context); - - for (cur = preboots_tail; cur; cur = cur->prev) - if (! err) -diff --git a/include/grub/loader.h b/include/grub/loader.h -index b208642821..1846fa6c5f 100644 ---- a/include/grub/loader.h -+++ b/include/grub/loader.h -@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), - grub_err_t (*unload) (void), - int flags); - -+void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *), -+ grub_err_t (*unload) (void *), -+ void *context, -+ int flags); -+ - /* Unset current loader, if any. */ - void EXPORT_FUNC (grub_loader_unset) (void); - diff --git a/SOURCES/0234-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch b/SOURCES/0234-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch new file mode 100644 index 0000000..ab0d471 --- /dev/null +++ b/SOURCES/0234-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 20 Dec 2021 21:55:43 +1100 +Subject: [PATCH] net/dns: Don't read past the end of the string we're checking + against + +I don't really understand what's going on here but fuzzing found +a bug where we read past the end of check_with. That's a C string, +so use grub_strlen() to make sure we don't overread it. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 6a97b3f4b1d5173aa516edc6dedbc63de7306d21) +--- + grub-core/net/dns.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c +index 135faac035..17961a9f18 100644 +--- a/grub-core/net/dns.c ++++ b/grub-core/net/dns.c +@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + int *length, char *set) + { + const char *readable_ptr = check_with; ++ int readable_len; + const grub_uint8_t *ptr; + char *optr = set; + int bytes_processed = 0; + if (length) + *length = 0; ++ ++ if (readable_ptr != NULL) ++ readable_len = grub_strlen (readable_ptr); ++ else ++ readable_len = 0; ++ + for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; ) + { + /* End marker. */ +@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]); + continue; + } +- if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) ++ if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)) + return 0; + if (grub_memchr (ptr + 1, 0, *ptr) + || grub_memchr (ptr + 1, '.', *ptr)) + return 0; + if (readable_ptr) +- readable_ptr += *ptr; ++ { ++ readable_ptr += *ptr; ++ readable_len -= *ptr; ++ } + if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0) + return 0; + bytes_processed += *ptr + 1; +@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + if (optr) + *optr++ = '.'; + if (readable_ptr && *readable_ptr) +- readable_ptr++; ++ { ++ readable_ptr++; ++ readable_len--; ++ } + ptr += *ptr + 1; + } + return 0; diff --git a/SOURCES/0235-loader-efi-chainloader-Use-grub_loader_set_ex.patch b/SOURCES/0235-loader-efi-chainloader-Use-grub_loader_set_ex.patch deleted file mode 100644 index 6a41992..0000000 --- a/SOURCES/0235-loader-efi-chainloader-Use-grub_loader_set_ex.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Fri, 29 Apr 2022 21:30:56 +0100 -Subject: [PATCH] loader/efi/chainloader: Use grub_loader_set_ex - -This ports the EFI chainloader to use grub_loader_set_ex in order to fix -a use-after-free bug that occurs when grub_cmd_chainloader is executed -more than once before a boot attempt is performed. - -Signed-off-by: Chris Coulson -(cherry picked from commit 4b7f0402b7cb0f67a93be736f2b75b818d7f44c9) -(cherry picked from commit fc1a79bf0e0bc019362ace46d908a92b48dcd55b) -[rharwood: context sludge from previous commit] -Signed-off-by: Robbie Harwood ---- - grub-core/loader/efi/chainloader.c | 38 ++++++++++++++++++++++---------------- - 1 file changed, 22 insertions(+), 16 deletions(-) - -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 0717ce0478..8ef508beca 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -48,8 +48,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); - - static grub_dl_t my_mod; - --static grub_efi_handle_t image_handle; -- - struct grub_secureboot_chainloader_context { - grub_efi_physical_address_t address; - grub_efi_uintn_t pages; -@@ -59,7 +57,6 @@ struct grub_secureboot_chainloader_context { - grub_ssize_t cmdline_len; - grub_efi_handle_t dev_handle; - }; --static struct grub_secureboot_chainloader_context *sb_context; - - static grub_err_t - grub_start_image (grub_efi_handle_t handle) -@@ -98,11 +95,14 @@ grub_start_image (grub_efi_handle_t handle) - } - - static grub_err_t --grub_chainloader_unload (void) -+grub_chainloader_unload (void *context) - { -+ grub_efi_handle_t image_handle; - grub_efi_loaded_image_t *loaded_image; - grub_efi_boot_services_t *b; - -+ image_handle = (grub_efi_handle_t) context; -+ - loaded_image = grub_efi_get_loaded_image (image_handle); - if (loaded_image != NULL) - grub_free (loaded_image->load_options); -@@ -115,10 +115,12 @@ grub_chainloader_unload (void) - } - - static grub_err_t --grub_chainloader_boot (void) -+grub_chainloader_boot (void *context) - { -+ grub_efi_handle_t image_handle; - grub_err_t err; - -+ image_handle = (grub_efi_handle_t) context; - err = grub_start_image (image_handle); - - grub_loader_unset (); -@@ -839,15 +841,17 @@ error_exit: - } - - static grub_err_t --grub_secureboot_chainloader_unload (void) -+grub_secureboot_chainloader_unload (void *context) - { -+ struct grub_secureboot_chainloader_context *sb_context; -+ -+ sb_context = (struct grub_secureboot_chainloader_context *) context; -+ - grub_efi_free_pages (sb_context->address, sb_context->pages); - grub_free (sb_context->file_path); - grub_free (sb_context->cmdline); - grub_free (sb_context); - -- sb_context = 0; -- - grub_dl_unref (my_mod); - return GRUB_ERR_NONE; - } -@@ -896,12 +900,15 @@ grub_load_image(grub_efi_device_path_t *file_path, void *boot_image, - } - - static grub_err_t --grub_secureboot_chainloader_boot (void) -+grub_secureboot_chainloader_boot (void *context) - { -+ struct grub_secureboot_chainloader_context *sb_context; - grub_efi_boot_services_t *b; - int rc; - grub_efi_handle_t handle = 0; - -+ sb_context = (struct grub_secureboot_chainloader_context *) context; -+ - rc = handle_image (sb_context); - if (rc == 0) - { -@@ -943,6 +950,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_efi_char16_t *cmdline = 0; - grub_ssize_t cmdline_len = 0; - grub_efi_handle_t dev_handle = 0; -+ grub_efi_handle_t image_handle = 0; -+ struct grub_secureboot_chainloader_context *sb_context = 0; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -@@ -1130,8 +1139,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - grub_file_close (file); - grub_device_close (dev); - -- grub_loader_set (grub_secureboot_chainloader_boot, -- grub_secureboot_chainloader_unload, 0); -+ grub_loader_set_ex (grub_secureboot_chainloader_boot, -+ grub_secureboot_chainloader_unload, sb_context, 0); - return 0; - } - else if (rc == 0) -@@ -1145,7 +1154,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - efi_call_2 (b->free_pages, address, pages); - grub_free (file_path); - -- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); -+ grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0); - - return 0; - } -@@ -1173,10 +1182,7 @@ fail: - grub_free (cmdline); - - if (image_handle != 0) -- { -- efi_call_1 (b->unload_image, image_handle); -- image_handle = 0; -- } -+ efi_call_1 (b->unload_image, image_handle); - - grub_dl_unref (my_mod); - diff --git a/SOURCES/0235-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch b/SOURCES/0235-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch new file mode 100644 index 0000000..3ff7b6b --- /dev/null +++ b/SOURCES/0235-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch @@ -0,0 +1,112 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 20 Sep 2021 01:12:24 +1000 +Subject: [PATCH] net/tftp: Prevent a UAF and double-free from a failed seek + +A malicious tftp server can cause UAFs and a double free. + +An attempt to read from a network file is handled by grub_net_fs_read(). If +the read is at an offset other than the current offset, grub_net_seek_real() +is invoked. + +In grub_net_seek_real(), if a backwards seek cannot be satisfied from the +currently received packets, and the underlying transport does not provide +a seek method, then grub_net_seek_real() will close and reopen the network +protocol layer. + +For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t +file->data. The file->data pointer is not nulled out after the free. + +If the ->open() call fails, the file->data will not be reallocated and will +continue point to a freed memory block. This could happen from a server +refusing to send the requisite ack to the new tftp request, for example. + +The seek and the read will then fail, but the grub_file continues to exist: +the failed seek does not necessarily cause the entire file to be thrown +away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc., +a read failure is interpreted as a decompressor passing on the file, not as +an invalidation of the entire grub_file_t structure). + +This means subsequent attempts to read or seek the file will use the old +file->data after free. Eventually, the file will be close()d again and +file->data will be freed again. + +Mark a net_fs file that doesn't reopen as broken. Do not permit read() or +close() on a broken file (seek is not exposed directly to the file API - +it is only called as part of read, so this blocks seeks as well). + +As an additional defence, null out the ->data pointer if tftp_open() fails. +That would have lead to a simple null pointer dereference rather than +a mess of UAFs. + +This may affect other protocols, I haven't checked. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit dada1dda695439bb55b2848dddc2d89843552f81) +--- + grub-core/net/net.c | 11 +++++++++-- + grub-core/net/tftp.c | 1 + + include/grub/net.h | 1 + + 3 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 55aed92722..1001c611d1 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1625,7 +1625,8 @@ grub_net_fs_close (grub_file_t file) + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } +- file->device->net->protocol->close (file); ++ if (!file->device->net->broken) ++ file->device->net->protocol->close (file); + grub_free (file->device->net->name); + return GRUB_ERR_NONE; + } +@@ -1847,7 +1848,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) + file->device->net->stall = 0; + err = file->device->net->protocol->open (file, file->device->net->name); + if (err) +- return err; ++ { ++ file->device->net->broken = 1; ++ return err; ++ } + grub_net_fs_read_real (file, NULL, offset); + return grub_errno; + } +@@ -1856,6 +1860,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) + static grub_ssize_t + grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) + { ++ if (file->device->net->broken) ++ return -1; ++ + if (file->offset != file->device->net->offset) + { + grub_err_t err; +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index d54b13f09f..788ad1dc44 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -408,6 +408,7 @@ tftp_open (struct grub_file *file, const char *filename) + { + grub_net_udp_close (data->sock); + grub_free (data); ++ file->data = NULL; + return grub_errno; + } + +diff --git a/include/grub/net.h b/include/grub/net.h +index 42af7de250..9e4898cc6b 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -280,6 +280,7 @@ typedef struct grub_net + grub_fs_t fs; + int eof; + int stall; ++ int broken; + } *grub_net_t; + + extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); diff --git a/SOURCES/0236-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch b/SOURCES/0236-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch deleted file mode 100644 index 4be2008..0000000 --- a/SOURCES/0236-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Mon, 2 May 2022 14:39:31 +0200 -Subject: [PATCH] loader/i386/efi/linux: Avoid a use-after-free in the linuxefi - loader - -In some error paths in grub_cmd_linux, the pointer to lh may be -dereferenced after the buffer it points to has been freed. There aren't -any security implications from this because nothing else uses the -allocator after the buffer is freed and before the pointer is -dereferenced, but fix it anyway. - -Signed-off-by: Chris Coulson -(cherry picked from commit 8224f5a71af94bec8697de17e7e579792db9f9e2) -(cherry picked from commit 4744b62e20d07674017213ac54d7442d679f9d1a) ---- - grub-core/loader/i386/efi/linux.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 3cf0f9b330..08c9fe6b0e 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -478,9 +478,6 @@ fail: - if (file) - grub_file_close (file); - -- if (kernel) -- grub_free (kernel); -- - if (grub_errno != GRUB_ERR_NONE) - { - grub_dl_unref (my_mod); -@@ -496,6 +493,8 @@ fail: - kernel_free (params, sizeof(*params)); - } - -+ grub_free (kernel); -+ - return grub_errno; - } - diff --git a/SOURCES/0236-net-tftp-Avoid-a-trivial-UAF.patch b/SOURCES/0236-net-tftp-Avoid-a-trivial-UAF.patch new file mode 100644 index 0000000..4ec3b56 --- /dev/null +++ b/SOURCES/0236-net-tftp-Avoid-a-trivial-UAF.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 18 Jan 2022 14:29:20 +1100 +Subject: [PATCH] net/tftp: Avoid a trivial UAF + +Under tftp errors, we print a tftp error message from the tftp header. +However, the tftph pointer is a pointer inside nb, the netbuff. Previously, +we were freeing the nb and then dereferencing it. Don't do that, use it +and then free it later. + +This isn't really _bad_ per se, especially as we're single-threaded, but +it trips up fuzzers. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 956f4329cec23e4375182030ca9b2be631a61ba5) +--- + grub-core/net/tftp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 788ad1dc44..a95766dcbd 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), + return GRUB_ERR_NONE; + case TFTP_ERROR: + data->have_oack = 1; +- grub_netbuff_free (nb); + grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg); + grub_error_save (&data->save_err); ++ grub_netbuff_free (nb); + return GRUB_ERR_NONE; + default: + grub_netbuff_free (nb); diff --git a/SOURCES/0237-loader-i386-efi-linux-Use-grub_loader_set_ex.patch b/SOURCES/0237-loader-i386-efi-linux-Use-grub_loader_set_ex.patch deleted file mode 100644 index 9f5c491..0000000 --- a/SOURCES/0237-loader-i386-efi-linux-Use-grub_loader_set_ex.patch +++ /dev/null @@ -1,298 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Mon, 2 May 2022 17:04:23 +0200 -Subject: [PATCH] loader/i386/efi/linux: Use grub_loader_set_ex - -This ports the linuxefi loader to use grub_loader_set_ex in order to fix -a use-after-fre bug that occurs when grub_cmd_linux is executed more than -once before a boot attempt is performed. - -This is more complicated than for the chainloader command, as the initrd -command needs access to the loader state. To solve this, the linuxefi -module registers a dummy initrd command at startup that returns an error. -The linuxefi command then registers a proper initrd command with a higher -priority that is passed the loader state. - -Signed-off-by: Chris Coulson -(cherry picked from commit 7cf736436b4c934df5ddfa6f44b46a7e07d99fdc) -[rharwood/pjones: set kernel_size in context] -(cherry picked from commit 9c056391f7a36ea480de9a759c12e55a90f2040a) -[rharwood: verifying twice] -Signed-off-by: Robbie Harwood ---- - grub-core/loader/i386/efi/linux.c | 146 +++++++++++++++++++++++--------------- - 1 file changed, 87 insertions(+), 59 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 08c9fe6b0e..9e25e51ccf 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -35,13 +35,19 @@ - GRUB_MOD_LICENSE ("GPLv3+"); - - static grub_dl_t my_mod; --static int loaded; --static void *kernel_mem; --static grub_uint64_t kernel_size; --static void *initrd_mem; --static grub_uint32_t handover_offset; --struct linux_kernel_params *params; --static char *linux_cmdline; -+ -+static grub_command_t cmd_linux, cmd_initrd; -+static grub_command_t cmd_linuxefi, cmd_initrdefi; -+ -+struct grub_linuxefi_context { -+ void *kernel_mem; -+ grub_uint64_t kernel_size; -+ grub_uint32_t handover_offset; -+ struct linux_kernel_params *params; -+ char *cmdline; -+ -+ void *initrd_mem; -+}; - - #define MIN(a, b) \ - ({ typeof (a) _a = (a); \ -@@ -124,25 +130,32 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) - } - - static grub_err_t --grub_linuxefi_boot (void) -+grub_linuxefi_boot (void *data) - { -+ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; -+ - asm volatile ("cli"); - -- return grub_efi_linux_boot ((char *)kernel_mem, -- handover_offset, -- params); -+ return grub_efi_linux_boot ((char *)context->kernel_mem, -+ context->handover_offset, -+ context->params); - } - - static grub_err_t --grub_linuxefi_unload (void) -+grub_linuxefi_unload (void *data) - { -+ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data; -+ struct linux_kernel_params *params = context->params; -+ - grub_dl_unref (my_mod); -- loaded = 0; - -- kernel_free(initrd_mem, params->ramdisk_size); -- kernel_free(linux_cmdline, params->cmdline_size + 1); -- kernel_free(kernel_mem, kernel_size); -- kernel_free(params, sizeof(*params)); -+ kernel_free (context->initrd_mem, params->ramdisk_size); -+ kernel_free (context->cmdline, params->cmdline_size + 1); -+ kernel_free (context->kernel_mem, context->kernel_size); -+ kernel_free (params, sizeof(*params)); -+ cmd_initrd->data = 0; -+ cmd_initrdefi->data = 0; -+ grub_free (context); - - return GRUB_ERR_NONE; - } -@@ -189,13 +202,14 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) - #define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull)) - - static grub_err_t --grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), -- int argc, char *argv[]) -+grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - { - grub_file_t *files = 0; - int i, nfiles = 0; - grub_size_t size = 0; - grub_uint8_t *ptr; -+ struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; -+ struct linux_kernel_params *params; - - if (argc == 0) - { -@@ -203,12 +217,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -- if (!loaded) -+ if (!context) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); - goto fail; - } - -+ params = context->params; -+ - files = grub_calloc (argc, sizeof (files[0])); - if (!files) - goto fail; -@@ -226,19 +242,19 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - } - } - -- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -- if (initrd_mem == NULL) -+ context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -+ if (context->initrd_mem == NULL) - goto fail; -- grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); -+ grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); - - params->ramdisk_size = LOW_U32(size); -- params->ramdisk_image = LOW_U32(initrd_mem); -+ params->ramdisk_image = LOW_U32(context->initrd_mem); - #if defined(__x86_64__) - params->ext_ramdisk_size = HIGH_U32(size); -- params->ext_ramdisk_image = HIGH_U32(initrd_mem); -+ params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); - #endif - -- ptr = initrd_mem; -+ ptr = context->initrd_mem; - - for (i = 0; i < nfiles; i++) - { -@@ -262,8 +278,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - grub_file_close (files[i]); - grub_free (files); - -- if (initrd_mem && grub_errno) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, -+ if (context->initrd_mem && grub_errno) -+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, - BYTES_TO_PAGES(size)); - - return grub_errno; -@@ -279,6 +295,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - void *kernel = NULL; - int setup_header_end_offset; - int rc; -+ void *kernel_mem = 0; -+ grub_uint64_t kernel_size = 0; -+ grub_uint32_t handover_offset; -+ struct linux_kernel_params *params = 0; -+ char *cmdline = 0; -+ struct grub_linuxefi_context *context = 0; - - grub_dl_ref (my_mod); - -@@ -403,27 +425,27 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "new lh is at %p\n", lh); - - grub_dprintf ("linux", "setting up cmdline\n"); -- linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); -- if (!linux_cmdline) -+ cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); -+ if (!cmdline) - goto fail; -- grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline); -+ grub_dprintf ("linux", "cmdline = %p\n", cmdline); - -- grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); -+ grub_memcpy (cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, -- linux_cmdline + sizeof (LINUX_IMAGE) - 1, -+ cmdline + sizeof (LINUX_IMAGE) - 1, - lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1), - GRUB_VERIFY_KERNEL_CMDLINE); - -- grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline); -+ grub_dprintf ("linux", "cmdline:%s\n", cmdline); - grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n", -- LOW_U32(linux_cmdline)); -- lh->cmd_line_ptr = LOW_U32(linux_cmdline); -+ LOW_U32(cmdline)); -+ lh->cmd_line_ptr = LOW_U32(cmdline); - #if defined(__x86_64__) -- if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull) -+ if ((grub_efi_uintn_t)cmdline > 0xffffffffull) - { - grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n", -- HIGH_U32(linux_cmdline)); -- params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline); -+ HIGH_U32(cmdline)); -+ params->ext_cmd_line_ptr = HIGH_U32(cmdline); - } - #endif - -@@ -448,16 +470,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -- kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel")); -+ kernel_size = lh->init_size; -+ kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) - goto fail; - grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem); - -- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); -- -- loaded = 1; -- - grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n", - LOW_U32(kernel_mem)); - lh->code32_start = LOW_U32(kernel_mem); -@@ -474,33 +493,42 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n", - params->ext_loader_type, params->ext_loader_ver); - -+ context = grub_zalloc (sizeof (*context)); -+ if (!context) -+ goto fail; -+ context->kernel_mem = kernel_mem; -+ context->kernel_size = kernel_size; -+ context->handover_offset = handover_offset; -+ context->params = params; -+ context->cmdline = cmdline; -+ -+ grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); -+ -+ cmd_initrd->data = context; -+ cmd_initrdefi->data = context; -+ -+ grub_file_close (file); -+ grub_free (kernel); -+ return 0; -+ - fail: - if (file) - grub_file_close (file); - -- if (grub_errno != GRUB_ERR_NONE) -- { -- grub_dl_unref (my_mod); -- loaded = 0; -- } -+ grub_dl_unref (my_mod); - -- if (!loaded) -- { -- if (lh) -- kernel_free (linux_cmdline, lh->cmdline_size + 1); -+ if (lh) -+ kernel_free (cmdline, lh->cmdline_size + 1); - -- kernel_free (kernel_mem, kernel_size); -- kernel_free (params, sizeof(*params)); -- } -+ kernel_free (kernel_mem, kernel_size); -+ kernel_free (params, sizeof(*params)); - -+ grub_free (context); - grub_free (kernel); - - return grub_errno; - } - --static grub_command_t cmd_linux, cmd_initrd; --static grub_command_t cmd_linuxefi, cmd_initrdefi; -- - GRUB_MOD_INIT(linux) - { - cmd_linux = diff --git a/SOURCES/0237-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch b/SOURCES/0237-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch new file mode 100644 index 0000000..186f0c3 --- /dev/null +++ b/SOURCES/0237-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 1 Mar 2022 23:14:15 +1100 +Subject: [PATCH] net/http: Do not tear down socket if it's already been torn + down + +It's possible for data->sock to get torn down in tcp error handling. +If we unconditionally tear it down again we will end up doing writes +to an offset of the NULL pointer when we go to tear it down again. + +Detect if it has been torn down and don't do it again. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit ec233d3ecf995293304de443579aab5c46c49e85) +--- + grub-core/net/http.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 7f878b5615..19cb8768e3 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -427,7 +427,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + return err; + } + +- for (i = 0; !data->headers_recv && i < 100; i++) ++ for (i = 0; data->sock && !data->headers_recv && i < 100; i++) + { + grub_net_tcp_retransmit (); + grub_net_poll_cards (300, &data->headers_recv); +@@ -435,7 +435,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + + if (!data->headers_recv) + { +- grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); ++ if (data->sock) ++ grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + if (data->err) + { + char *str = data->errmsg; diff --git a/SOURCES/0238-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch b/SOURCES/0238-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch deleted file mode 100644 index fe329e6..0000000 --- a/SOURCES/0238-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Coulson -Date: Tue, 3 May 2022 09:47:35 +0200 -Subject: [PATCH] loader/i386/efi/linux: Fix a memory leak in the initrd - command - -Subsequent invocations of the initrd command result in the previous -initrd being leaked, so fix that. - -Signed-off-by: Chris Coulson -(cherry picked from commit d98af31ce1e31bb22163960d53f5eb28c66582a0) -(cherry picked from commit 62234d6a00e6d1dd8e017ff161d359feb5234082) ---- - grub-core/loader/i386/efi/linux.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 9e25e51ccf..d24553a79d 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -210,6 +210,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - grub_uint8_t *ptr; - struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data; - struct linux_kernel_params *params; -+ void *initrd_mem = 0; - - if (argc == 0) - { -@@ -242,19 +243,19 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - } - -- context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -- if (context->initrd_mem == NULL) -+ initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -+ if (initrd_mem == NULL) - goto fail; -- grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem); -+ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); - - params->ramdisk_size = LOW_U32(size); -- params->ramdisk_image = LOW_U32(context->initrd_mem); -+ params->ramdisk_image = LOW_U32(initrd_mem); - #if defined(__x86_64__) - params->ext_ramdisk_size = HIGH_U32(size); -- params->ext_ramdisk_image = HIGH_U32(context->initrd_mem); -+ params->ext_ramdisk_image = HIGH_U32(initrd_mem); - #endif - -- ptr = context->initrd_mem; -+ ptr = initrd_mem; - - for (i = 0; i < nfiles; i++) - { -@@ -271,6 +272,9 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } - -+ kernel_free(context->initrd_mem, params->ramdisk_size); -+ -+ context->initrd_mem = initrd_mem; - params->ramdisk_size = size; - - fail: -@@ -278,9 +282,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - grub_file_close (files[i]); - grub_free (files); - -- if (context->initrd_mem && grub_errno) -- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem, -- BYTES_TO_PAGES(size)); -+ if (initrd_mem && grub_errno) -+ kernel_free (initrd_mem, size); - - return grub_errno; - } diff --git a/SOURCES/0238-net-http-Fix-OOB-write-for-split-http-headers.patch b/SOURCES/0238-net-http-Fix-OOB-write-for-split-http-headers.patch new file mode 100644 index 0000000..f22960b --- /dev/null +++ b/SOURCES/0238-net-http-Fix-OOB-write-for-split-http-headers.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 8 Mar 2022 18:17:03 +1100 +Subject: [PATCH] net/http: Fix OOB write for split http headers + +GRUB has special code for handling an http header that is split +across two packets. + +The code tracks the end of line by looking for a "\n" byte. The +code for split headers has always advanced the pointer just past the +end of the line, whereas the code that handles unsplit headers does +not advance the pointer. This extra advance causes the length to be +one greater, which breaks an assumption in parse_line(), leading to +it writing a NUL byte one byte past the end of the buffer where we +reconstruct the line from the two packets. + +It's conceivable that an attacker controlled set of packets could +cause this to zero out the first byte of the "next" pointer of the +grub_mm_region structure following the current_line buffer. + +Do not advance the pointer in the split header case. + +Fixes: CVE-2022-28734 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit e9fb459638811c12b0989dbf64e3e124974ef617) +--- + grub-core/net/http.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 19cb8768e3..58546739a2 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -193,9 +193,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), + int have_line = 1; + char *t; + ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); +- if (ptr) +- ptr++; +- else ++ if (ptr == NULL) + { + have_line = 0; + ptr = (char *) nb->tail; diff --git a/SOURCES/0239-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch b/SOURCES/0239-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch deleted file mode 100644 index 716d1f1..0000000 --- a/SOURCES/0239-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Julian Andres Klode -Date: Thu, 2 Dec 2021 15:03:53 +0100 -Subject: [PATCH] kern/efi/sb: Reject non-kernel files in the shim_lock - verifier - -We must not allow other verifiers to pass things like the GRUB modules. -Instead of maintaining a blocklist, maintain an allowlist of things -that we do not care about. - -This allowlist really should be made reusable, and shared by the -lockdown verifier, but this is the minimal patch addressing -security concerns where the TPM verifier was able to mark modules -as verified (or the OpenPGP verifier for that matter), when it -should not do so on shim-powered secure boot systems. - -Fixes: CVE-2022-28735 - -Signed-off-by: Julian Andres Klode -Reviewed-by: Daniel Kiper -(cherry picked from commit fa61ad69861c1cb3f68bf853d78fae7fd93986a0) -(cherry picked from commit f418191e01b38a635319a26925cf345523d4440c) ---- - grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++--- - include/grub/verify.h | 1 + - 2 files changed, 37 insertions(+), 3 deletions(-) - -diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c -index c52ec6226a..89c4bb3fd1 100644 ---- a/grub-core/kern/efi/sb.c -+++ b/grub-core/kern/efi/sb.c -@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), - void **context __attribute__ ((unused)), - enum grub_verify_flags *flags) - { -- *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; -+ *flags = GRUB_VERIFY_FLAGS_NONE; - - switch (type & GRUB_FILE_TYPE_MASK) - { -+ /* Files we check. */ - case GRUB_FILE_TYPE_LINUX_KERNEL: - case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: - case GRUB_FILE_TYPE_BSD_KERNEL: -@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), - case GRUB_FILE_TYPE_PLAN9_KERNEL: - case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: - *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; -+ return GRUB_ERR_NONE; - -- /* Fall through. */ -+ /* Files that do not affect secureboot state. */ -+ case GRUB_FILE_TYPE_NONE: -+ case GRUB_FILE_TYPE_LOOPBACK: -+ case GRUB_FILE_TYPE_LINUX_INITRD: -+ case GRUB_FILE_TYPE_OPENBSD_RAMDISK: -+ case GRUB_FILE_TYPE_XNU_RAMDISK: -+ case GRUB_FILE_TYPE_SIGNATURE: -+ case GRUB_FILE_TYPE_PUBLIC_KEY: -+ case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST: -+ case GRUB_FILE_TYPE_PRINT_BLOCKLIST: -+ case GRUB_FILE_TYPE_TESTLOAD: -+ case GRUB_FILE_TYPE_GET_SIZE: -+ case GRUB_FILE_TYPE_FONT: -+ case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: -+ case GRUB_FILE_TYPE_CAT: -+ case GRUB_FILE_TYPE_HEXCAT: -+ case GRUB_FILE_TYPE_CMP: -+ case GRUB_FILE_TYPE_HASHLIST: -+ case GRUB_FILE_TYPE_TO_HASH: -+ case GRUB_FILE_TYPE_KEYBOARD_LAYOUT: -+ case GRUB_FILE_TYPE_PIXMAP: -+ case GRUB_FILE_TYPE_GRUB_MODULE_LIST: -+ case GRUB_FILE_TYPE_CONFIG: -+ case GRUB_FILE_TYPE_THEME: -+ case GRUB_FILE_TYPE_GETTEXT_CATALOG: -+ case GRUB_FILE_TYPE_FS_SEARCH: -+ case GRUB_FILE_TYPE_LOADENV: -+ case GRUB_FILE_TYPE_SAVEENV: -+ case GRUB_FILE_TYPE_VERIFY_SIGNATURE: -+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; -+ return GRUB_ERR_NONE; - -+ /* Other files. */ - default: -- return GRUB_ERR_NONE; -+ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy")); - } - } - -diff --git a/include/grub/verify.h b/include/grub/verify.h -index cd129c398f..672ae16924 100644 ---- a/include/grub/verify.h -+++ b/include/grub/verify.h -@@ -24,6 +24,7 @@ - - enum grub_verify_flags - { -+ GRUB_VERIFY_FLAGS_NONE = 0, - GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1, - GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2, - /* Defer verification to another authority. */ diff --git a/SOURCES/0239-net-http-Error-out-on-headers-with-LF-without-CR.patch b/SOURCES/0239-net-http-Error-out-on-headers-with-LF-without-CR.patch new file mode 100644 index 0000000..b73c169 --- /dev/null +++ b/SOURCES/0239-net-http-Error-out-on-headers-with-LF-without-CR.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 8 Mar 2022 19:04:40 +1100 +Subject: [PATCH] net/http: Error out on headers with LF without CR + +In a similar vein to the previous patch, parse_line() would write +a NUL byte past the end of the buffer if there was an HTTP header +with a LF rather than a CRLF. + +RFC-2616 says: + + Many HTTP/1.1 header field values consist of words separated by LWS + or special characters. These special characters MUST be in a quoted + string to be used within a parameter value (as defined in section 3.6). + +We don't support quoted sections or continuation lines, etc. + +If we see an LF that's not part of a CRLF, bail out. + +Fixes: CVE-2022-28734 + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit d232ad41ac4979a9de4d746e5fdff9caf0e303de) +--- + grub-core/net/http.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 58546739a2..57d2721719 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -69,7 +69,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) + char *end = ptr + len; + while (end > ptr && *(end - 1) == '\r') + end--; ++ ++ /* LF without CR. */ ++ if (end == ptr + len) ++ { ++ data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR")); ++ return GRUB_ERR_NONE; ++ } + *end = 0; ++ + /* Trailing CRLF. */ + if (data->in_chunk_len == 1) + { diff --git a/SOURCES/0240-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch b/SOURCES/0240-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch new file mode 100644 index 0000000..79df1c2 --- /dev/null +++ b/SOURCES/0240-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +Date: Wed, 6 Apr 2022 18:03:37 +0530 +Subject: [PATCH] fs/f2fs: Do not read past the end of nat journal entries + +A corrupt f2fs file system could specify a nat journal entry count +that is beyond the maximum NAT_JOURNAL_ENTRIES. + +Check if the specified nat journal entry count before accessing the +array, and throw an error if it is too large. + +Signed-off-by: Sudhakar Kuppusamy +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit a3988cb3f0a108dd67ac127a79a4c8479d23334e) +--- + grub-core/fs/f2fs.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c +index 8a9992ca9e..63702214b0 100644 +--- a/grub-core/fs/f2fs.c ++++ b/grub-core/fs/f2fs.c +@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data) + return err; + } + +-static grub_uint32_t +-get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid) ++static grub_err_t ++get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid, ++ grub_uint32_t *blkaddr) + { + grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats); +- grub_uint32_t blkaddr = 0; + grub_uint16_t i; + ++ if (n >= NAT_JOURNAL_ENTRIES) ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid number of nat journal entries"); ++ + for (i = 0; i < n; i++) + { + if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid) + { +- blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); ++ *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); + break; + } + } + +- return blkaddr; ++ return GRUB_ERR_NONE; + } + + static grub_uint32_t +@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) + { + struct grub_f2fs_nat_block *nat_block; + grub_uint32_t seg_off, block_off, entry_off, block_addr; +- grub_uint32_t blkaddr; ++ grub_uint32_t blkaddr = 0; + grub_err_t err; + +- blkaddr = get_blkaddr_from_nat_journal (data, nid); ++ err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); ++ if (err != GRUB_ERR_NONE) ++ return 0; ++ + if (blkaddr) + return blkaddr; + diff --git a/SOURCES/0240-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch b/SOURCES/0240-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch deleted file mode 100644 index f75512c..0000000 --- a/SOURCES/0240-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Fri, 25 Jun 2021 02:19:05 +1000 -Subject: [PATCH] kern/file: Do not leak device_name on error in - grub_file_open() - -If we have an error in grub_file_open() before we free device_name, we -will leak it. - -Free device_name in the error path and null out the pointer in the good -path once we free it there. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 1499a5068839fa37cb77ecef4b5bdacbd1ed12ea) -(cherry picked from commit 2ec50b289d8b24922433439533113087f111f110) ---- - grub-core/kern/file.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c -index e19aea3e51..ed69fc0f0f 100644 ---- a/grub-core/kern/file.c -+++ b/grub-core/kern/file.c -@@ -81,6 +81,7 @@ grub_file_open (const char *name, enum grub_file_type type) - - device = grub_device_open (device_name); - grub_free (device_name); -+ device_name = NULL; - if (! device) - goto fail; - -@@ -135,6 +136,7 @@ grub_file_open (const char *name, enum grub_file_type type) - return file; - - fail: -+ grub_free (device_name); - if (device) - grub_device_close (device); - diff --git a/SOURCES/0241-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch b/SOURCES/0241-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch new file mode 100644 index 0000000..855e882 --- /dev/null +++ b/SOURCES/0241-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +Date: Wed, 6 Apr 2022 18:49:09 +0530 +Subject: [PATCH] fs/f2fs: Do not read past the end of nat bitmap + +A corrupt f2fs filesystem could have a block offset or a bitmap +offset that would cause us to read beyond the bounds of the nat +bitmap. + +Introduce the nat_bitmap_size member in grub_f2fs_data which holds +the size of nat bitmap. + +Set the size when loading the nat bitmap in nat_bitmap_ptr(), and +catch when an invalid offset would create a pointer past the end of +the allocated space. + +Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid +reading past the end of the nat bitmap. + +Signed-off-by: Sudhakar Kuppusamy +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 62d63d5e38c67a6e349148bf7cb87c560e935a7e) +--- + grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------ + 1 file changed, 27 insertions(+), 6 deletions(-) + +diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c +index 63702214b0..8898b235e0 100644 +--- a/grub-core/fs/f2fs.c ++++ b/grub-core/fs/f2fs.c +@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */ + + #define MAX_VOLUME_NAME 512 ++#define MAX_NAT_BITMAP_SIZE 3900 + + enum FILE_TYPE + { +@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint + grub_uint32_t checksum_offset; + grub_uint64_t elapsed_time; + grub_uint8_t alloc_type[MAX_ACTIVE_LOGS]; +- grub_uint8_t sit_nat_version_bitmap[3900]; ++ grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE]; + grub_uint32_t checksum; + } GRUB_PACKED; + +@@ -302,6 +303,7 @@ struct grub_f2fs_data + + struct grub_f2fs_nat_journal nat_j; + char *nat_bitmap; ++ grub_uint32_t nat_bitmap_size; + + grub_disk_t disk; + struct grub_f2fs_node *inode; +@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type) + } + + static void * +-nat_bitmap_ptr (struct grub_f2fs_data *data) ++nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size) + { + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; + grub_uint32_t offset; ++ *nat_bitmap_size = MAX_NAT_BITMAP_SIZE; + + if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0) + return ckpt->sit_nat_version_bitmap; + + offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize); ++ if (offset >= MAX_NAT_BITMAP_SIZE) ++ return NULL; ++ ++ *nat_bitmap_size = *nat_bitmap_size - offset; + + return ckpt->sit_nat_version_bitmap + offset; + } +@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len) + } + + static int +-grub_f2fs_test_bit (grub_uint32_t nr, const char *p) ++grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len) + { + int mask; ++ grub_uint32_t shifted_nr = (nr >> 3); + +- p += (nr >> 3); ++ if (shifted_nr >= len) ++ return -1; ++ ++ p += shifted_nr; + mask = 1 << (7 - (nr & 0x07)); + + return mask & *p; +@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) + grub_uint32_t seg_off, block_off, entry_off, block_addr; + grub_uint32_t blkaddr = 0; + grub_err_t err; ++ int result_bit; + + err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); + if (err != GRUB_ERR_NONE) +@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) + ((seg_off * data->blocks_per_seg) << 1) + + (block_off & (data->blocks_per_seg - 1)); + +- if (grub_f2fs_test_bit (block_off, data->nat_bitmap)) ++ result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap, ++ data->nat_bitmap_size); ++ if (result_bit > 0) + block_addr += data->blocks_per_seg; ++ else if (result_bit == -1) ++ { ++ grub_free (nat_block); ++ return 0; ++ } + + err = grub_f2fs_block_read (data, block_addr, nat_block); + if (err) +@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk) + if (err) + goto fail; + +- data->nat_bitmap = nat_bitmap_ptr (data); ++ data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size); ++ if (data->nat_bitmap == NULL) ++ goto fail; + + err = get_nat_journal (data); + if (err) diff --git a/SOURCES/0241-video-readers-png-Abort-sooner-if-a-read-operation-f.patch b/SOURCES/0241-video-readers-png-Abort-sooner-if-a-read-operation-f.patch deleted file mode 100644 index 870f462..0000000 --- a/SOURCES/0241-video-readers-png-Abort-sooner-if-a-read-operation-f.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 14:02:55 +1000 -Subject: [PATCH] video/readers/png: Abort sooner if a read operation fails - -Fuzzing revealed some inputs that were taking a long time, potentially -forever, because they did not bail quickly upon encountering an I/O error. - -Try to catch I/O errors sooner and bail out. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 882be97d1df6449b9fd4d593f0cb70005fde3494) -(cherry picked from commit 3f6fc3ebfd58fcdb3fe6c2f7a5a4fa05772ae786) ---- - grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++++++++------- - 1 file changed, 47 insertions(+), 8 deletions(-) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index 0157ff7420..e2a6b1cf3c 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -142,6 +142,7 @@ static grub_uint8_t - grub_png_get_byte (struct grub_png_data *data) - { - grub_uint8_t r; -+ grub_ssize_t bytes_read = 0; - - if ((data->inside_idat) && (data->idat_remain == 0)) - { -@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data) - } - - r = 0; -- grub_file_read (data->file, &r, 1); -+ bytes_read = grub_file_read (data->file, &r, 1); -+ -+ if (bytes_read != 1) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: unexpected end of data"); -+ return 0; -+ } - - if (data->inside_idat) - data->idat_remain--; -@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data, - if (len == 0) - return GRUB_ERR_NONE; - -- for (i = 0; 3 * i < len && i < 256; i++) -+ grub_errno = GRUB_ERR_NONE; -+ for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++) - for (j = 0; j < 3; j++) - data->palette[i][j] = grub_png_get_byte (data); -- for (i *= 3; i < len; i++) -+ for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++) - grub_png_get_byte (data); - - grub_png_get_dword (data); - -- return GRUB_ERR_NONE; -+ return grub_errno; - } - - static grub_err_t -@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size"); - - color_bits = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - data->is_16bit = (color_bits == 16); - - color_type = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - /* According to PNG spec, no other types are valid. */ - if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR)) -@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data) - if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: compression method not supported"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: filter method not supported"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if (grub_png_get_byte (data) != PNG_INTERLACE_NONE) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: interlace method not supported"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - /* Skip crc checksum. */ - grub_png_get_dword (data); -@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht) - int code, i; - - code = 0; -- for (i = 0; i < ht->max_length; i++) -+ for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++) - { - code = (code << 1) + grub_png_get_bits (data, 1); - if (code < ht->maxval[i]) -@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data) - grub_uint8_t lens[DEFLATE_HCLEN_MAX]; - - nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) || - (nb > DEFLATE_HCLEN_MAX)) -@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data) - data->dist_offset); - - prev = 0; -- for (i = 0; i < nl + nd; i++) -+ for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++) - { - int n, code; - struct huff_table *ht; -@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data) - len = cplens[n]; - if (cplext[n]) - len += grub_png_get_bits (data, cplext[n]); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - n = grub_png_get_huff_code (data, &data->dist_table); - dist = cpdist[n]; - if (cpdext[n]) - dist += grub_png_get_bits (data, cpdext[n]); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - pos = data->wp - dist; - if (pos < 0) - pos += WSIZE; - -- while (len > 0) -+ while (len > 0 && grub_errno == GRUB_ERR_NONE) - { - data->slide[data->wp] = data->slide[pos]; - grub_png_output_byte (data, data->slide[data->wp]); -@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data) - int final; - - cmf = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - flg = grub_png_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if ((cmf & 0xF) != Z_DEFLATED) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, -@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data) - int block_type; - - final = grub_png_get_bits (data, 1); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - block_type = grub_png_get_bits (data, 2); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - switch (block_type) - { -@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data) - grub_png_get_byte (data); - grub_png_get_byte (data); - -- for (i = 0; i < len; i++) -+ for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++) - grub_png_output_byte (data, grub_png_get_byte (data)); - - break; -@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data) - - len = grub_png_get_dword (data); - type = grub_png_get_dword (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ break; - data->next_offset = data->file->offset + len + 4; - - switch (type) diff --git a/SOURCES/0242-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch b/SOURCES/0242-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch new file mode 100644 index 0000000..0553d60 --- /dev/null +++ b/SOURCES/0242-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +Date: Wed, 6 Apr 2022 18:17:43 +0530 +Subject: [PATCH] fs/f2fs: Do not copy file names that are too long + +A corrupt f2fs file system might specify a name length which is greater +than the maximum name length supported by the GRUB f2fs driver. + +We will allocate enough memory to store the overly long name, but there +are only F2FS_NAME_LEN bytes in the source, so we would read past the end +of the source. + +While checking directory entries, do not copy a file name with an invalid +length. + +Signed-off-by: Sudhakar Kuppusamy +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 9a891f638509e031d322c94e3cbcf38d36f3993a) +--- + grub-core/fs/f2fs.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c +index 8898b235e0..df6beb544c 100644 +--- a/grub-core/fs/f2fs.c ++++ b/grub-core/fs/f2fs.c +@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx) + + ftype = ctx->dentry[i].file_type; + name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len); ++ ++ if (name_len >= F2FS_NAME_LEN) ++ return 0; ++ + filename = grub_malloc (name_len + 1); + if (!filename) + return 0; diff --git a/SOURCES/0242-video-readers-png-Refuse-to-handle-multiple-image-he.patch b/SOURCES/0242-video-readers-png-Refuse-to-handle-multiple-image-he.patch deleted file mode 100644 index 52832da..0000000 --- a/SOURCES/0242-video-readers-png-Refuse-to-handle-multiple-image-he.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 14:13:40 +1000 -Subject: [PATCH] video/readers/png: Refuse to handle multiple image headers - -This causes the bitmap to be leaked. Do not permit multiple image headers. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 8ce433557adeadbc46429aabb9f850b02ad2bdfb) -(cherry picked from commit 6e10bba6a4cbfd6c7bf116f41fd4e037465e19d8) ---- - grub-core/video/readers/png.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index e2a6b1cf3c..8955b8ecfd 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data) - int color_bits; - enum grub_video_blit_format blt; - -+ if (data->image_width || data->image_height) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found"); -+ - data->image_width = grub_png_get_dword (data); - data->image_height = grub_png_get_dword (data); - diff --git a/SOURCES/0243-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch b/SOURCES/0243-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch new file mode 100644 index 0000000..7ff5821 --- /dev/null +++ b/SOURCES/0243-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darren Kenny +Date: Tue, 29 Mar 2022 10:49:56 +0000 +Subject: [PATCH] fs/btrfs: Fix several fuzz issues with invalid dir item + sizing + +According to the btrfs code in Linux, the structure of a directory item +leaf should be of the form: + + |struct btrfs_dir_item|name|data| + +in GRUB the name len and data len are in the grub_btrfs_dir_item +structure's n and m fields respectively. + +The combined size of the structure, name and data should be less than +the allocated memory, a difference to the Linux kernel's struct +btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for +where the name is stored, so we adjust for that too. + +Signed-off-by: Darren Kenny +Reviewed-by: Daniel Kiper +(cherry picked from commit 6d3f06c0b6a8992b9b1bb0e62af93ac5ff2781f0) +[rharwood: we've an extra variable here] +Signed-off-by: Robbie Harwood +--- + grub-core/fs/btrfs.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 07c0ff874b..2fcfb738fe 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -2254,6 +2254,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, + grub_uint64_t tree; + grub_uint8_t type; + char *new_path = NULL; ++ grub_size_t est_size = 0; + + if (!data) + return grub_errno; +@@ -2320,6 +2321,18 @@ grub_btrfs_dir (grub_device_t device, const char *path, + break; + } + ++ if (direl == NULL || ++ grub_add (grub_le_to_cpu16 (direl->n), ++ grub_le_to_cpu16 (direl->m), &est_size) || ++ grub_add (est_size, sizeof (*direl), &est_size) || ++ grub_sub (est_size, sizeof (direl->name), &est_size) || ++ est_size > allocated) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ r = -grub_errno; ++ goto out; ++ } ++ + for (cdirel = direl; + (grub_uint8_t *) cdirel - (grub_uint8_t *) direl + < (grub_ssize_t) elemsize; +@@ -2330,6 +2343,19 @@ grub_btrfs_dir (grub_device_t device, const char *path, + char c; + struct grub_btrfs_inode inode; + struct grub_dirhook_info info; ++ ++ if (cdirel == NULL || ++ grub_add (grub_le_to_cpu16 (cdirel->n), ++ grub_le_to_cpu16 (cdirel->m), &est_size) || ++ grub_add (est_size, sizeof (*cdirel), &est_size) || ++ grub_sub (est_size, sizeof (cdirel->name), &est_size) || ++ est_size > allocated) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ r = -grub_errno; ++ goto out; ++ } ++ + err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id, + tree); + grub_memset (&info, 0, sizeof (info)); diff --git a/SOURCES/0243-video-readers-png-Drop-greyscale-support-to-fix-heap.patch b/SOURCES/0243-video-readers-png-Drop-greyscale-support-to-fix-heap.patch deleted file mode 100644 index c639780..0000000 --- a/SOURCES/0243-video-readers-png-Drop-greyscale-support-to-fix-heap.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 18:51:35 +1000 -Subject: [PATCH] video/readers/png: Drop greyscale support to fix heap - out-of-bounds write - -A 16-bit greyscale PNG without alpha is processed in the following loop: - - for (i = 0; i < (data->image_width * data->image_height); - i++, d1 += 4, d2 += 2) - { - d1[R3] = d2[1]; - d1[G3] = d2[1]; - d1[B3] = d2[1]; - } - -The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration, -but there are only 3 bytes allocated for storage. This means that image -data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes -out of every 4 following the end of the image. - -This has existed since greyscale support was added in 2013 in commit -3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale). - -Saving starfield.png as a 16-bit greyscale image without alpha in the gimp -and attempting to load it causes grub-emu to crash - I don't think this code -has ever worked. - -Delete all PNG greyscale support. - -Fixes: CVE-2021-3695 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 0e1d163382669bd734439d8864ee969616d971d9) -[rharwood: context conflict] -Signed-off-by: Robbie Harwood -(cherry picked from commit 4c631c8119206b3178912df2905434d967661c3d) ---- - grub-core/video/readers/png.c | 85 +++---------------------------------------- - 1 file changed, 6 insertions(+), 79 deletions(-) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index 8955b8ecfd..a3161e25b6 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -100,7 +100,7 @@ struct grub_png_data - - unsigned image_width, image_height; - int bpp, is_16bit; -- int raw_bytes, is_gray, is_alpha, is_palette; -+ int raw_bytes, is_alpha, is_palette; - int row_bytes, color_bits; - grub_uint8_t *image_data; - -@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data) - data->bpp = 3; - else - { -- data->is_gray = 1; -- data->bpp = 1; -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: color type not supported"); - } - - if ((color_bits != 8) && (color_bits != 16) - && (color_bits != 4 -- || !(data->is_gray || data->is_palette))) -+ || !data->is_palette)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "png: bit depth must be 8 or 16"); - -@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data) - } - - #ifndef GRUB_CPU_WORDS_BIGENDIAN -- if (data->is_16bit || data->is_gray || data->is_palette) -+ if (data->is_16bit || data->is_palette) - #endif - { - data->image_data = grub_calloc (data->image_height, data->row_bytes); -@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data) - int shift; - int mask = (1 << data->color_bits) - 1; - unsigned j; -- if (data->is_gray) -- { -- /* Generic formula is -- (0xff * i) / ((1U << data->color_bits) - 1) -- but for allowed bit depth of 1, 2 and for it's -- equivalent to -- (0xff / ((1U << data->color_bits) - 1)) * i -- Precompute the multipliers to avoid division. -- */ - -- const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 }; -- for (i = 0; i < (1U << data->color_bits); i++) -- { -- grub_uint8_t col = multipliers[data->color_bits] * i; -- palette[i][0] = col; -- palette[i][1] = col; -- palette[i][2] = col; -- } -- } -- else -- grub_memcpy (palette, data->palette, 3 << data->color_bits); -+ grub_memcpy (palette, data->palette, 3 << data->color_bits); - d1c = d1; - d2c = d2; - for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3, -@@ -956,60 +937,6 @@ grub_png_convert_image (struct grub_png_data *data) - } - return; - } -- -- if (data->is_gray) -- { -- switch (data->bpp) -- { -- case 4: -- /* 16-bit gray with alpha. */ -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 4, d2 += 4) -- { -- d1[R4] = d2[3]; -- d1[G4] = d2[3]; -- d1[B4] = d2[3]; -- d1[A4] = d2[1]; -- } -- break; -- case 2: -- if (data->is_16bit) -- /* 16-bit gray without alpha. */ -- { -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 4, d2 += 2) -- { -- d1[R3] = d2[1]; -- d1[G3] = d2[1]; -- d1[B3] = d2[1]; -- } -- } -- else -- /* 8-bit gray with alpha. */ -- { -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 4, d2 += 2) -- { -- d1[R4] = d2[1]; -- d1[G4] = d2[1]; -- d1[B4] = d2[1]; -- d1[A4] = d2[0]; -- } -- } -- break; -- /* 8-bit gray without alpha. */ -- case 1: -- for (i = 0; i < (data->image_width * data->image_height); -- i++, d1 += 3, d2++) -- { -- d1[R3] = d2[0]; -- d1[G3] = d2[0]; -- d1[B3] = d2[0]; -- } -- break; -- } -- return; -- } - - { - /* Only copy the upper 8 bit. */ diff --git a/SOURCES/0244-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch b/SOURCES/0244-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch new file mode 100644 index 0000000..d638c11 --- /dev/null +++ b/SOURCES/0244-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darren Kenny +Date: Tue, 29 Mar 2022 15:52:46 +0000 +Subject: [PATCH] fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing + +The fuzzer is generating btrfs file systems that have chunks with +invalid combinations of stripes and substripes for the given RAID +configurations. + +After examining the Linux kernel fs/btrfs/tree-checker.c code, it +appears that sub-stripes should only be applied to RAID10, and in that +case there should only ever be 2 of them. + +Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4 +should have 2. 3 or 4 stripes respectively, which is what redundancy +corresponds. + +Some of the chunks ended up with a size of 0, which grub_malloc() still +returned memory for and in turn generated ASAN errors later when +accessed. + +While it would be possible to specifically limit the number of stripes, +a more correct test was on the combination of the chunk item, and the +number of stripes by the size of the chunk stripe structure in +comparison to the size of the chunk itself. + +Signed-off-by: Darren Kenny +Reviewed-by: Daniel Kiper +(cherry picked from commit 3849647b4b98a4419366708fc4b7f339c6f55ec7) +--- + grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 2fcfb738fe..0e9b450413 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -941,6 +941,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + return grub_error (GRUB_ERR_BAD_FS, + "couldn't find the chunk descriptor"); + ++ if (!chsize) ++ { ++ grub_dprintf ("btrfs", "zero-size chunk\n"); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "got an invalid zero-size chunk"); ++ } + chunk = grub_malloc (chsize); + if (!chunk) + return grub_errno; +@@ -999,6 +1005,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size), + nstripes, + NULL); ++ ++ /* For single, there should be exactly 1 stripe. */ ++ if (grub_le_to_cpu16 (chunk->nstripes) != 1) ++ { ++ grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n", ++ grub_le_to_cpu16 (chunk->nstripes)); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid RAID_SINGLE: nstripes != 1 (%u)", ++ grub_le_to_cpu16 (chunk->nstripes)); ++ } + if (stripe_length == 0) + stripe_length = 512; + stripen = grub_divmod64 (off, stripe_length, &stripe_offset); +@@ -1018,6 +1034,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + stripen = 0; + stripe_offset = off; + csize = grub_le_to_cpu64 (chunk->size) - off; ++ ++ /* ++ * Redundancy, and substripes only apply to RAID10, and there ++ * should be exactly 2 sub-stripes. ++ */ ++ if (grub_le_to_cpu16 (chunk->nstripes) != redundancy) ++ { ++ grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n", ++ redundancy, grub_le_to_cpu16 (chunk->nstripes)); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid RAID1: nstripes != %u (%u)", ++ redundancy, grub_le_to_cpu16 (chunk->nstripes)); ++ } + break; + } + case GRUB_BTRFS_CHUNK_TYPE_RAID0: +@@ -1054,6 +1083,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + stripe_offset = low + chunk_stripe_length + * high; + csize = chunk_stripe_length - low; ++ ++ /* ++ * Substripes only apply to RAID10, and there ++ * should be exactly 2 sub-stripes. ++ */ ++ if (grub_le_to_cpu16 (chunk->nsubstripes) != 2) ++ { ++ grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)", ++ grub_le_to_cpu16 (chunk->nsubstripes)); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "invalid RAID10: nsubstripes != 2 (%u)", ++ grub_le_to_cpu16 (chunk->nsubstripes)); ++ } ++ + break; + } + case GRUB_BTRFS_CHUNK_TYPE_RAID5: +@@ -1153,6 +1196,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + + for (j = 0; j < 2; j++) + { ++ grub_size_t est_chunk_alloc = 0; ++ + grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T + "+0x%" PRIxGRUB_UINT64_T + " (%d stripes (%d substripes) of %" +@@ -1165,6 +1210,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n", + addr); + ++ if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe), ++ grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) || ++ grub_add (est_chunk_alloc, ++ sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) || ++ est_chunk_alloc > chunk->size) ++ { ++ err = GRUB_ERR_BAD_FS; ++ break; ++ } ++ + if (is_raid56) + { + err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/SOURCES/0244-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch b/SOURCES/0244-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch deleted file mode 100644 index c1e232e..0000000 --- a/SOURCES/0244-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 23:25:07 +1000 -Subject: [PATCH] video/readers/png: Avoid heap OOB R/W inserting huff table - items - -In fuzzing we observed crashes where a code would attempt to be inserted -into a huffman table before the start, leading to a set of heap OOB reads -and writes as table entries with negative indices were shifted around and -the new code written in. - -Catch the case where we would underflow the array and bail. - -Fixes: CVE-2021-3696 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 1ae9a91d42cb40da8a6f11fac65541858e340afa) -(cherry picked from commit 132ccc681cf642ad748580f26b54c9259a7f43fd) ---- - grub-core/video/readers/png.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index a3161e25b6..d7ed5aa6cf 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len) - for (i = len; i < ht->max_length; i++) - n += ht->maxval[i]; - -+ if (n > ht->num_values) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: out of range inserting huffman table item"); -+ return; -+ } -+ - for (i = 0; i < n; i++) - ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1]; - diff --git a/SOURCES/0245-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch b/SOURCES/0245-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch new file mode 100644 index 0000000..2e5145f --- /dev/null +++ b/SOURCES/0245-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darren Kenny +Date: Thu, 7 Apr 2022 15:18:12 +0000 +Subject: [PATCH] fs/btrfs: Fix more fuzz issues related to chunks + +The corpus we generating issues in grub_btrfs_read_logical() when +attempting to iterate over nstripes entries in the boot mapping. + +In most cases the reason for the failure was that the number of strips +exceeded the possible space statically allocated in superblock bootmapping +space. Each stripe entry in the bootmapping block consists of +a grub_btrfs_key followed by a grub_btrfs_chunk_stripe. + +Another issue that came up was that while calculating the chunk size, +in an earlier piece of code in that function, depending on the data +provided in the btrfs file system, it would end up calculating a size +that was too small to contain even 1 grub_btrfs_chunk_item, which is +obviously invalid too. + +Signed-off-by: Darren Kenny +Reviewed-by: Daniel Kiper +(cherry picked from commit e00cd76cbadcc897a9cc4087cb2fcb5dbe15e596) +--- + grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 0e9b450413..47325f6ad7 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -947,6 +947,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + return grub_error (GRUB_ERR_BAD_FS, + "got an invalid zero-size chunk"); + } ++ ++ /* ++ * The space being allocated for a chunk should at least be able to ++ * contain one chunk item. ++ */ ++ if (chsize < sizeof (struct grub_btrfs_chunk_item)) ++ { ++ grub_dprintf ("btrfs", "chunk-size too small\n"); ++ return grub_error (GRUB_ERR_BAD_FS, ++ "got an invalid chunk size"); ++ } + chunk = grub_malloc (chsize); + if (!chunk) + return grub_errno; +@@ -1194,6 +1205,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + if (csize > (grub_uint64_t) size) + csize = size; + ++ /* ++ * The space for a chunk stripe is limited to the space provide in the super-block's ++ * bootstrap mapping with an initial btrfs key at the start of each chunk. ++ */ ++ grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) / ++ (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe)); ++ + for (j = 0; j < 2; j++) + { + grub_size_t est_chunk_alloc = 0; +@@ -1220,6 +1238,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, + break; + } + ++ if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes) ++ { ++ err = GRUB_ERR_BAD_FS; ++ break; ++ } ++ + if (is_raid56) + { + err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/SOURCES/0245-video-readers-png-Sanity-check-some-huffman-codes.patch b/SOURCES/0245-video-readers-png-Sanity-check-some-huffman-codes.patch deleted file mode 100644 index 01d6333..0000000 --- a/SOURCES/0245-video-readers-png-Sanity-check-some-huffman-codes.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 6 Jul 2021 19:19:11 +1000 -Subject: [PATCH] video/readers/png: Sanity check some huffman codes - -ASAN picked up two OOB global reads: we weren't checking if some code -values fit within the cplens or cpdext arrays. Check and throw an error -if not. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit c3a8ab0cbd24153ec7b1f84a96ddfdd72ef8d117) -(cherry picked from commit 5d09addf58086aa11d5f9a91af5632ff87c2d2ee) ---- - grub-core/video/readers/png.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c -index d7ed5aa6cf..7f2ba7849b 100644 ---- a/grub-core/video/readers/png.c -+++ b/grub-core/video/readers/png.c -@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) - int len, dist, pos; - - n -= 257; -+ if (((unsigned int) n) >= ARRAY_SIZE (cplens)) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: invalid huff code"); - len = cplens[n]; - if (cplext[n]) - len += grub_png_get_bits (data, cplext[n]); -@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data) - return grub_errno; - - n = grub_png_get_huff_code (data, &data->dist_table); -+ if (((unsigned int) n) >= ARRAY_SIZE (cpdist)) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "png: invalid huff code"); - dist = cpdist[n]; - if (cpdext[n]) - dist += grub_png_get_bits (data, cpdext[n]); diff --git a/SOURCES/0246-misc-Make-grub_min-and-grub_max-more-resilient.patch b/SOURCES/0246-misc-Make-grub_min-and-grub_max-more-resilient.patch new file mode 100644 index 0000000..eb2e8fd --- /dev/null +++ b/SOURCES/0246-misc-Make-grub_min-and-grub_max-more-resilient.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 16:06:10 -0400 +Subject: [PATCH] misc: Make grub_min() and grub_max() more resilient. + +grub_min(a,b) and grub_max(a,b) use a relatively naive implementation +which leads to several problems: +- they evaluate their parameters more than once +- the naive way to address this, to declare temporary variables in a + statement-expression, isn't resilient against nested uses, because + MIN(a,MIN(b,c)) results in the temporary variables being declared in + two nested scopes, which may result in a build warning depending on + your build options. + +This patch changes our implementation to use a statement-expression +inside a helper macro, and creates the symbols for the temporary +variables with __COUNTER__ (A GNU C cpp extension) and token pasting to +create uniquely named internal variables. + +Signed-off-by: Peter Jones +--- + grub-core/loader/multiboot_elfxx.c | 4 +--- + include/grub/misc.h | 25 +++++++++++++++++++++++-- + 2 files changed, 24 insertions(+), 5 deletions(-) + +diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c +index f2318e0d16..87f6e31aa6 100644 +--- a/grub-core/loader/multiboot_elfxx.c ++++ b/grub-core/loader/multiboot_elfxx.c +@@ -35,9 +35,7 @@ + #endif + + #include +- +-#define CONCAT(a,b) CONCAT_(a, b) +-#define CONCAT_(a,b) a ## b ++#include + + #pragma GCC diagnostic ignored "-Wcast-align" + +diff --git a/include/grub/misc.h b/include/grub/misc.h +index 6c4aa85ac5..cf84aec1db 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -35,6 +35,14 @@ + #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) + #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } + ++#ifndef CONCAT_ ++#define CONCAT_(a, b) a ## b ++#endif ++ ++#ifndef CONCAT ++#define CONCAT(a, b) CONCAT_(a, b) ++#endif ++ + #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__) + + void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n); +@@ -498,8 +506,21 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, + #define grub_boot_time(...) + #endif + +-#define grub_max(a, b) (((a) > (b)) ? (a) : (b)) +-#define grub_min(a, b) (((a) < (b)) ? (a) : (b)) ++#define _grub_min(a, b, _a, _b) \ ++ ({ typeof (a) _a = (a); \ ++ typeof (b) _b = (b); \ ++ _a < _b ? _a : _b; }) ++#define grub_min(a, b) _grub_min(a, b, \ ++ CONCAT(_a_,__COUNTER__), \ ++ CONCAT(_b_,__COUNTER__)) ++ ++#define _grub_max(a, b, _a, _b) \ ++ ({ typeof (a) _a = (a); \ ++ typeof (b) _b = (b); \ ++ _a > _b ? _a : _b; }) ++#define grub_max(a, b) _grub_max(a, b, \ ++ CONCAT(_a_,__COUNTER__), \ ++ CONCAT(_b_,__COUNTER__)) + + #define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) - __builtin_clzll (n) - 1) + diff --git a/SOURCES/0246-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch b/SOURCES/0246-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch deleted file mode 100644 index e03b6d9..0000000 --- a/SOURCES/0246-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch +++ /dev/null @@ -1,256 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 28 Jun 2021 14:16:14 +1000 -Subject: [PATCH] video/readers/jpeg: Abort sooner if a read operation fails - -Fuzzing revealed some inputs that were taking a long time, potentially -forever, because they did not bail quickly upon encountering an I/O error. - -Try to catch I/O errors sooner and bail out. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit ab2e5d2e4bff488bbb557ed435a61ae102ef9f0c) -(cherry picked from commit 1ff8df0d2dea8ec7c8575241d5e7d6622c204ec3) ---- - grub-core/video/readers/jpeg.c | 86 ++++++++++++++++++++++++++++++++++-------- - 1 file changed, 70 insertions(+), 16 deletions(-) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index e31602f766..10225abd53 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -109,9 +109,17 @@ static grub_uint8_t - grub_jpeg_get_byte (struct grub_jpeg_data *data) - { - grub_uint8_t r; -+ grub_ssize_t bytes_read; - - r = 0; -- grub_file_read (data->file, &r, 1); -+ bytes_read = grub_file_read (data->file, &r, 1); -+ -+ if (bytes_read != 1) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: unexpected end of data"); -+ return 0; -+ } - - return r; - } -@@ -120,9 +128,17 @@ static grub_uint16_t - grub_jpeg_get_word (struct grub_jpeg_data *data) - { - grub_uint16_t r; -+ grub_ssize_t bytes_read; - - r = 0; -- grub_file_read (data->file, &r, sizeof (grub_uint16_t)); -+ bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t)); -+ -+ if (bytes_read != sizeof (grub_uint16_t)) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: unexpected end of data"); -+ return 0; -+ } - - return grub_be_to_cpu16 (r); - } -@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) - if (data->bit_mask == 0) - { - data->bit_save = grub_jpeg_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: file read error"); -+ return 0; -+ } - if (data->bit_save == JPEG_ESC_CHAR) - { - if (grub_jpeg_get_byte (data) != 0) -@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data) - "jpeg: invalid 0xFF in data stream"); - return 0; - } -+ if (grub_errno != GRUB_ERR_NONE) -+ { -+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error"); -+ return 0; -+ } - } - data->bit_mask = 0x80; - } -@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num) - return 0; - - msb = value = grub_jpeg_get_bit (data); -- for (i = 1; i < num; i++) -+ for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++) - value = (value << 1) + (grub_jpeg_get_bit (data) != 0); - if (!msb) - value += 1 - (1 << num); -@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) - while (data->file->offset + sizeof (count) + 1 <= next_marker) - { - id = grub_jpeg_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - ac = (id >> 4) & 1; - id &= 0xF; - if (id > 1) -@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) - - next_marker = data->file->offset; - next_marker += grub_jpeg_get_word (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - - if (next_marker > data->file->size) - { -@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data) - <= next_marker) - { - id = grub_jpeg_get_byte (data); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (id >= 0x10) /* Upper 4-bit is precision. */ - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: only 8-bit precision is supported"); -@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) - next_marker = data->file->offset; - next_marker += grub_jpeg_get_word (data); - -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ - if (grub_jpeg_get_byte (data) != 8) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: only 8-bit precision is supported"); -@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); - - ss = grub_jpeg_get_byte (data); /* Sampling factor. */ -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (!id) - { - grub_uint8_t vs, hs; -@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du) - } - } - --static void -+static grub_err_t - grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - { - int h1, h2, qt; -@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - data->dc_value[id] += - grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1)); - -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ - du[0] = data->dc_value[id] * (int) data->quan_table[qt][0]; - pos = 1; - while (pos < ARRAY_SIZE (data->quan_table[qt])) -@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - num >>= 4; - pos += num; - -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; -+ - if (pos >= ARRAY_SIZE (jpeg_zigzag_order)) - { -- grub_error (GRUB_ERR_BAD_FILE_TYPE, -- "jpeg: invalid position in zigzag order!?"); -- return; -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: invalid position in zigzag order!?"); - } - - du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos]; -@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du) - } - - grub_jpeg_idct_transform (du); -+ return GRUB_ERR_NONE; - } - - static void -@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - data_offset += grub_jpeg_get_word (data); - - cc = grub_jpeg_get_byte (data); -- -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (cc != 3 && cc != 1) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: component count must be 1 or 3"); -@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - id = grub_jpeg_get_byte (data) - 1; - if ((id < 0) || (id >= 3)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index"); -- -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - ht = grub_jpeg_get_byte (data); - data->comp_index[id][1] = (ht >> 4); - data->comp_index[id][2] = (ht & 0xF) + 2; -@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) || - (data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index"); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - } - - grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */ - grub_jpeg_get_word (data); -- -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_errno; - if (data->file->offset != data_offset) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); - -@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - { - unsigned c1, vb, hb, nr1, nc1; - int rst = data->dri; -+ grub_err_t err = GRUB_ERR_NONE; - - vb = 8 << data->log_vs; - hb = 8 << data->log_hs; -@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - - for (r2 = 0; r2 < (1U << data->log_vs); r2++) - for (c2 = 0; c2 < (1U << data->log_hs); c2++) -- grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); -+ { -+ err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ } - - if (data->color_components >= 3) - { -- grub_jpeg_decode_du (data, 1, data->cbdu); -- grub_jpeg_decode_du (data, 2, data->crdu); -+ err = grub_jpeg_decode_du (data, 1, data->cbdu); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ err = grub_jpeg_decode_du (data, 2, data->crdu); -+ if (err != GRUB_ERR_NONE) -+ return err; - } - -- if (grub_errno) -- return grub_errno; -- - nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb; - nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb; - diff --git a/SOURCES/0247-ReiserFS-switch-to-using-grub_min-grub_max.patch b/SOURCES/0247-ReiserFS-switch-to-using-grub_min-grub_max.patch new file mode 100644 index 0000000..0707af3 --- /dev/null +++ b/SOURCES/0247-ReiserFS-switch-to-using-grub_min-grub_max.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 Apr 2022 16:31:17 -0400 +Subject: [PATCH] ReiserFS: switch to using grub_min()/grub_max() + +This is a minor cleanup patch to remove the bespoke MIN() and MAX() +definitions from the reiserfs driver, and uses grub_min() / grub_max() +instead. + +Signed-off-by: Peter Jones +--- + grub-core/fs/reiserfs.c | 28 +++++++++------------------- + 1 file changed, 9 insertions(+), 19 deletions(-) + +diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c +index af6a226a7f..b8253da7fe 100644 +--- a/grub-core/fs/reiserfs.c ++++ b/grub-core/fs/reiserfs.c +@@ -42,16 +42,6 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + +-#define MIN(a, b) \ +- ({ typeof (a) _a = (a); \ +- typeof (b) _b = (b); \ +- _a < _b ? _a : _b; }) +- +-#define MAX(a, b) \ +- ({ typeof (a) _a = (a); \ +- typeof (b) _b = (b); \ +- _a > _b ? _a : _b; }) +- + #define REISERFS_SUPER_BLOCK_OFFSET 0x10000 + #define REISERFS_MAGIC_LEN 12 + #define REISERFS_MAGIC_STRING "ReIsEr" +@@ -1076,7 +1066,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2); + initial_position = off; + current_position = 0; +- final_position = MIN (len + initial_position, node->size); ++ final_position = grub_min (len + initial_position, node->size); + grub_dprintf ("reiserfs", + "Reading from %lld to %lld (%lld instead of requested %ld)\n", + (unsigned long long) initial_position, +@@ -1115,8 +1105,8 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block); + if (initial_position < current_position + item_size) + { +- offset = MAX ((signed) (initial_position - current_position), 0); +- length = (MIN (item_size, final_position - current_position) ++ offset = grub_max ((signed) (initial_position - current_position), 0); ++ length = (grub_min (item_size, final_position - current_position) + - offset); + grub_dprintf ("reiserfs", + "Reading direct block %u from %u to %u...\n", +@@ -1161,9 +1151,9 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block); + if (current_position + block_size >= initial_position) + { +- offset = MAX ((signed) (initial_position - current_position), +- 0); +- length = (MIN (block_size, final_position - current_position) ++ offset = grub_max ((signed) (initial_position - current_position), ++ 0); ++ length = (grub_min (block_size, final_position - current_position) + - offset); + grub_dprintf ("reiserfs", + "Reading indirect block %u from %u to %u...\n", +@@ -1205,7 +1195,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + switch (found.type) + { + case GRUB_REISERFS_DIRECT: +- read_length = MIN (len, item_size - file->offset); ++ read_length = grub_min (len, item_size - file->offset); + grub_disk_read (found.data->disk, + (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE, + grub_le_to_cpu16 (found.header.item_location) + file->offset, +@@ -1224,12 +1214,12 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, + item_size, (char *) indirect_block_ptr); + if (grub_errno) + goto fail; +- len = MIN (len, file->size - file->offset); ++ len = grub_min (len, file->size - file->offset); + for (indirect_block = file->offset / block_size; + indirect_block < indirect_block_count && read_length < len; + indirect_block++) + { +- read = MIN (block_size, len - read_length); ++ read = grub_min (block_size, len - read_length); + grub_disk_read (found.data->disk, + (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE, + file->offset % block_size, read, diff --git a/SOURCES/0247-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch b/SOURCES/0247-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch deleted file mode 100644 index 0ee92d5..0000000 --- a/SOURCES/0247-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 28 Jun 2021 14:16:58 +1000 -Subject: [PATCH] video/readers/jpeg: Do not reallocate a given huff table - -Fix a memory leak where an invalid file could cause us to reallocate -memory for a huffman table we had already allocated memory for. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit bc06e12b4de55cc6f926af9f064170c82b1403e9) -(cherry picked from commit 5298bf758ea39a90537f9a1c76541ff2f21b970b) ---- - grub-core/video/readers/jpeg.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index 10225abd53..caa211f06d 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data) - n += count[i]; - - id += ac * 2; -+ if (data->huff_value[id] != NULL) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: attempt to reallocate huffman table"); - data->huff_value[id] = grub_malloc (n); - if (grub_errno) - return grub_errno; diff --git a/SOURCES/0248-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch b/SOURCES/0248-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch new file mode 100644 index 0000000..a7ac6f2 --- /dev/null +++ b/SOURCES/0248-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 24 Mar 2022 14:40:01 -0400 +Subject: [PATCH] misc: make grub_boot_time() also call + grub_dprintf("boot",...) + +Currently grub_boot_time() includes valuable debugging messages, but if +you build without BOOT_TIME_STATS enabled, they are silently and +confusingly compiled away. + +This patch changes grub_boot_time() to also log when "boot" is enabled +in DEBUG, regardless of BOOT_TIME_STATS. + +Signed-off-by: Peter Jones +--- + grub-core/kern/misc.c | 3 ++- + include/grub/misc.h | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index a186ad3dd4..cb45461402 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -1334,7 +1334,8 @@ grub_real_boot_time (const char *file, + n->next = 0; + + va_start (args, fmt); +- n->msg = grub_xvasprintf (fmt, args); ++ n->msg = grub_xvasprintf (fmt, args); ++ grub_dprintf ("boot", "%s\n", n->msg); + va_end (args); + + *boot_time_last = n; +diff --git a/include/grub/misc.h b/include/grub/misc.h +index cf84aec1db..faae0ae860 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -503,7 +503,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, + const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 3, 4))); + #define grub_boot_time(...) grub_real_boot_time(GRUB_FILE, __LINE__, __VA_ARGS__) + #else +-#define grub_boot_time(...) ++#define grub_boot_time(fmt, ...) grub_dprintf("boot", fmt "\n", ##__VA_ARGS__) + #endif + + #define _grub_min(a, b, _a, _b) \ diff --git a/SOURCES/0248-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch b/SOURCES/0248-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch deleted file mode 100644 index ed20cda..0000000 --- a/SOURCES/0248-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 28 Jun 2021 14:25:17 +1000 -Subject: [PATCH] video/readers/jpeg: Refuse to handle multiple start of - streams - -An invalid file could contain multiple start of stream blocks, which -would cause us to reallocate and leak our bitmap. Refuse to handle -multiple start of streams. - -Additionally, fix a grub_error() call formatting. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit f3a854def3e281b7ad4bbea730cd3046de1da52f) -(cherry picked from commit db0154828989a0a52ee59a4dda8c3803752bc827) ---- - grub-core/video/readers/jpeg.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index caa211f06d..1df1171d78 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) - if (data->file->offset != data_offset) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos"); - -+ if (*data->bitmap) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks"); -+ - if (grub_video_bitmap_create (data->bitmap, data->image_width, - data->image_height, - GRUB_VIDEO_BLIT_FORMAT_RGB_888)) -@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - nc1 = (data->image_width + hb - 1) >> (3 + data->log_hs); - - if (data->bitmap_ptr == NULL) -- return grub_error(GRUB_ERR_BAD_FILE_TYPE, -- "jpeg: attempted to decode data before start of stream"); -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: attempted to decode data before start of stream"); - - for (; data->r1 < nr1 && (!data->dri || rst); - data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) diff --git a/SOURCES/0249-modules-make-.module_license-read-only.patch b/SOURCES/0249-modules-make-.module_license-read-only.patch new file mode 100644 index 0000000..ba3b313 --- /dev/null +++ b/SOURCES/0249-modules-make-.module_license-read-only.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 24 Feb 2022 16:32:51 -0500 +Subject: [PATCH] modules: make .module_license read-only + +Currently .module_license is set writable (that is, the section has the +SHF_WRITE flag set) in the module's ELF headers. This probably never +actually matters, but it can't possibly be correct. + +This patch sets that data as "const", which causes that flag not to be +set. + +Signed-off-by: Peter Jones +--- + include/grub/dl.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 20d870f2a4..618ae6f474 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -121,7 +121,7 @@ grub_mod_fini (void) + #define ATTRIBUTE_USED __unused__ + #endif + #define GRUB_MOD_LICENSE(license) \ +- static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; ++ static const char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; + #define GRUB_MOD_DEP(name) \ + static const char grub_module_depend_##name[] \ + __attribute__((section(GRUB_MOD_SECTION(moddeps)), ATTRIBUTE_USED)) = #name diff --git a/SOURCES/0249-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch b/SOURCES/0249-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch deleted file mode 100644 index ed39a71..0000000 --- a/SOURCES/0249-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Wed, 7 Jul 2021 15:38:19 +1000 -Subject: [PATCH] video/readers/jpeg: Block int underflow -> wild pointer write - -Certain 1 px wide images caused a wild pointer write in -grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(), -we have the following loop: - -for (; data->r1 < nr1 && (!data->dri || rst); - data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) - -We did not check if vb * width >= hb * nc1. - -On a 64-bit platform, if that turns out to be negative, it will underflow, -be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so -we see data->bitmap_ptr jump, e.g.: - -0x6180_0000_0480 to -0x6181_0000_0498 - ^ - ~--- carry has occurred and this pointer is now far away from - any object. - -On a 32-bit platform, it will decrement the pointer, creating a pointer -that won't crash but will overwrite random data. - -Catch the underflow and error out. - -Fixes: CVE-2021-3697 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 41aeb2004db9924fecd9f2dd64bc2a5a5594a4b5) -(cherry picked from commit 5f9582490792108306d047379fed2371bee286f8) ---- - grub-core/video/readers/jpeg.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c -index 1df1171d78..2da04094b3 100644 ---- a/grub-core/video/readers/jpeg.c -+++ b/grub-core/video/readers/jpeg.c -@@ -705,6 +705,10 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, - "jpeg: attempted to decode data before start of stream"); - -+ if (vb * data->image_width <= hb * nc1) -+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, -+ "jpeg: cannot decode image with these dimensions"); -+ - for (; data->r1 < nr1 && (!data->dri || rst); - data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) - for (c1 = 0; c1 < nc1 && (!data->dri || rst); diff --git a/SOURCES/0250-modules-strip-.llvm_addrsig-sections-and-similar.patch b/SOURCES/0250-modules-strip-.llvm_addrsig-sections-and-similar.patch new file mode 100644 index 0000000..9f26115 --- /dev/null +++ b/SOURCES/0250-modules-strip-.llvm_addrsig-sections-and-similar.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 24 Feb 2022 16:40:11 -0500 +Subject: [PATCH] modules: strip .llvm_addrsig sections and similar. + +Currently grub modules built with clang or gcc have several sections +which we don't actually need or support. + +We already have a list of section to skip in genmod.sh, and this patch +adds the following sections to that list (as well as a few newlines): + +.note.gnu.property +.llvm* + +Note that the glob there won't work without a new enough linker, but the +failure is just reversion to the status quo, so that's not a big problem. + +Signed-off-by: Peter Jones +--- + grub-core/genmod.sh.in | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in +index 1250589b3f..c2c5280d75 100644 +--- a/grub-core/genmod.sh.in ++++ b/grub-core/genmod.sh.in +@@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then + @TARGET_STRIP@ --strip-unneeded \ + -K grub_mod_init -K grub_mod_fini \ + -K _grub_mod_init -K _grub_mod_fini \ +- -R .note.gnu.gold-version -R .note.GNU-stack \ ++ -R .note.GNU-stack \ ++ -R .note.gnu.gold-version \ ++ -R .note.gnu.property \ + -R .gnu.build.attributes \ ++ -R '.llvm*' \ + -R .rel.gnu.build.attributes \ + -R .rela.gnu.build.attributes \ + -R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \ diff --git a/SOURCES/0250-normal-charset-Fix-array-out-of-bounds-formatting-un.patch b/SOURCES/0250-normal-charset-Fix-array-out-of-bounds-formatting-un.patch deleted file mode 100644 index e51d293..0000000 --- a/SOURCES/0250-normal-charset-Fix-array-out-of-bounds-formatting-un.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 13 Jul 2021 13:24:38 +1000 -Subject: [PATCH] normal/charset: Fix array out-of-bounds formatting unicode - for display - -In some cases attempting to display arbitrary binary strings leads -to ASAN splats reading the widthspec array out of bounds. - -Check the index. If it would be out of bounds, return a width of 1. -I don't know if that's strictly correct, but we're not really expecting -great display of arbitrary binary data, and it's certainly not worse than -an OOB read. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit fdf32abc7a3928852422c0f291d8cd1dd6b34a8d) -(cherry picked from commit f2c10aaf335b88a69885375c4d68ffab2429df77) ---- - grub-core/normal/charset.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c -index 4dfcc31078..7a5a7c153c 100644 ---- a/grub-core/normal/charset.c -+++ b/grub-core/normal/charset.c -@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c) - { - if (grub_unicode_get_comb_type (c->base)) - return 0; -+ if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec)) -+ return 1; - if (widthspec[c->base >> 3] & (1 << (c->base & 7))) - return 2; - else diff --git a/SOURCES/0251-modules-Don-t-allocate-space-for-non-allocable-secti.patch b/SOURCES/0251-modules-Don-t-allocate-space-for-non-allocable-secti.patch new file mode 100644 index 0000000..d07d838 --- /dev/null +++ b/SOURCES/0251-modules-Don-t-allocate-space-for-non-allocable-secti.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 16:56:10 -0400 +Subject: [PATCH] modules: Don't allocate space for non-allocable sections. + +Currently when loading grub modules, we allocate space for all sections, +including those without SHF_ALLOC set. We then copy the sections that +/do/ have SHF_ALLOC set into the allocated memory, leaving some of our +allocation untouched forever. Additionally, on platforms with GOT +fixups and trampolines, we currently compute alignment round-ups for the +sections and sections with sh_size = 0. + +This patch removes the extra space from the allocation computation, and +makes the allocation computation loop skip empty sections as the loading +loop does. + +Signed-off-by: Peter Jones +--- + grub-core/kern/dl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index f304494574..aef8af8aa7 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -289,6 +289,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + i < e->e_shnum; + i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) + { ++ if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) ++ continue; ++ + tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; + if (talign < s->sh_addralign) + talign = s->sh_addralign; diff --git a/SOURCES/0251-net-netbuff-Block-overly-large-netbuff-allocs.patch b/SOURCES/0251-net-netbuff-Block-overly-large-netbuff-allocs.patch deleted file mode 100644 index e74df27..0000000 --- a/SOURCES/0251-net-netbuff-Block-overly-large-netbuff-allocs.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 8 Mar 2022 23:47:46 +1100 -Subject: [PATCH] net/netbuff: Block overly large netbuff allocs - -A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment -reassembly. - -This helps avoid some bugs (and provides a spot to instrument to catch -them at their source). - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit ee9591103004cd13b4efadda671536090ca7fd57) -(cherry picked from commit acde668bb9d9fa862a1a63e3bbd5fa47fdfa9183) ---- - grub-core/net/netbuff.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c -index dbeeefe478..d5e9e9a0d7 100644 ---- a/grub-core/net/netbuff.c -+++ b/grub-core/net/netbuff.c -@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len) - - COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0); - -+ /* -+ * The largest size of a TCP packet is 64 KiB, and everything else -+ * should be a lot smaller - most MTUs are 1500 or less. Cap data -+ * size at 64 KiB + a buffer. -+ */ -+ if (len > 0xffffUL + 0x1000UL) -+ { -+ grub_error (GRUB_ERR_BUG, -+ "attempted to allocate a packet that is too big"); -+ return NULL; -+ } -+ - if (len < NETBUFFMINLEN) - len = NETBUFFMINLEN; - - len = ALIGN_UP (len, NETBUFF_ALIGN); -+ - #ifdef GRUB_MACHINE_EMU - data = grub_malloc (len + sizeof (*nb)); - #else diff --git a/SOURCES/0252-net-ip-Do-IP-fragment-maths-safely.patch b/SOURCES/0252-net-ip-Do-IP-fragment-maths-safely.patch deleted file mode 100644 index 4ba8455..0000000 --- a/SOURCES/0252-net-ip-Do-IP-fragment-maths-safely.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 20 Dec 2021 19:41:21 +1100 -Subject: [PATCH] net/ip: Do IP fragment maths safely - -This avoids an underflow and subsequent unpleasantness. - -Fixes: CVE-2022-28733 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit eb74e5743ca7e18a5e75c392fe0b21d1549a1936) -(cherry picked from commit 552ad34583e788542e9ca08524a0d4bc8f98c297) ---- - grub-core/net/ip.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c -index ce6bdc75c6..cf74f1f794 100644 ---- a/grub-core/net/ip.c -+++ b/grub-core/net/ip.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - - struct iphdr { -@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb, - { - rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) - + (nb->tail - nb->data)); -- rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); -+ -+ if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t), -+ &rsm->total_len)) -+ { -+ grub_dprintf ("net", "IP reassembly size underflow\n"); -+ return GRUB_ERR_NONE; -+ } -+ - rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len); - if (!rsm->asm_netbuff) - { diff --git a/SOURCES/0252-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch b/SOURCES/0252-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch new file mode 100644 index 0000000..ef51214 --- /dev/null +++ b/SOURCES/0252-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 25 Mar 2022 15:40:12 -0400 +Subject: [PATCH] pe: add the DOS header struct and fix some bad naming. + +In order to properly validate a loaded kernel's support for being loaded +without a writable stack or executable, we need to be able to properly +parse arbitrary PE headers. + +Currently, pe32.h is written in such a way that the MS-DOS header that +tells us where to find the PE header in the binary can't be accessed. +Further, for some reason it calls the DOS MZ magic "GRUB_PE32_MAGIC". + +This patch adds the structure for the DOS header, renames the DOS magic +define, and adds defines for the actual PE magic. + +Signed-off-by: Peter Jones +--- + grub-core/loader/arm64/linux.c | 2 +- + include/grub/efi/pe32.h | 28 ++++++++++++++++++++++++++-- + 2 files changed, 27 insertions(+), 3 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index d2af47c2c0..cc67f43906 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -58,7 +58,7 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) + if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) + return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); + +- if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC) ++ if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); + +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index a43adf2746..2a5e1ee003 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -46,7 +46,30 @@ + + #define GRUB_PE32_MSDOS_STUB_SIZE 0x80 + +-#define GRUB_PE32_MAGIC 0x5a4d ++#define GRUB_DOS_MAGIC 0x5a4d ++ ++struct grub_dos_header ++{ ++ grub_uint16_t magic; ++ grub_uint16_t cblp; ++ grub_uint16_t cp; ++ grub_uint16_t crlc; ++ grub_uint16_t cparhdr; ++ grub_uint16_t minalloc; ++ grub_uint16_t maxalloc; ++ grub_uint16_t ss; ++ grub_uint16_t sp; ++ grub_uint16_t csum; ++ grub_uint16_t ip; ++ grub_uint16_t cs; ++ grub_uint16_t lfarlc; ++ grub_uint16_t ovno; ++ grub_uint16_t res0[4]; ++ grub_uint16_t oemid; ++ grub_uint16_t oeminfo; ++ grub_uint16_t res1[10]; ++ grub_uint32_t lfanew; ++}; + + /* According to the spec, the minimal alignment is 512 bytes... + But some examples (such as EFI drivers in the Intel +@@ -280,7 +303,8 @@ struct grub_pe32_section_table + + + +-#define GRUB_PE32_SIGNATURE_SIZE 4 ++#define GRUB_PE32_SIGNATURE_SIZE 4 ++#define GRUB_PE32_SIGNATURE "PE\0\0" + + struct grub_pe32_header + { diff --git a/SOURCES/0253-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch b/SOURCES/0253-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch new file mode 100644 index 0000000..c6688cd --- /dev/null +++ b/SOURCES/0253-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 9 Feb 2022 16:08:20 -0500 +Subject: [PATCH] EFI: allocate kernel in EFI_RUNTIME_SERVICES_CODE instead of + EFI_LOADER_DATA. + +On some of the firmwares with more security mitigations, EFI_LOADER_DATA +doesn't get you executable memory, and we take a fault and reboot when +we enter kernel. + +This patch correctly allocates the kernel code as EFI_RUNTIME_SERVICES_CODE +rather than EFI_LOADER_DATA. + +Signed-off-by: Peter Jones +[rharwood: use kernel_size] +Signed-off-by: Robbie Harwood +--- + grub-core/loader/i386/efi/linux.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 9e5c11ac69..92b2fb5091 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -86,7 +86,9 @@ kernel_free(void *addr, grub_efi_uintn_t size) + } + + static void * +-kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) ++kernel_alloc(grub_efi_uintn_t size, ++ grub_efi_memory_type_t memtype, ++ const char * const errmsg) + { + void *addr = 0; + unsigned int i; +@@ -112,7 +114,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) + prev_max = max; + addr = grub_efi_allocate_pages_real (max, pages, + max_addresses[i].alloc_type, +- GRUB_EFI_LOADER_DATA); ++ memtype); + if (addr) + grub_dprintf ("linux", "Allocated at %p\n", addr); + } +@@ -242,7 +244,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + } + +- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); ++ initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, ++ N_("can't allocate initrd")); + if (initrd_mem == NULL) + goto fail; + grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); +@@ -393,7 +396,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + +- params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); ++ params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, ++ "cannot allocate kernel parameters"); + if (!params) + goto fail; + grub_dprintf ("linux", "params = %p\n", params); +@@ -415,7 +419,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "new lh is at %p\n", lh); + + grub_dprintf ("linux", "setting up cmdline\n"); +- cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); ++ cmdline = kernel_alloc (lh->cmdline_size + 1, ++ GRUB_EFI_RUNTIME_SERVICES_DATA, ++ N_("can't allocate cmdline")); + if (!cmdline) + goto fail; + grub_dprintf ("linux", "cmdline = %p\n", cmdline); +@@ -461,7 +467,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + kernel_size = lh->init_size; +- kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); ++ kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, ++ N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) + goto fail; diff --git a/SOURCES/0253-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch b/SOURCES/0253-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch deleted file mode 100644 index 96c5361..0000000 --- a/SOURCES/0253-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Thu, 16 Sep 2021 01:29:54 +1000 -Subject: [PATCH] net/dns: Fix double-free addresses on corrupt DNS response - -grub_net_dns_lookup() takes as inputs a pointer to an array of addresses -("addresses") for the given name, and pointer to a number of addresses -("naddresses"). grub_net_dns_lookup() is responsible for allocating -"addresses", and the caller is responsible for freeing it if -"naddresses" > 0. - -The DNS recv_hook will sometimes set and free the addresses array, -for example if the packet is too short: - - if (ptr + 10 >= nb->tail) - { - if (!*data->naddresses) - grub_free (*data->addresses); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - -Later on the nslookup command code unconditionally frees the "addresses" -array. Normally this is fine: the array is either populated with valid -data or is NULL. But in these sorts of error cases it is neither NULL -nor valid and we get a double-free. - -Only free "addresses" if "naddresses" > 0. - -It looks like the other use of grub_net_dns_lookup() is not affected. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit eb2e69fcf51307757e43f55ee8c9354d1ee42dd1) -(cherry picked from commit d801a27e7acec6c1a83067fab0bb975877eaf704) ---- - grub-core/net/dns.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c -index 906ec7d678..135faac035 100644 ---- a/grub-core/net/dns.c -+++ b/grub-core/net/dns.c -@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)), - grub_net_addr_to_str (&addresses[i], buf); - grub_printf ("%s\n", buf); - } -- grub_free (addresses); - if (naddresses) -- return GRUB_ERR_NONE; -+ { -+ grub_free (addresses); -+ return GRUB_ERR_NONE; -+ } - return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found")); - } - diff --git a/SOURCES/0254-modules-load-module-sections-at-page-aligned-address.patch b/SOURCES/0254-modules-load-module-sections-at-page-aligned-address.patch new file mode 100644 index 0000000..eb171f5 --- /dev/null +++ b/SOURCES/0254-modules-load-module-sections-at-page-aligned-address.patch @@ -0,0 +1,378 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 17:45:40 -0400 +Subject: [PATCH] modules: load module sections at page-aligned addresses + +Currently we load module sections at whatever alignment gcc+ld happened +to dump into the ELF section header, which is often pretty useless. For +example, by default time.mod has these sections on a current x86_64 +build: + +$ eu-readelf -a grub-core/time.mod |& grep ^Section -A13 +Section Headers: +[Nr] Name Type Addr Off Size ES Flags Lk Inf Al +[ 0] NULL 0 00000000 00000000 0 0 0 0 +[ 1] .text PROGBITS 0 00000040 0000015e 0 AX 0 0 1 +[ 2] .rela.text RELA 0 00000458 000001e0 24 I 8 1 8 +[ 3] .rodata.str1.1 PROGBITS 0 0000019e 000000a1 1 AMS 0 0 1 +[ 4] .module_license PROGBITS 0 00000240 0000000f 0 A 0 0 8 +[ 5] .data PROGBITS 0 0000024f 00000000 0 WA 0 0 1 +[ 6] .bss NOBITS 0 00000250 00000008 0 WA 0 0 8 +[ 7] .modname PROGBITS 0 00000250 00000005 0 0 0 1 +[ 8] .symtab SYMTAB 0 00000258 00000150 24 9 6 8 +[ 9] .strtab STRTAB 0 000003a8 000000ab 0 0 0 1 +[10] .shstrtab STRTAB 0 00000638 00000059 0 0 0 1 + +With NX protections being page based, loading sections with either a 1 +or 8 *byte* alignment does absolutely nothing to help us out. + +This patch switches most EFI platforms to load module sections at 4kB +page-aligned addresses. To do so, it adds an new per-arch function, +grub_arch_dl_min_alignment(), which returns the alignment needed for +dynamically loaded sections (in bytes). Currently it sets it to 4096 +when GRUB_MACHINE_EFI is true on x86_64, i386, arm, arm64, and emu, and +1-byte alignment on everything else. + +It then changes the allocation size computation and the loader code in +grub_dl_load_segments() to align the locations and sizes up to these +boundaries, and fills any added padding with zeros. + +All of this happens before relocations are applied, so the relocations +factor that in with no change. + +As an aside, initially Daniel Kiper and I thought that it might be a +better idea to split the modules up into top-level sections as +.text.modules, .rodata.modules, .data.modules, etc., so that their page +permissions would get set by the loader that's loading grub itself. +This turns out to have two significant downsides: 1) either in mkimage +or in grub_dl_relocate_symbols(), you wind up having to dynamically +process the relocations to accommodate the moved module sections, and 2) +you then need to change the permissions on the modules and change them +back while relocating them in grub_dl_relocate_symbols(), which means +that any loader that /does/ honor the section flags but does /not/ +generally support NX with the memory attributes API will cause grub to +fail. + +Signed-off-by: Peter Jones +--- + grub-core/kern/arm/dl.c | 13 +++++++++++++ + grub-core/kern/arm64/dl.c | 13 +++++++++++++ + grub-core/kern/dl.c | 29 +++++++++++++++++++++-------- + grub-core/kern/emu/full.c | 13 +++++++++++++ + grub-core/kern/i386/dl.c | 13 +++++++++++++ + grub-core/kern/ia64/dl.c | 9 +++++++++ + grub-core/kern/mips/dl.c | 8 ++++++++ + grub-core/kern/powerpc/dl.c | 9 +++++++++ + grub-core/kern/riscv/dl.c | 13 +++++++++++++ + grub-core/kern/sparc64/dl.c | 9 +++++++++ + grub-core/kern/x86_64/dl.c | 13 +++++++++++++ + include/grub/dl.h | 2 ++ + docs/grub-dev.texi | 6 +++--- + 13 files changed, 139 insertions(+), 11 deletions(-) + +diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c +index eab9d17ff2..9260737936 100644 +--- a/grub-core/kern/arm/dl.c ++++ b/grub-core/kern/arm/dl.c +@@ -278,3 +278,16 @@ grub_arch_dl_check_header (void *ehdr) + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c +index 512e5a80b0..0d4a26857f 100644 +--- a/grub-core/kern/arm64/dl.c ++++ b/grub-core/kern/arm64/dl.c +@@ -196,3 +196,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index aef8af8aa7..8c7aacef39 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -277,7 +277,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + { + unsigned i; + const Elf_Shdr *s; +- grub_size_t tsize = 0, talign = 1; ++ grub_size_t tsize = 0, talign = 1, arch_addralign = 1; + #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) + grub_size_t tramp; + grub_size_t got; +@@ -285,16 +285,24 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + #endif + char *ptr; + ++ arch_addralign = grub_arch_dl_min_alignment (); ++ + for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) + { ++ grub_size_t sh_addralign; ++ grub_size_t sh_size; ++ + if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) + continue; + +- tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; +- if (talign < s->sh_addralign) +- talign = s->sh_addralign; ++ sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); ++ sh_size = ALIGN_UP(s->sh_size, sh_addralign); ++ ++ tsize = ALIGN_UP (tsize, sh_addralign) + sh_size; ++ if (talign < sh_addralign) ++ talign = sh_addralign; + } + + #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) +@@ -323,6 +331,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + i < e->e_shnum; + i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) + { ++ grub_size_t sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); ++ grub_size_t sh_size = ALIGN_UP(s->sh_size, sh_addralign); ++ + if (s->sh_flags & SHF_ALLOC) + { + grub_dl_segment_t seg; +@@ -335,17 +346,19 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + { + void *addr; + +- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign); ++ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign); + addr = ptr; +- ptr += s->sh_size; ++ ptr += sh_size; + + switch (s->sh_type) + { + case SHT_PROGBITS: + grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size); ++ grub_memset ((char *)addr + s->sh_size, 0, ++ sh_size - s->sh_size); + break; + case SHT_NOBITS: +- grub_memset (addr, 0, s->sh_size); ++ grub_memset (addr, 0, sh_size); + break; + } + +@@ -354,7 +367,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + else + seg->addr = 0; + +- seg->size = s->sh_size; ++ seg->size = sh_size; + seg->section = i; + seg->next = mod->segment; + mod->segment = seg; +diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c +index e8d63b1f5f..1de1c28eb0 100644 +--- a/grub-core/kern/emu/full.c ++++ b/grub-core/kern/emu/full.c +@@ -67,3 +67,16 @@ grub_arch_dl_init_linker (void) + } + #endif + ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c +index 1346da5cc9..d6b4681fc9 100644 +--- a/grub-core/kern/i386/dl.c ++++ b/grub-core/kern/i386/dl.c +@@ -79,3 +79,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c +index db59300fea..92d82c5750 100644 +--- a/grub-core/kern/ia64/dl.c ++++ b/grub-core/kern/ia64/dl.c +@@ -148,3 +148,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + } + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c +index 5d7d299c74..6d83bd71e9 100644 +--- a/grub-core/kern/mips/dl.c ++++ b/grub-core/kern/mips/dl.c +@@ -272,3 +272,11 @@ grub_arch_dl_init_linker (void) + grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0); + } + ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c +index cdd61b305f..5d9ba2e158 100644 +--- a/grub-core/kern/powerpc/dl.c ++++ b/grub-core/kern/powerpc/dl.c +@@ -167,3 +167,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c +index f26b12aaa4..aa18f9e990 100644 +--- a/grub-core/kern/riscv/dl.c ++++ b/grub-core/kern/riscv/dl.c +@@ -343,3 +343,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c +index f3d960186b..f054f08241 100644 +--- a/grub-core/kern/sparc64/dl.c ++++ b/grub-core/kern/sparc64/dl.c +@@ -189,3 +189,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++ return 1; ++} +diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c +index e5a8bdcf4f..a105dc50ce 100644 +--- a/grub-core/kern/x86_64/dl.c ++++ b/grub-core/kern/x86_64/dl.c +@@ -119,3 +119,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + + return GRUB_ERR_NONE; + } ++ ++/* ++ * Tell the loader what our minimum section alignment is. ++ */ ++grub_size_t ++grub_arch_dl_min_alignment (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ return 4096; ++#else ++ return 1; ++#endif ++} +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 618ae6f474..f36ed5cb17 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -280,6 +280,8 @@ grub_err_t grub_arch_dl_check_header (void *ehdr); + grub_err_t + grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg); ++grub_size_t ++grub_arch_dl_min_alignment (void); + #endif + + #if defined (_mips) +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi +index 19f708ee66..7b2455a8fe 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -755,9 +755,9 @@ declare startup asm file ($cpu_$platform_startup) as well as any other files + (e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c). + At this stage you will also need to add dummy dl.c and cache.S with functions + grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t +-grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and +-void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They +-won't be used for now. ++grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c), grub_uint32_t ++grub_arch_dl_min_alignment (void), and void grub_arch_sync_caches (void ++*address, grub_size_t len) (cache.S). They won't be used for now. + + You will need to create directory include/$cpu/$platform and a file + include/$cpu/types.h. The later folowing this template: diff --git a/SOURCES/0254-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch b/SOURCES/0254-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch deleted file mode 100644 index 8451c19..0000000 --- a/SOURCES/0254-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 20 Dec 2021 21:55:43 +1100 -Subject: [PATCH] net/dns: Don't read past the end of the string we're checking - against - -I don't really understand what's going on here but fuzzing found -a bug where we read past the end of check_with. That's a C string, -so use grub_strlen() to make sure we don't overread it. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 6a97b3f4b1d5173aa516edc6dedbc63de7306d21) -(cherry picked from commit e0589624e86bc96666cbdb62f6e55cafec2871b3) ---- - grub-core/net/dns.c | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - -diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c -index 135faac035..17961a9f18 100644 ---- a/grub-core/net/dns.c -+++ b/grub-core/net/dns.c -@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, - int *length, char *set) - { - const char *readable_ptr = check_with; -+ int readable_len; - const grub_uint8_t *ptr; - char *optr = set; - int bytes_processed = 0; - if (length) - *length = 0; -+ -+ if (readable_ptr != NULL) -+ readable_len = grub_strlen (readable_ptr); -+ else -+ readable_len = 0; -+ - for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; ) - { - /* End marker. */ -@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, - ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]); - continue; - } -- if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) -+ if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)) - return 0; - if (grub_memchr (ptr + 1, 0, *ptr) - || grub_memchr (ptr + 1, '.', *ptr)) - return 0; - if (readable_ptr) -- readable_ptr += *ptr; -+ { -+ readable_ptr += *ptr; -+ readable_len -= *ptr; -+ } - if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0) - return 0; - bytes_processed += *ptr + 1; -@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, - if (optr) - *optr++ = '.'; - if (readable_ptr && *readable_ptr) -- readable_ptr++; -+ { -+ readable_ptr++; -+ readable_len--; -+ } - ptr += *ptr + 1; - } - return 0; diff --git a/SOURCES/0255-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch b/SOURCES/0255-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch deleted file mode 100644 index dba4ca7..0000000 --- a/SOURCES/0255-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Mon, 20 Sep 2021 01:12:24 +1000 -Subject: [PATCH] net/tftp: Prevent a UAF and double-free from a failed seek - -A malicious tftp server can cause UAFs and a double free. - -An attempt to read from a network file is handled by grub_net_fs_read(). If -the read is at an offset other than the current offset, grub_net_seek_real() -is invoked. - -In grub_net_seek_real(), if a backwards seek cannot be satisfied from the -currently received packets, and the underlying transport does not provide -a seek method, then grub_net_seek_real() will close and reopen the network -protocol layer. - -For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t -file->data. The file->data pointer is not nulled out after the free. - -If the ->open() call fails, the file->data will not be reallocated and will -continue point to a freed memory block. This could happen from a server -refusing to send the requisite ack to the new tftp request, for example. - -The seek and the read will then fail, but the grub_file continues to exist: -the failed seek does not necessarily cause the entire file to be thrown -away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc., -a read failure is interpreted as a decompressor passing on the file, not as -an invalidation of the entire grub_file_t structure). - -This means subsequent attempts to read or seek the file will use the old -file->data after free. Eventually, the file will be close()d again and -file->data will be freed again. - -Mark a net_fs file that doesn't reopen as broken. Do not permit read() or -close() on a broken file (seek is not exposed directly to the file API - -it is only called as part of read, so this blocks seeks as well). - -As an additional defence, null out the ->data pointer if tftp_open() fails. -That would have lead to a simple null pointer dereference rather than -a mess of UAFs. - -This may affect other protocols, I haven't checked. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit dada1dda695439bb55b2848dddc2d89843552f81) -(cherry picked from commit 352c5ae8a9fc715712e6ecbd7ccb6218122c748f) ---- - grub-core/net/net.c | 11 +++++++++-- - grub-core/net/tftp.c | 1 + - include/grub/net.h | 1 + - 3 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/net.c b/grub-core/net/net.c -index 55aed92722..1001c611d1 100644 ---- a/grub-core/net/net.c -+++ b/grub-core/net/net.c -@@ -1625,7 +1625,8 @@ grub_net_fs_close (grub_file_t file) - grub_netbuff_free (file->device->net->packs.first->nb); - grub_net_remove_packet (file->device->net->packs.first); - } -- file->device->net->protocol->close (file); -+ if (!file->device->net->broken) -+ file->device->net->protocol->close (file); - grub_free (file->device->net->name); - return GRUB_ERR_NONE; - } -@@ -1847,7 +1848,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) - file->device->net->stall = 0; - err = file->device->net->protocol->open (file, file->device->net->name); - if (err) -- return err; -+ { -+ file->device->net->broken = 1; -+ return err; -+ } - grub_net_fs_read_real (file, NULL, offset); - return grub_errno; - } -@@ -1856,6 +1860,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) - static grub_ssize_t - grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) - { -+ if (file->device->net->broken) -+ return -1; -+ - if (file->offset != file->device->net->offset) - { - grub_err_t err; -diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c -index d54b13f09f..788ad1dc44 100644 ---- a/grub-core/net/tftp.c -+++ b/grub-core/net/tftp.c -@@ -408,6 +408,7 @@ tftp_open (struct grub_file *file, const char *filename) - { - grub_net_udp_close (data->sock); - grub_free (data); -+ file->data = NULL; - return grub_errno; - } - -diff --git a/include/grub/net.h b/include/grub/net.h -index 42af7de250..9e4898cc6b 100644 ---- a/include/grub/net.h -+++ b/include/grub/net.h -@@ -280,6 +280,7 @@ typedef struct grub_net - grub_fs_t fs; - int eof; - int stall; -+ int broken; - } *grub_net_t; - - extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); diff --git a/SOURCES/0255-nx-add-memory-attribute-get-set-API.patch b/SOURCES/0255-nx-add-memory-attribute-get-set-API.patch new file mode 100644 index 0000000..91c9d2f --- /dev/null +++ b/SOURCES/0255-nx-add-memory-attribute-get-set-API.patch @@ -0,0 +1,317 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 22 Mar 2022 10:56:21 -0400 +Subject: [PATCH] nx: add memory attribute get/set API + +For NX, we need to set the page access permission attributes for write +and execute permissions. + +This patch adds two new primitives, grub_set_mem_attrs() and +grub_clear_mem_attrs(), and associated constant definitions, to be used +for that purpose. + +For most platforms, it adds a dummy implementation that returns +GRUB_ERR_NONE. On EFI platforms, it adds a common helper function, +grub_efi_status_to_err(), which translates EFI error codes to grub error +codes, adds headers for the EFI Memory Attribute Protocol (still pending +standardization), and an implementation of the grub nx primitives using +it. + +Signed-off-by: Peter Jones +[rharwood: add pjones's none/nyi fixup] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/efi/efi.c | 36 +++++++++++++ + grub-core/kern/efi/mm.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ + include/grub/efi/api.h | 25 +++++++++ + include/grub/efi/efi.h | 2 + + include/grub/mm.h | 32 ++++++++++++ + 5 files changed, 226 insertions(+) + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 7fcca69c17..4ac2b2754e 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -1096,3 +1096,39 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, + + return 0; + } ++ ++grub_err_t ++grub_efi_status_to_err (grub_efi_status_t status) ++{ ++ grub_err_t err; ++ switch (status) ++ { ++ case GRUB_EFI_SUCCESS: ++ err = GRUB_ERR_NONE; ++ break; ++ case GRUB_EFI_INVALID_PARAMETER: ++ default: ++ err = GRUB_ERR_BAD_ARGUMENT; ++ break; ++ case GRUB_EFI_OUT_OF_RESOURCES: ++ err = GRUB_ERR_OUT_OF_MEMORY; ++ break; ++ case GRUB_EFI_DEVICE_ERROR: ++ err = GRUB_ERR_IO; ++ break; ++ case GRUB_EFI_WRITE_PROTECTED: ++ err = GRUB_ERR_WRITE_ERROR; ++ break; ++ case GRUB_EFI_SECURITY_VIOLATION: ++ err = GRUB_ERR_ACCESS_DENIED; ++ break; ++ case GRUB_EFI_NOT_FOUND: ++ err = GRUB_ERR_FILE_NOT_FOUND; ++ break; ++ case GRUB_EFI_ABORTED: ++ err = GRUB_ERR_WAIT; ++ break; ++ } ++ ++ return err; ++} +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index e84961d078..2c33758ed7 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -738,3 +738,134 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) + return GRUB_ERR_NONE; + } + #endif ++ ++static inline grub_uint64_t ++grub_mem_attrs_to_uefi_mem_attrs (grub_uint64_t attrs) ++{ ++ grub_uint64_t ret = GRUB_EFI_MEMORY_RP | ++ GRUB_EFI_MEMORY_RO | ++ GRUB_EFI_MEMORY_XP; ++ ++ if (attrs & GRUB_MEM_ATTR_R) ++ ret &= ~GRUB_EFI_MEMORY_RP; ++ ++ if (attrs & GRUB_MEM_ATTR_W) ++ ret &= ~GRUB_EFI_MEMORY_RO; ++ ++ if (attrs & GRUB_MEM_ATTR_X) ++ ret &= ~GRUB_EFI_MEMORY_XP; ++ ++ return ret; ++} ++ ++static inline grub_uint64_t ++uefi_mem_attrs_to_grub_mem_attrs (grub_uint64_t attrs) ++{ ++ grub_uint64_t ret = GRUB_MEM_ATTR_R | ++ GRUB_MEM_ATTR_W | ++ GRUB_MEM_ATTR_X; ++ ++ if (attrs & GRUB_EFI_MEMORY_RP) ++ ret &= ~GRUB_MEM_ATTR_R; ++ ++ if (attrs & GRUB_EFI_MEMORY_RO) ++ ret &= ~GRUB_MEM_ATTR_W; ++ ++ if (attrs & GRUB_EFI_MEMORY_XP) ++ ret &= ~GRUB_MEM_ATTR_X; ++ ++ return ret; ++} ++ ++grub_err_t ++grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_uint64_t *attrs) ++{ ++ grub_efi_memory_attribute_protocol_t *proto; ++ grub_efi_physical_address_t physaddr = addr; ++ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; ++ grub_efi_status_t efi_status; ++ ++ proto = grub_efi_locate_protocol (&protocol_guid, 0); ++ if (!proto) ++ return GRUB_ERR_NOT_IMPLEMENTED_YET; ++ ++ if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL) ++ { ++ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" and attrs %p\n", ++ __func__, physaddr, physaddr+size-1, attrs); ++ return 0; ++ } ++ ++ efi_status = efi_call_4(proto->get_memory_attributes, ++ proto, physaddr, size, attrs); ++ *attrs = uefi_mem_attrs_to_grub_mem_attrs (*attrs); ++ ++ return grub_efi_status_to_err (efi_status); ++} ++ ++grub_err_t ++grub_update_mem_attrs (grub_addr_t addr, grub_size_t size, ++ grub_uint64_t set_attrs, grub_uint64_t clear_attrs) ++{ ++ grub_efi_memory_attribute_protocol_t *proto; ++ grub_efi_physical_address_t physaddr = addr; ++ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; ++ grub_efi_status_t efi_status = GRUB_EFI_SUCCESS; ++ grub_uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs; ++ grub_err_t err; ++ ++ proto = grub_efi_locate_protocol (&protocol_guid, 0); ++ if (!proto) ++ return GRUB_ERR_NONE; ++ ++ err = grub_get_mem_attrs (addr, size, &before); ++ if (err) ++ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", ++ addr, size, &before, err); ++ ++ if (physaddr & 0xfff || size & 0xfff || size == 0) ++ { ++ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" +%s%s%s -%s%s%s\n", ++ __func__, physaddr, physaddr + size - 1, ++ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); ++ return 0; ++ } ++ ++ uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs); ++ grub_dprintf ("nx", "translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs); ++ uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs); ++ grub_dprintf ("nx", "translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs); ++ if (uefi_set_attrs) ++ efi_status = efi_call_4(proto->set_memory_attributes, ++ proto, physaddr, size, uefi_set_attrs); ++ if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs) ++ efi_status = efi_call_4(proto->clear_memory_attributes, ++ proto, physaddr, size, uefi_clear_attrs); ++ ++ err = grub_get_mem_attrs (addr, size, &after); ++ if (err) ++ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", ++ addr, size, &after, err); ++ ++ grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" before:%c%c%c after:%c%c%c\n", ++ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ addr, addr + size - 1, ++ (before & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (before & GRUB_MEM_ATTR_W) ? 'w' : '-', ++ (before & GRUB_MEM_ATTR_X) ? 'x' : '-', ++ (after & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (after & GRUB_MEM_ATTR_W) ? 'w' : '-', ++ (after & GRUB_MEM_ATTR_X) ? 'x' : '-'); ++ ++ return grub_efi_status_to_err (efi_status); ++} +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index f431f49973..464842ba37 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -363,6 +363,11 @@ + { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ + } + ++#define GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID \ ++ { 0xf4560cf6, 0x40ec, 0x4b4a, \ ++ { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \ ++ } ++ + struct grub_efi_sal_system_table + { + grub_uint32_t signature; +@@ -2102,6 +2107,26 @@ struct grub_efi_ip6_config_manual_address { + }; + typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; + ++struct grub_efi_memory_attribute_protocol ++{ ++ grub_efi_status_t (*get_memory_attributes) ( ++ struct grub_efi_memory_attribute_protocol *this, ++ grub_efi_physical_address_t base_address, ++ grub_efi_uint64_t length, ++ grub_efi_uint64_t *attributes); ++ grub_efi_status_t (*set_memory_attributes) ( ++ struct grub_efi_memory_attribute_protocol *this, ++ grub_efi_physical_address_t base_address, ++ grub_efi_uint64_t length, ++ grub_efi_uint64_t attributes); ++ grub_efi_status_t (*clear_memory_attributes) ( ++ struct grub_efi_memory_attribute_protocol *this, ++ grub_efi_physical_address_t base_address, ++ grub_efi_uint64_t length, ++ grub_efi_uint64_t attributes); ++}; ++typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t; ++ + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ + || defined(__riscv) +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index ec52083c49..34825c4adc 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -164,4 +164,6 @@ struct grub_net_card; + grub_efi_handle_t + grub_efinet_get_device_handle (struct grub_net_card *card); + ++grub_err_t EXPORT_FUNC(grub_efi_status_to_err) (grub_efi_status_t status); ++ + #endif /* ! GRUB_EFI_EFI_HEADER */ +diff --git a/include/grub/mm.h b/include/grub/mm.h +index 9c38dd3ca5..d81623d226 100644 +--- a/include/grub/mm.h ++++ b/include/grub/mm.h +@@ -22,6 +22,7 @@ + + #include + #include ++#include + #include + + #ifndef NULL +@@ -38,6 +39,37 @@ void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size); + void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size); + #endif + ++#define GRUB_MEM_ATTR_R 0x0000000000000004LLU ++#define GRUB_MEM_ATTR_W 0x0000000000000002LLU ++#define GRUB_MEM_ATTR_X 0x0000000000000001LLU ++ ++#ifdef GRUB_MACHINE_EFI ++grub_err_t EXPORT_FUNC(grub_get_mem_attrs) (grub_addr_t addr, ++ grub_size_t size, ++ grub_uint64_t *attrs); ++grub_err_t EXPORT_FUNC(grub_update_mem_attrs) (grub_addr_t addr, ++ grub_size_t size, ++ grub_uint64_t set_attrs, ++ grub_uint64_t clear_attrs); ++#else /* !GRUB_MACHINE_EFI */ ++static inline grub_err_t ++grub_get_mem_attrs (grub_addr_t addr __attribute__((__unused__)), ++ grub_size_t size __attribute__((__unused__)), ++ grub_uint64_t *attrs __attribute__((__unused__))) ++{ ++ return GRUB_ERR_NONE; ++} ++ ++static inline grub_err_t ++grub_update_mem_attrs (grub_addr_t addr __attribute__((__unused__)), ++ grub_size_t size __attribute__((__unused__)), ++ grub_uint64_t set_attrs __attribute__((__unused__)), ++ grub_uint64_t clear_attrs __attribute__((__unused__))) ++{ ++ return GRUB_ERR_NONE; ++} ++#endif /* GRUB_MACHINE_EFI */ ++ + void grub_mm_check_real (const char *file, int line); + #define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__); + diff --git a/SOURCES/0256-net-tftp-Avoid-a-trivial-UAF.patch b/SOURCES/0256-net-tftp-Avoid-a-trivial-UAF.patch deleted file mode 100644 index 09a583a..0000000 --- a/SOURCES/0256-net-tftp-Avoid-a-trivial-UAF.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 18 Jan 2022 14:29:20 +1100 -Subject: [PATCH] net/tftp: Avoid a trivial UAF - -Under tftp errors, we print a tftp error message from the tftp header. -However, the tftph pointer is a pointer inside nb, the netbuff. Previously, -we were freeing the nb and then dereferencing it. Don't do that, use it -and then free it later. - -This isn't really _bad_ per se, especially as we're single-threaded, but -it trips up fuzzers. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 956f4329cec23e4375182030ca9b2be631a61ba5) -(cherry picked from commit dbe9abcdee6ce796811111b67e3f24eefe2135d1) ---- - grub-core/net/tftp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c -index 788ad1dc44..a95766dcbd 100644 ---- a/grub-core/net/tftp.c -+++ b/grub-core/net/tftp.c -@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), - return GRUB_ERR_NONE; - case TFTP_ERROR: - data->have_oack = 1; -- grub_netbuff_free (nb); - grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg); - grub_error_save (&data->save_err); -+ grub_netbuff_free (nb); - return GRUB_ERR_NONE; - default: - grub_netbuff_free (nb); diff --git a/SOURCES/0256-nx-set-page-permissions-for-loaded-modules.patch b/SOURCES/0256-nx-set-page-permissions-for-loaded-modules.patch new file mode 100644 index 0000000..9e0aebb --- /dev/null +++ b/SOURCES/0256-nx-set-page-permissions-for-loaded-modules.patch @@ -0,0 +1,263 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 21 Mar 2022 17:46:35 -0400 +Subject: [PATCH] nx: set page permissions for loaded modules. + +For NX, we need to set write and executable permissions on the sections +of grub modules when we load them. + +On sections with SHF_ALLOC set, which is typically everything except +.modname and the symbol and string tables, this patch clears the Read +Only flag on sections that have the ELF flag SHF_WRITE set, and clears +the No eXecute flag on sections with SHF_EXECINSTR set. In all other +cases it sets both flags. + +Signed-off-by: Peter Jones +[rharwood: arm tgptr -> tgaddr] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/dl.c | 120 +++++++++++++++++++++++++++++++++++++++------------- + include/grub/dl.h | 44 +++++++++++++++++++ + 2 files changed, 134 insertions(+), 30 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 8c7aacef39..d5de80186f 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -285,6 +285,8 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + #endif + char *ptr; + ++ grub_dprintf ("modules", "loading segments for \"%s\"\n", mod->name); ++ + arch_addralign = grub_arch_dl_min_alignment (); + + for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); +@@ -384,6 +386,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) + ptr += got; + #endif + ++ grub_dprintf ("modules", "done loading segments for \"%s\"\n", mod->name); + return GRUB_ERR_NONE; + } + +@@ -517,23 +520,6 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name) + return s; + return NULL; + } +-static long +-grub_dl_find_section_index (Elf_Ehdr *e, const char *name) +-{ +- Elf_Shdr *s; +- const char *str; +- unsigned i; +- +- s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); +- str = (char *) e + s->sh_offset; +- +- for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); +- i < e->e_shnum; +- i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) +- if (grub_strcmp (str + s->sh_name, name) == 0) +- return (long)i; +- return -1; +-} + + /* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. +@@ -662,6 +648,7 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) + Elf_Shdr *s; + unsigned i; + ++ grub_dprintf ("modules", "relocating symbols for \"%s\"\n", mod->name); + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) +@@ -670,24 +657,95 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) + grub_dl_segment_t seg; + grub_err_t err; + +- /* Find the target segment. */ +- for (seg = mod->segment; seg; seg = seg->next) +- if (seg->section == s->sh_info) +- break; ++ seg = grub_dl_find_segment(mod, s->sh_info); ++ if (!seg) ++ continue; + +- if (seg) +- { +- if (!mod->symtab) +- return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); ++ if (!mod->symtab) ++ return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); + +- err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); +- if (err) +- return err; +- } ++ err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); ++ if (err) ++ return err; + } + ++ grub_dprintf ("modules", "done relocating symbols for \"%s\"\n", mod->name); + return GRUB_ERR_NONE; + } ++ ++static grub_err_t ++grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr) ++{ ++ unsigned i; ++ const Elf_Shdr *s; ++ const Elf_Ehdr *e = ehdr; ++#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) ++ grub_size_t arch_addralign = grub_arch_dl_min_alignment (); ++ grub_addr_t tgaddr; ++ grub_uint64_t tgsz; ++#endif ++ ++ grub_dprintf ("modules", "updating memory attributes for \"%s\"\n", ++ mod->name); ++ for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); ++ i < e->e_shnum; ++ i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) ++ { ++ grub_dl_segment_t seg; ++ grub_uint64_t set_attrs = GRUB_MEM_ATTR_R; ++ grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X; ++ ++ seg = grub_dl_find_segment(mod, i); ++ if (!seg) ++ continue; ++ ++ if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC)) ++ continue; ++ ++ if (s->sh_flags & SHF_WRITE) ++ { ++ set_attrs |= GRUB_MEM_ATTR_W; ++ clear_attrs &= ~GRUB_MEM_ATTR_W; ++ } ++ ++ if (s->sh_flags & SHF_EXECINSTR) ++ { ++ set_attrs |= GRUB_MEM_ATTR_X; ++ clear_attrs &= ~GRUB_MEM_ATTR_X; ++ } ++ ++ grub_dprintf ("modules", "setting memory attrs for section \"%s\" to -%s%s%s+%s%s%s\n", ++ grub_dl_get_section_name(e, s), ++ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", ++ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", ++ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", ++ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); ++ grub_update_mem_attrs ((grub_addr_t)(seg->addr), seg->size, set_attrs, clear_attrs); ++ } ++ ++#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) ++ tgaddr = grub_min((grub_addr_t)mod->tramp, (grub_addr_t)mod->got); ++ tgsz = grub_max((grub_addr_t)mod->trampptr, (grub_addr_t)mod->gotptr) - tgaddr; ++ ++ if (tgsz) ++ { ++ tgsz = ALIGN_UP(tgsz, arch_addralign); ++ ++ grub_dprintf ("modules", "updating attributes for GOT and trampolines\n", ++ mod->name); ++ grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X, ++ GRUB_MEM_ATTR_W); ++ } ++#endif ++ ++ grub_dprintf ("modules", "done updating module memory attributes for \"%s\"\n", ++ mod->name); ++ ++ return GRUB_ERR_NONE; ++} ++ + static void + grub_dl_print_gdb_info (grub_dl_t mod, Elf_Ehdr *e) + { +@@ -753,6 +811,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + mod->ref_count = 1; + + grub_dprintf ("modules", "relocating to %p\n", mod); ++ + /* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. + Modules have to be licensed under GPLv3 or GPLv3+ (optionally +@@ -766,7 +825,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + || grub_dl_resolve_dependencies (mod, e) + || grub_dl_load_segments (mod, e) + || grub_dl_resolve_symbols (mod, e) +- || grub_dl_relocate_symbols (mod, e)) ++ || grub_dl_relocate_symbols (mod, e) ++ || grub_dl_set_mem_attrs (mod, e)) + { + mod->fini = 0; + grub_dl_unload (mod); +diff --git a/include/grub/dl.h b/include/grub/dl.h +index f36ed5cb17..45ac8e339f 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #endif + + /* +@@ -268,6 +269,49 @@ grub_dl_is_persistent (grub_dl_t mod) + return mod->persistent; + } + ++static inline const char * ++grub_dl_get_section_name (const Elf_Ehdr *e, const Elf_Shdr *s) ++{ ++ Elf_Shdr *str_s; ++ const char *str; ++ ++ str_s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); ++ str = (char *) e + str_s->sh_offset; ++ ++ return str + s->sh_name; ++} ++ ++static inline long ++grub_dl_find_section_index (Elf_Ehdr *e, const char *name) ++{ ++ Elf_Shdr *s; ++ const char *str; ++ unsigned i; ++ ++ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); ++ str = (char *) e + s->sh_offset; ++ ++ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); ++ i < e->e_shnum; ++ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) ++ if (grub_strcmp (str + s->sh_name, name) == 0) ++ return (long)i; ++ return -1; ++} ++ ++/* Return the segment for a section of index N */ ++static inline grub_dl_segment_t ++grub_dl_find_segment (grub_dl_t mod, unsigned n) ++{ ++ grub_dl_segment_t seg; ++ ++ for (seg = mod->segment; seg; seg = seg->next) ++ if (seg->section == n) ++ return seg; ++ ++ return NULL; ++} ++ + #endif + + void * EXPORT_FUNC(grub_resolve_symbol) (const char *name); diff --git a/SOURCES/0257-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch b/SOURCES/0257-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch deleted file mode 100644 index cbc7162..0000000 --- a/SOURCES/0257-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 1 Mar 2022 23:14:15 +1100 -Subject: [PATCH] net/http: Do not tear down socket if it's already been torn - down - -It's possible for data->sock to get torn down in tcp error handling. -If we unconditionally tear it down again we will end up doing writes -to an offset of the NULL pointer when we go to tear it down again. - -Detect if it has been torn down and don't do it again. - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit ec233d3ecf995293304de443579aab5c46c49e85) -(cherry picked from commit d39cf87ed701b9f0900daed7f672e07994d37ce8) ---- - grub-core/net/http.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 7f878b5615..19cb8768e3 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -427,7 +427,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - return err; - } - -- for (i = 0; !data->headers_recv && i < 100; i++) -+ for (i = 0; data->sock && !data->headers_recv && i < 100; i++) - { - grub_net_tcp_retransmit (); - grub_net_poll_cards (300, &data->headers_recv); -@@ -435,7 +435,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) - - if (!data->headers_recv) - { -- grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); -+ if (data->sock) -+ grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); - if (data->err) - { - char *str = data->errmsg; diff --git a/SOURCES/0257-nx-set-attrs-in-our-kernel-loaders.patch b/SOURCES/0257-nx-set-attrs-in-our-kernel-loaders.patch new file mode 100644 index 0000000..514df1f --- /dev/null +++ b/SOURCES/0257-nx-set-attrs-in-our-kernel-loaders.patch @@ -0,0 +1,565 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 22 Mar 2022 10:57:07 -0400 +Subject: [PATCH] nx: set attrs in our kernel loaders + +For NX, our kernel loaders need to set write and execute page +permissions on allocated pages and the stack. + +This patch adds those calls. + +Signed-off-by: Peter Jones +[rharwood: fix stack_attrs undefined, fix aarch64 callsites] +Signed-off-by: Robbie Harwood +--- + grub-core/kern/efi/mm.c | 77 +++++++++++++++++ + grub-core/loader/arm64/linux.c | 16 +++- + grub-core/loader/arm64/xen_boot.c | 4 +- + grub-core/loader/efi/chainloader.c | 11 +++ + grub-core/loader/efi/linux.c | 164 ++++++++++++++++++++++++++++++++++++- + grub-core/loader/i386/efi/linux.c | 26 +++++- + grub-core/loader/i386/linux.c | 5 ++ + include/grub/efi/efi.h | 6 +- + include/grub/efi/linux.h | 16 +++- + include/grub/efi/pe32.h | 2 + + 10 files changed, 312 insertions(+), 15 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 2c33758ed7..e460b072e6 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -610,6 +610,81 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + #endif + ++grub_addr_t grub_stack_addr = (grub_addr_t)-1ll; ++grub_size_t grub_stack_size = 0; ++ ++static void ++grub_nx_init (void) ++{ ++ grub_uint64_t attrs, stack_attrs; ++ grub_err_t err; ++ grub_addr_t stack_current, stack_end; ++ const grub_uint64_t page_size = 4096; ++ const grub_uint64_t page_mask = ~(page_size - 1); ++ ++ /* ++ * These are to confirm that the flags are working as expected when ++ * debugging. ++ */ ++ attrs = 0; ++ stack_current = (grub_addr_t)grub_nx_init & page_mask; ++ err = grub_get_mem_attrs (stack_current, page_size, &attrs); ++ if (err) ++ { ++ grub_dprintf ("nx", ++ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", ++ stack_current, err); ++ grub_error_pop (); ++ } ++ else ++ grub_dprintf ("nx", "page attrs for grub_nx_init (%p) are %c%c%c\n", ++ grub_dl_load_core, ++ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); ++ ++ stack_current = (grub_addr_t)&stack_current & page_mask; ++ err = grub_get_mem_attrs (stack_current, page_size, &stack_attrs); ++ if (err) ++ { ++ grub_dprintf ("nx", ++ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", ++ stack_current, err); ++ grub_error_pop (); ++ } ++ else ++ { ++ attrs = stack_attrs; ++ grub_dprintf ("nx", "page attrs for stack (%p) are %c%c%c\n", ++ &attrs, ++ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', ++ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); ++ } ++ for (stack_end = stack_current + page_size ; ++ !(attrs & GRUB_MEM_ATTR_R); ++ stack_end += page_size) ++ { ++ err = grub_get_mem_attrs (stack_current, page_size, &attrs); ++ if (err) ++ { ++ grub_dprintf ("nx", ++ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", ++ stack_current, err); ++ grub_error_pop (); ++ break; ++ } ++ } ++ if (stack_end > stack_current) ++ { ++ grub_stack_addr = stack_current; ++ grub_stack_size = stack_end - stack_current; ++ grub_dprintf ("nx", ++ "detected stack from 0x%"PRIxGRUB_ADDR" to 0x%"PRIxGRUB_ADDR"\n", ++ grub_stack_addr, grub_stack_addr + grub_stack_size - 1); ++ } ++} ++ + void + grub_efi_mm_init (void) + { +@@ -623,6 +698,8 @@ grub_efi_mm_init (void) + grub_efi_uint64_t required_pages; + int mm_status; + ++ grub_nx_init (); ++ + /* Prepare a memory region to store two memory maps. */ + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + if (! memory_map) +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index cc67f43906..de85583487 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -172,7 +172,8 @@ free_params (void) + } + + grub_err_t +-grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) ++grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args, ++ int nx_supported) + { + grub_err_t retval; + +@@ -182,7 +183,8 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) + + grub_dprintf ("linux", "linux command line: '%s'\n", args); + +- retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr); ++ retval = grub_efi_linux_boot (addr, size, handover_offset, ++ (void *)addr, nx_supported); + + /* Never reached... */ + free_params(); +@@ -192,7 +194,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) + static grub_err_t + grub_linux_boot (void) + { +- return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args)); ++ return grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, ++ (grub_size_t)kernel_size, ++ linux_args, ++ 0); + } + + static grub_err_t +@@ -340,6 +345,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_off_t filelen; + grub_uint32_t align; + void *kernel = NULL; ++ int nx_supported = 1; + + grub_dl_ref (my_mod); + +@@ -376,6 +382,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); + grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); + ++ err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); ++ if (err != GRUB_ERR_NONE) ++ goto fail; ++ + grub_loader_unset(); + + kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); +diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c +index d9b7a9ba40..6e7e920416 100644 +--- a/grub-core/loader/arm64/xen_boot.c ++++ b/grub-core/loader/arm64/xen_boot.c +@@ -266,7 +266,9 @@ xen_boot (void) + return err; + + return grub_arch_efi_linux_boot_image (xen_hypervisor->start, +- xen_hypervisor->cmdline); ++ xen_hypervisor->size, ++ xen_hypervisor->cmdline, ++ 0); + } + + static void +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index fb874f1855..dd31ac9bb3 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -1070,6 +1070,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ /* ++ * The OS kernel is going to set its own permissions when it takes over ++ * paging a few million instructions from now, and load_image() will set up ++ * anything that's needed based on the section headers, so there's no point ++ * in doing anything but clearing the protection bits here. ++ */ ++ grub_dprintf("nx", "setting attributes for %p (%lu bytes) to %llx\n", ++ (void *)(grub_addr_t)address, fsize, 0llu); ++ grub_update_mem_attrs (address, fsize, ++ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X, 0); ++ + #if defined (__i386__) || defined (__x86_64__) + if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) + { +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 9265cf4200..277f352e0c 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -26,16 +26,127 @@ + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" ++#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" ++ ++grub_err_t ++grub_efi_check_nx_image_support (grub_addr_t kernel_addr, ++ grub_size_t kernel_size, ++ int *nx_supported) ++{ ++ struct grub_dos_header *doshdr; ++ grub_size_t sz = sizeof (*doshdr); ++ ++ struct grub_pe32_header_32 *pe32; ++ struct grub_pe32_header_64 *pe64; ++ ++ int image_is_compatible = 0; ++ int is_64_bit; ++ ++ if (kernel_size < sz) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); ++ ++ doshdr = (void *)kernel_addr; ++ ++ if ((doshdr->magic & 0xffff) != GRUB_DOS_MAGIC) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel DOS magic is invalid")); ++ ++ sz = doshdr->lfanew + sizeof (*pe32); ++ if (kernel_size < sz) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); ++ ++ pe32 = (struct grub_pe32_header_32 *)(kernel_addr + doshdr->lfanew); ++ pe64 = (struct grub_pe32_header_64 *)pe32; ++ ++ if (grub_memcmp (pe32->signature, GRUB_PE32_SIGNATURE, ++ GRUB_PE32_SIGNATURE_SIZE) != 0) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel PE magic is invalid")); ++ ++ switch (pe32->coff_header.machine) ++ { ++ case GRUB_PE32_MACHINE_ARMTHUMB_MIXED: ++ case GRUB_PE32_MACHINE_I386: ++ case GRUB_PE32_MACHINE_RISCV32: ++ is_64_bit = 0; ++ break; ++ case GRUB_PE32_MACHINE_ARM64: ++ case GRUB_PE32_MACHINE_IA64: ++ case GRUB_PE32_MACHINE_RISCV64: ++ case GRUB_PE32_MACHINE_X86_64: ++ is_64_bit = 1; ++ break; ++ default: ++ return grub_error (GRUB_ERR_BAD_OS, N_("PE machine type 0x%04hx unknown"), ++ pe32->coff_header.machine); ++ } ++ ++ if (is_64_bit) ++ { ++ sz = doshdr->lfanew + sizeof (*pe64); ++ if (kernel_size < sz) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); ++ ++ if (pe64->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) ++ image_is_compatible = 1; ++ } ++ else ++ { ++ if (pe32->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) ++ image_is_compatible = 1; ++ } ++ ++ *nx_supported = image_is_compatible; ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_efi_check_nx_required (int *nx_required) ++{ ++ grub_efi_status_t status; ++ grub_efi_guid_t guid = GRUB_EFI_SHIM_LOCK_GUID; ++ grub_size_t mok_policy_sz = 0; ++ char *mok_policy = NULL; ++ grub_uint32_t mok_policy_attrs = 0; ++ ++ status = grub_efi_get_variable_with_attributes ("MokPolicy", &guid, ++ &mok_policy_sz, ++ (void **)&mok_policy, ++ &mok_policy_attrs); ++ if (status == GRUB_EFI_NOT_FOUND || ++ mok_policy_sz == 0 || ++ mok_policy == NULL) ++ { ++ *nx_required = 0; ++ return GRUB_ERR_NONE; ++ } ++ ++ *nx_required = 0; ++ if (mok_policy_sz < 1 || ++ mok_policy_attrs != (GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ GRUB_EFI_VARIABLE_RUNTIME_ACCESS) || ++ (mok_policy[mok_policy_sz-1] & GRUB_MOK_POLICY_NX_REQUIRED)) ++ *nx_required = 1; ++ ++ return GRUB_ERR_NONE; ++} + + typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); + + grub_err_t +-grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, +- void *kernel_params) ++grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, ++ grub_off_t handover_offset, void *kernel_params, ++ int nx_supported) + { + grub_efi_loaded_image_t *loaded_image = NULL; + handover_func hf; + int offset = 0; ++ grub_uint64_t stack_set_attrs = GRUB_MEM_ATTR_R | ++ GRUB_MEM_ATTR_W | ++ GRUB_MEM_ATTR_X; ++ grub_uint64_t stack_clear_attrs = 0; ++ grub_uint64_t kernel_set_attrs = stack_set_attrs; ++ grub_uint64_t kernel_clear_attrs = stack_clear_attrs; ++ grub_uint64_t attrs; ++ int nx_required = 0; + + #ifdef __x86_64__ + offset = 512; +@@ -48,12 +159,57 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, + */ + loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (loaded_image) +- loaded_image->image_base = kernel_addr; ++ loaded_image->image_base = (void *)kernel_addr; + else + grub_dprintf ("linux", "Loaded Image base address could not be set\n"); + + grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", +- kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); ++ (void *)kernel_addr, (void *)handover_offset, kernel_params); ++ ++ ++ if (nx_required && !nx_supported) ++ return grub_error (GRUB_ERR_BAD_OS, N_("kernel does not support NX loading required by policy")); ++ ++ if (nx_supported) ++ { ++ kernel_set_attrs &= ~GRUB_MEM_ATTR_W; ++ kernel_clear_attrs |= GRUB_MEM_ATTR_W; ++ stack_set_attrs &= ~GRUB_MEM_ATTR_X; ++ stack_clear_attrs |= GRUB_MEM_ATTR_X; ++ } ++ ++ grub_dprintf ("nx", "Setting attributes for 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to r%cx\n", ++ kernel_addr, kernel_addr + kernel_size - 1, ++ (kernel_set_attrs & GRUB_MEM_ATTR_W) ? 'w' : '-'); ++ grub_update_mem_attrs (kernel_addr, kernel_size, ++ kernel_set_attrs, kernel_clear_attrs); ++ ++ grub_get_mem_attrs (kernel_addr, 4096, &attrs); ++ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", ++ (grub_addr_t)kernel_addr, ++ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", ++ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", ++ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); ++ if (grub_stack_addr != (grub_addr_t)-1ll) ++ { ++ grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n", ++ grub_stack_addr, grub_stack_addr + grub_stack_size - 1, ++ (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-'); ++ grub_update_mem_attrs (grub_stack_addr, grub_stack_size, ++ stack_set_attrs, stack_clear_attrs); ++ ++ grub_get_mem_attrs (grub_stack_addr, 4096, &attrs); ++ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", ++ grub_stack_addr, ++ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", ++ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", ++ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); ++ } ++ ++#if defined(__i386__) || defined(__x86_64__) ++ asm volatile ("cli"); ++#endif ++ + hf = (handover_func)((char *)kernel_addr + handover_offset + offset); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 92b2fb5091..91ae274299 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -44,7 +44,7 @@ struct grub_linuxefi_context { + grub_uint32_t handover_offset; + struct linux_kernel_params *params; + char *cmdline; +- ++ int nx_supported; + void *initrd_mem; + }; + +@@ -110,13 +110,19 @@ kernel_alloc(grub_efi_uintn_t size, + pages = BYTES_TO_PAGES(size); + grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", + (unsigned long)pages, (void *)(unsigned long)max); ++ size = pages * GRUB_EFI_PAGE_SIZE; + + prev_max = max; + addr = grub_efi_allocate_pages_real (max, pages, + max_addresses[i].alloc_type, + memtype); + if (addr) +- grub_dprintf ("linux", "Allocated at %p\n", addr); ++ { ++ grub_dprintf ("linux", "Allocated at %p\n", addr); ++ grub_update_mem_attrs ((grub_addr_t)addr, size, ++ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, ++ GRUB_MEM_ATTR_X); ++ } + } + + while (grub_error_pop ()) +@@ -137,9 +143,11 @@ grub_linuxefi_boot (void *data) + + asm volatile ("cli"); + +- return grub_efi_linux_boot ((char *)context->kernel_mem, ++ return grub_efi_linux_boot ((grub_addr_t)context->kernel_mem, ++ context->kernel_size, + context->handover_offset, +- context->params); ++ context->params, ++ context->nx_supported); + } + + static grub_err_t +@@ -304,7 +312,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_uint32_t handover_offset; + struct linux_kernel_params *params = 0; + char *cmdline = 0; ++ int nx_supported = 1; + struct grub_linuxefi_context *context = 0; ++ grub_err_t err; + + grub_dl_ref (my_mod); + +@@ -334,6 +344,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ err = grub_efi_check_nx_image_support ((grub_addr_t)kernel, filelen, ++ &nx_supported); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ grub_dprintf ("linux", "nx is%s supported by this kernel\n", ++ nx_supported ? "" : " not"); ++ + lh = (struct linux_i386_kernel_header *)kernel; + grub_dprintf ("linux", "original lh is at %p\n", kernel); + +@@ -498,6 +515,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + context->handover_offset = handover_offset; + context->params = params; + context->cmdline = cmdline; ++ context->nx_supported = nx_supported; + + grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 4aeb0e4b9a..3c1ff64763 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -805,6 +805,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + kernel_offset += len; + } + ++ grub_dprintf("efi", "setting attributes for %p (%zu bytes) to +rw-x\n", ++ &linux_params, sizeof (lh) + len); ++ grub_update_mem_attrs ((grub_addr_t)&linux_params, sizeof (lh) + len, ++ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, GRUB_MEM_ATTR_X); ++ + linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR; + linux_params.kernel_alignment = (1 << align); + linux_params.ps_mouse = linux_params.padding11 = 0; +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 34825c4adc..449e55269f 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -140,12 +140,16 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); + ++extern grub_addr_t EXPORT_VAR(grub_stack_addr); ++extern grub_size_t EXPORT_VAR(grub_stack_size); ++ + #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) + void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); + grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); + #include + grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); +-grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args); ++grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size, ++ char *args, int nx_enabled); + #endif + + grub_addr_t grub_efi_section_addr (const char *section); +diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h +index 887b02fd9f..b82f71006a 100644 +--- a/include/grub/efi/linux.h ++++ b/include/grub/efi/linux.h +@@ -22,8 +22,20 @@ + #include + #include + ++#define GRUB_MOK_POLICY_NX_REQUIRED 0x1 ++ + grub_err_t +-EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, +- void *kernel_param); ++EXPORT_FUNC(grub_efi_linux_boot) (grub_addr_t kernel_address, ++ grub_size_t kernel_size, ++ grub_off_t handover_offset, ++ void *kernel_param, int nx_enabled); ++ ++grub_err_t ++EXPORT_FUNC(grub_efi_check_nx_image_support) (grub_addr_t kernel_addr, ++ grub_size_t kernel_size, ++ int *nx_supported); ++ ++grub_err_t ++EXPORT_FUNC(grub_efi_check_nx_required) (int *nx_required); + + #endif /* ! GRUB_EFI_LINUX_HEADER */ +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index 2a5e1ee003..a5e623eb04 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -181,6 +181,8 @@ struct grub_pe32_optional_header + struct grub_pe32_data_directory reserved_entry; + }; + ++#define GRUB_PE32_NX_COMPAT 0x0100 ++ + struct grub_pe64_optional_header + { + grub_uint16_t magic; diff --git a/SOURCES/0258-net-http-Fix-OOB-write-for-split-http-headers.patch b/SOURCES/0258-net-http-Fix-OOB-write-for-split-http-headers.patch deleted file mode 100644 index 367a827..0000000 --- a/SOURCES/0258-net-http-Fix-OOB-write-for-split-http-headers.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 8 Mar 2022 18:17:03 +1100 -Subject: [PATCH] net/http: Fix OOB write for split http headers - -GRUB has special code for handling an http header that is split -across two packets. - -The code tracks the end of line by looking for a "\n" byte. The -code for split headers has always advanced the pointer just past the -end of the line, whereas the code that handles unsplit headers does -not advance the pointer. This extra advance causes the length to be -one greater, which breaks an assumption in parse_line(), leading to -it writing a NUL byte one byte past the end of the buffer where we -reconstruct the line from the two packets. - -It's conceivable that an attacker controlled set of packets could -cause this to zero out the first byte of the "next" pointer of the -grub_mm_region structure following the current_line buffer. - -Do not advance the pointer in the split header case. - -Fixes: CVE-2022-28734 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit e9fb459638811c12b0989dbf64e3e124974ef617) -(cherry picked from commit b604916beb6c39e8ed27f72851eb16f3eaa293c5) ---- - grub-core/net/http.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 19cb8768e3..58546739a2 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -193,9 +193,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), - int have_line = 1; - char *t; - ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); -- if (ptr) -- ptr++; -- else -+ if (ptr == NULL) - { - have_line = 0; - ptr = (char *) nb->tail; diff --git a/SOURCES/0258-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch b/SOURCES/0258-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch new file mode 100644 index 0000000..7da75a8 --- /dev/null +++ b/SOURCES/0258-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 22 Mar 2022 10:57:20 -0400 +Subject: [PATCH] nx: set the nx compatible flag in EFI grub images + +For NX, we need the grub binary to announce that it is compatible with +the NX feature. This implies that when loading the executable grub +image, several attributes are true: + +- the binary doesn't need an executable stack +- the binary doesn't need sections to be both executable and writable +- the binary knows how to use the EFI Memory Attributes protocol on code + it is loading. + +This patch adds a definition for the PE DLL Characteristics flag +GRUB_PE32_NX_COMPAT, and changes grub-mkimage to set that flag. + +Signed-off-by: Peter Jones +--- + util/mkimage.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/util/mkimage.c b/util/mkimage.c +index 8319e8dfbd..c3d33aaac8 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -1418,6 +1418,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + section = (struct grub_pe32_section_table *)(o64 + 1); + } + ++ PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 (GRUB_PE32_NX_COMPAT); + PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size); + PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address); + PE_OHDR (o32, o64, image_base) = 0; diff --git a/SOURCES/0259-grub-probe-document-the-behavior-of-multiple-v.patch b/SOURCES/0259-grub-probe-document-the-behavior-of-multiple-v.patch new file mode 100644 index 0000000..4e9d7cc --- /dev/null +++ b/SOURCES/0259-grub-probe-document-the-behavior-of-multiple-v.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Jul 2022 15:49:25 -0400 +Subject: [PATCH] grub-probe: document the behavior of multiple -v + +Signed-off-by: Robbie Harwood +(cherry picked from commit 51a55233eed08f7f12276afd6b3724b807a0b680) +--- + util/grub-probe.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/util/grub-probe.c b/util/grub-probe.c +index c6fac732b4..ba867319a7 100644 +--- a/util/grub-probe.c ++++ b/util/grub-probe.c +@@ -732,7 +732,8 @@ static struct argp_option options[] = { + {"device-map", 'm', N_("FILE"), 0, + N_("use FILE as the device map [default=%s]"), 0}, + {"target", 't', N_("TARGET"), 0, 0, 0}, +- {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, ++ {"verbose", 'v', 0, 0, ++ N_("print verbose messages (pass twice to enable debug printing)."), 0}, + {0, '0', 0, 0, N_("separate items in output using ASCII NUL characters"), 0}, + { 0, 0, 0, 0, 0, 0 } + }; diff --git a/SOURCES/0259-net-http-Error-out-on-headers-with-LF-without-CR.patch b/SOURCES/0259-net-http-Error-out-on-headers-with-LF-without-CR.patch deleted file mode 100644 index ea8ce37..0000000 --- a/SOURCES/0259-net-http-Error-out-on-headers-with-LF-without-CR.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Axtens -Date: Tue, 8 Mar 2022 19:04:40 +1100 -Subject: [PATCH] net/http: Error out on headers with LF without CR - -In a similar vein to the previous patch, parse_line() would write -a NUL byte past the end of the buffer if there was an HTTP header -with a LF rather than a CRLF. - -RFC-2616 says: - - Many HTTP/1.1 header field values consist of words separated by LWS - or special characters. These special characters MUST be in a quoted - string to be used within a parameter value (as defined in section 3.6). - -We don't support quoted sections or continuation lines, etc. - -If we see an LF that's not part of a CRLF, bail out. - -Fixes: CVE-2022-28734 - -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit d232ad41ac4979a9de4d746e5fdff9caf0e303de) -(cherry picked from commit 8960e6d6137090a7e8c6592077da6e387a4ef972) ---- - grub-core/net/http.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/grub-core/net/http.c b/grub-core/net/http.c -index 58546739a2..57d2721719 100644 ---- a/grub-core/net/http.c -+++ b/grub-core/net/http.c -@@ -69,7 +69,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) - char *end = ptr + len; - while (end > ptr && *(end - 1) == '\r') - end--; -+ -+ /* LF without CR. */ -+ if (end == ptr + len) -+ { -+ data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR")); -+ return GRUB_ERR_NONE; -+ } - *end = 0; -+ - /* Trailing CRLF. */ - if (data->in_chunk_len == 1) - { diff --git a/SOURCES/0260-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch b/SOURCES/0260-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch deleted file mode 100644 index f0292c5..0000000 --- a/SOURCES/0260-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudhakar Kuppusamy -Date: Wed, 6 Apr 2022 18:03:37 +0530 -Subject: [PATCH] fs/f2fs: Do not read past the end of nat journal entries - -A corrupt f2fs file system could specify a nat journal entry count -that is beyond the maximum NAT_JOURNAL_ENTRIES. - -Check if the specified nat journal entry count before accessing the -array, and throw an error if it is too large. - -Signed-off-by: Sudhakar Kuppusamy -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit a3988cb3f0a108dd67ac127a79a4c8479d23334e) -(cherry picked from commit 7125978aa7d6068812ef6da0ab38ce521ae7eba1) ---- - grub-core/fs/f2fs.c | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c -index 8a9992ca9e..63702214b0 100644 ---- a/grub-core/fs/f2fs.c -+++ b/grub-core/fs/f2fs.c -@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data) - return err; - } - --static grub_uint32_t --get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid) -+static grub_err_t -+get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid, -+ grub_uint32_t *blkaddr) - { - grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats); -- grub_uint32_t blkaddr = 0; - grub_uint16_t i; - -+ if (n >= NAT_JOURNAL_ENTRIES) -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid number of nat journal entries"); -+ - for (i = 0; i < n; i++) - { - if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid) - { -- blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); -+ *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); - break; - } - } - -- return blkaddr; -+ return GRUB_ERR_NONE; - } - - static grub_uint32_t -@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) - { - struct grub_f2fs_nat_block *nat_block; - grub_uint32_t seg_off, block_off, entry_off, block_addr; -- grub_uint32_t blkaddr; -+ grub_uint32_t blkaddr = 0; - grub_err_t err; - -- blkaddr = get_blkaddr_from_nat_journal (data, nid); -+ err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); -+ if (err != GRUB_ERR_NONE) -+ return 0; -+ - if (blkaddr) - return blkaddr; - diff --git a/SOURCES/0260-grub_fs_probe-dprint-errors-from-filesystems.patch b/SOURCES/0260-grub_fs_probe-dprint-errors-from-filesystems.patch new file mode 100644 index 0000000..1455ae4 --- /dev/null +++ b/SOURCES/0260-grub_fs_probe-dprint-errors-from-filesystems.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Jul 2022 15:39:41 -0400 +Subject: [PATCH] grub_fs_probe(): dprint errors from filesystems + +When filesystem detection fails, all that's currently debug-logged is a +series of messages like: + + grub-core/kern/fs.c:56:fs: Detecting ntfs... + grub-core/kern/fs.c:76:fs: ntfs detection failed. + +repeated for each filesystem. Any messages provided to grub_error() by +the filesystem are lost, and one has to break out gdb to figure out what +went wrong. + +With this change, one instead sees: + + grub-core/kern/fs.c:56:fs: Detecting fat... + grub-core/osdep/hostdisk.c:357:hostdisk: reusing open device + `/path/to/device' + grub-core/kern/fs.c:77:fs: error: invalid modification timestamp for /. + grub-core/kern/fs.c:79:fs: fat detection failed. + +in the debug prints. + +Signed-off-by: Robbie Harwood +(cherry picked from commit 838c79d658797d0662ee7f9e033e38ee88059e02) +--- + grub-core/kern/fs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c +index c698295bcb..b58e2ae1d2 100644 +--- a/grub-core/kern/fs.c ++++ b/grub-core/kern/fs.c +@@ -74,6 +74,7 @@ grub_fs_probe (grub_device_t device) + if (grub_errno == GRUB_ERR_NONE) + return p; + ++ grub_dprintf ("fs", _("error: %s.\n"), grub_errmsg); + grub_error_push (); + grub_dprintf ("fs", "%s detection failed.\n", p->name); + grub_error_pop (); diff --git a/SOURCES/0261-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch b/SOURCES/0261-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch deleted file mode 100644 index 1d59fb6..0000000 --- a/SOURCES/0261-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudhakar Kuppusamy -Date: Wed, 6 Apr 2022 18:49:09 +0530 -Subject: [PATCH] fs/f2fs: Do not read past the end of nat bitmap - -A corrupt f2fs filesystem could have a block offset or a bitmap -offset that would cause us to read beyond the bounds of the nat -bitmap. - -Introduce the nat_bitmap_size member in grub_f2fs_data which holds -the size of nat bitmap. - -Set the size when loading the nat bitmap in nat_bitmap_ptr(), and -catch when an invalid offset would create a pointer past the end of -the allocated space. - -Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid -reading past the end of the nat bitmap. - -Signed-off-by: Sudhakar Kuppusamy -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 62d63d5e38c67a6e349148bf7cb87c560e935a7e) -(cherry picked from commit 92219e6d379b5b4d30b05361830b72ab1d95d281) ---- - grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------ - 1 file changed, 27 insertions(+), 6 deletions(-) - -diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c -index 63702214b0..8898b235e0 100644 ---- a/grub-core/fs/f2fs.c -+++ b/grub-core/fs/f2fs.c -@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - #define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */ - - #define MAX_VOLUME_NAME 512 -+#define MAX_NAT_BITMAP_SIZE 3900 - - enum FILE_TYPE - { -@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint - grub_uint32_t checksum_offset; - grub_uint64_t elapsed_time; - grub_uint8_t alloc_type[MAX_ACTIVE_LOGS]; -- grub_uint8_t sit_nat_version_bitmap[3900]; -+ grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE]; - grub_uint32_t checksum; - } GRUB_PACKED; - -@@ -302,6 +303,7 @@ struct grub_f2fs_data - - struct grub_f2fs_nat_journal nat_j; - char *nat_bitmap; -+ grub_uint32_t nat_bitmap_size; - - grub_disk_t disk; - struct grub_f2fs_node *inode; -@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type) - } - - static void * --nat_bitmap_ptr (struct grub_f2fs_data *data) -+nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size) - { - struct grub_f2fs_checkpoint *ckpt = &data->ckpt; - grub_uint32_t offset; -+ *nat_bitmap_size = MAX_NAT_BITMAP_SIZE; - - if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0) - return ckpt->sit_nat_version_bitmap; - - offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize); -+ if (offset >= MAX_NAT_BITMAP_SIZE) -+ return NULL; -+ -+ *nat_bitmap_size = *nat_bitmap_size - offset; - - return ckpt->sit_nat_version_bitmap + offset; - } -@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len) - } - - static int --grub_f2fs_test_bit (grub_uint32_t nr, const char *p) -+grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len) - { - int mask; -+ grub_uint32_t shifted_nr = (nr >> 3); - -- p += (nr >> 3); -+ if (shifted_nr >= len) -+ return -1; -+ -+ p += shifted_nr; - mask = 1 << (7 - (nr & 0x07)); - - return mask & *p; -@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) - grub_uint32_t seg_off, block_off, entry_off, block_addr; - grub_uint32_t blkaddr = 0; - grub_err_t err; -+ int result_bit; - - err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); - if (err != GRUB_ERR_NONE) -@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) - ((seg_off * data->blocks_per_seg) << 1) + - (block_off & (data->blocks_per_seg - 1)); - -- if (grub_f2fs_test_bit (block_off, data->nat_bitmap)) -+ result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap, -+ data->nat_bitmap_size); -+ if (result_bit > 0) - block_addr += data->blocks_per_seg; -+ else if (result_bit == -1) -+ { -+ grub_free (nat_block); -+ return 0; -+ } - - err = grub_f2fs_block_read (data, block_addr, nat_block); - if (err) -@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk) - if (err) - goto fail; - -- data->nat_bitmap = nat_bitmap_ptr (data); -+ data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size); -+ if (data->nat_bitmap == NULL) -+ goto fail; - - err = get_nat_journal (data); - if (err) diff --git a/SOURCES/0261-fs-fat-don-t-error-when-mtime-is-0.patch b/SOURCES/0261-fs-fat-don-t-error-when-mtime-is-0.patch new file mode 100644 index 0000000..f014f6c --- /dev/null +++ b/SOURCES/0261-fs-fat-don-t-error-when-mtime-is-0.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Jul 2022 15:42:41 -0400 +Subject: [PATCH] fs/fat: don't error when mtime is 0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the wild, we occasionally see valid ESPs where some file modification times +are 0. For instance: + + ├── [Dec 31 1979] EFI + │ ├── [Dec 31 1979] BOOT + │ │ ├── [Dec 31 1979] BOOTX64.EFI + │ │ └── [Dec 31 1979] fbx64.efi + │ └── [Jun 27 02:41] fedora + │ ├── [Dec 31 1979] BOOTX64.CSV + │ ├── [Dec 31 1979] fonts + │ ├── [Mar 14 03:35] fw + │ │ ├── [Mar 14 03:35] fwupd-359c1169-abd6-4a0d-8bce-e4d4713335c1.cap + │ │ ├── [Mar 14 03:34] fwupd-9d255c4b-2d88-4861-860d-7ee52ade9463.cap + │ │ └── [Mar 14 03:34] fwupd-b36438d8-9128-49d2-b280-487be02d948b.cap + │ ├── [Dec 31 1979] fwupdx64.efi + │ ├── [May 10 10:47] grub.cfg + │ ├── [Jun 3 12:38] grub.cfg.new.new + │ ├── [May 10 10:41] grub.cfg.old + │ ├── [Jun 27 02:41] grubenv + │ ├── [Dec 31 1979] grubx64.efi + │ ├── [Dec 31 1979] mmx64.efi + │ ├── [Dec 31 1979] shim.efi + │ ├── [Dec 31 1979] shimx64.efi + │ └── [Dec 31 1979] shimx64-fedora.efi + └── [Dec 31 1979] FSCK0000.REC + + 5 directories, 17 files + +This causes grub-probe failure, which in turn causes grub-mkconfig +failure. They are valid filesystems that appear intact, and the Linux +FAT stack is able to mount and manipulate them without complaint. + +The check for mtime of 0 has been present since +20def1a3c3952982395cd7c3ea7e78638527962b ("fat: support file +modification times"). + +Signed-off-by: Robbie Harwood +(cherry picked from commit 0615c4887352e32d7bb7198e9ad0d695f9dc2c31) +--- + grub-core/fs/fat.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c +index dd82e4ee35..ff6200c5be 100644 +--- a/grub-core/fs/fat.c ++++ b/grub-core/fs/fat.c +@@ -1027,9 +1027,6 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + grub_le_to_cpu16 (ctxt.dir.w_date), + &info.mtime); + #endif +- if (info.mtimeset == 0) +- grub_error (GRUB_ERR_OUT_OF_RANGE, +- "invalid modification timestamp for %s", path); + + if (hook (ctxt.filename, &info, hook_data)) + break; diff --git a/SOURCES/0262-Make-debug-file-show-which-file-filters-get-run.patch b/SOURCES/0262-Make-debug-file-show-which-file-filters-get-run.patch new file mode 100644 index 0000000..78bc095 --- /dev/null +++ b/SOURCES/0262-Make-debug-file-show-which-file-filters-get-run.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 29 Jul 2022 15:56:00 -0400 +Subject: [PATCH] Make debug=file show which file filters get run. + +If one of the file filters breaks things, it's hard to figure out where +it has happened. + +This makes grub log which filter is being run, which makes it easier to +figure out where you are in the sequence of events. + +Signed-off-by: Peter Jones +--- + grub-core/kern/file.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c +index db938e099d..868ce3b63e 100644 +--- a/grub-core/kern/file.c ++++ b/grub-core/kern/file.c +@@ -30,6 +30,14 @@ void (*EXPORT_VAR (grub_grubnet_fini)) (void); + + grub_file_filter_t grub_file_filters[GRUB_FILE_FILTER_MAX]; + ++static const char *filter_names[] = { ++ [GRUB_FILE_FILTER_VERIFY] = "GRUB_FILE_FILTER_VERIFY", ++ [GRUB_FILE_FILTER_GZIO] = "GRUB_FILE_FILTER_GZIO", ++ [GRUB_FILE_FILTER_XZIO] = "GRUB_FILE_FILTER_XZIO", ++ [GRUB_FILE_FILTER_LZOPIO] = "GRUB_FILE_FILTER_LZOPIO", ++ [GRUB_FILE_FILTER_MAX] = "GRUB_FILE_FILTER_MAX" ++}; ++ + /* Get the device part of the filename NAME. It is enclosed by parentheses. */ + char * + grub_file_get_device_name (const char *name) +@@ -124,6 +132,9 @@ grub_file_open (const char *name, enum grub_file_type type) + if (grub_file_filters[filter]) + { + last_file = file; ++ if (filter < GRUB_FILE_FILTER_MAX) ++ grub_dprintf ("file", "Running %s file filter\n", ++ filter_names[filter]); + file = grub_file_filters[filter] (file, type); + if (file && file != last_file) + { diff --git a/SOURCES/0262-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch b/SOURCES/0262-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch deleted file mode 100644 index c454897..0000000 --- a/SOURCES/0262-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudhakar Kuppusamy -Date: Wed, 6 Apr 2022 18:17:43 +0530 -Subject: [PATCH] fs/f2fs: Do not copy file names that are too long - -A corrupt f2fs file system might specify a name length which is greater -than the maximum name length supported by the GRUB f2fs driver. - -We will allocate enough memory to store the overly long name, but there -are only F2FS_NAME_LEN bytes in the source, so we would read past the end -of the source. - -While checking directory entries, do not copy a file name with an invalid -length. - -Signed-off-by: Sudhakar Kuppusamy -Signed-off-by: Daniel Axtens -Reviewed-by: Daniel Kiper -(cherry picked from commit 9a891f638509e031d322c94e3cbcf38d36f3993a) -(cherry picked from commit 13f9160ae0d2806baed459884999356817096cd7) ---- - grub-core/fs/f2fs.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c -index 8898b235e0..df6beb544c 100644 ---- a/grub-core/fs/f2fs.c -+++ b/grub-core/fs/f2fs.c -@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx) - - ftype = ctx->dentry[i].file_type; - name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len); -+ -+ if (name_len >= F2FS_NAME_LEN) -+ return 0; -+ - filename = grub_malloc (name_len + 1); - if (!filename) - return 0; diff --git a/SOURCES/0263-efi-use-enumerated-array-positions-for-our-allocatio.patch b/SOURCES/0263-efi-use-enumerated-array-positions-for-our-allocatio.patch new file mode 100644 index 0000000..206e3a6 --- /dev/null +++ b/SOURCES/0263-efi-use-enumerated-array-positions-for-our-allocatio.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 14:06:30 -0400 +Subject: [PATCH] efi: use enumerated array positions for our allocation + choices + +In our kernel allocator on EFI systems, we currently have a growing +amount of code that references the various allocation policies by +position in the array, and of course maintenance of this code scales +very poorly. + +This patch changes them to be enumerated, so they're easier to refer to +farther along in the code without confusion. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 91ae274299..8daa070132 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -60,17 +60,26 @@ struct allocation_choice { + grub_efi_allocate_type_t alloc_type; + }; + +-static struct allocation_choice max_addresses[4] = ++enum { ++ KERNEL_PREF_ADDRESS, ++ KERNEL_4G_LIMIT, ++ KERNEL_NO_LIMIT, ++}; ++ ++static struct allocation_choice max_addresses[] = + { + /* the kernel overrides this one with pref_address and + * GRUB_EFI_ALLOCATE_ADDRESS */ +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ [KERNEL_PREF_ADDRESS] = ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ /* If the flag in params is set, this one gets changed to be above 4GB. */ ++ [KERNEL_4G_LIMIT] = ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + /* this one is always below 4GB, which we still *prefer* even if the flag + * is set. */ +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, +- /* If the flag in params is set, this one gets changed to be above 4GB. */ +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, +- { 0, 0 } ++ [KERNEL_NO_LIMIT] = ++ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { NO_MEM, 0, 0 } + }; + static struct allocation_choice saved_addresses[4]; + +@@ -405,7 +414,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) + { + grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); +- max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS; ++ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; + } + else + { +@@ -478,11 +487,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); + if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) + { +- max_addresses[0].addr = lh->pref_address; +- max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; ++ max_addresses[KERNEL_PREF_ADDRESS].addr = lh->pref_address; ++ max_addresses[KERNEL_PREF_ADDRESS].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; + } +- max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; +- max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + kernel_size = lh->init_size; + kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, + N_("can't allocate kernel")); diff --git a/SOURCES/0263-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch b/SOURCES/0263-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch deleted file mode 100644 index 5e8cd4d..0000000 --- a/SOURCES/0263-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Darren Kenny -Date: Tue, 29 Mar 2022 10:49:56 +0000 -Subject: [PATCH] fs/btrfs: Fix several fuzz issues with invalid dir item - sizing - -According to the btrfs code in Linux, the structure of a directory item -leaf should be of the form: - - |struct btrfs_dir_item|name|data| - -in GRUB the name len and data len are in the grub_btrfs_dir_item -structure's n and m fields respectively. - -The combined size of the structure, name and data should be less than -the allocated memory, a difference to the Linux kernel's struct -btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for -where the name is stored, so we adjust for that too. - -Signed-off-by: Darren Kenny -Reviewed-by: Daniel Kiper -(cherry picked from commit 6d3f06c0b6a8992b9b1bb0e62af93ac5ff2781f0) -[rharwood: we've an extra variable here] -Signed-off-by: Robbie Harwood -(cherry picked from commit e3e21b9a81aea09dd43368cf097c1029a8380d82) ---- - grub-core/fs/btrfs.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index 4cc86e9b79..f3ab64e098 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -2254,6 +2254,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, - grub_uint64_t tree; - grub_uint8_t type; - char *new_path = NULL; -+ grub_size_t est_size = 0; - - if (!data) - return grub_errno; -@@ -2320,6 +2321,18 @@ grub_btrfs_dir (grub_device_t device, const char *path, - break; - } - -+ if (direl == NULL || -+ grub_add (grub_le_to_cpu16 (direl->n), -+ grub_le_to_cpu16 (direl->m), &est_size) || -+ grub_add (est_size, sizeof (*direl), &est_size) || -+ grub_sub (est_size, sizeof (direl->name), &est_size) || -+ est_size > allocated) -+ { -+ grub_errno = GRUB_ERR_OUT_OF_RANGE; -+ r = -grub_errno; -+ goto out; -+ } -+ - for (cdirel = direl; - (grub_uint8_t *) cdirel - (grub_uint8_t *) direl - < (grub_ssize_t) elemsize; -@@ -2330,6 +2343,19 @@ grub_btrfs_dir (grub_device_t device, const char *path, - char c; - struct grub_btrfs_inode inode; - struct grub_dirhook_info info; -+ -+ if (cdirel == NULL || -+ grub_add (grub_le_to_cpu16 (cdirel->n), -+ grub_le_to_cpu16 (cdirel->m), &est_size) || -+ grub_add (est_size, sizeof (*cdirel), &est_size) || -+ grub_sub (est_size, sizeof (cdirel->name), &est_size) || -+ est_size > allocated) -+ { -+ grub_errno = GRUB_ERR_OUT_OF_RANGE; -+ r = -grub_errno; -+ goto out; -+ } -+ - err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id, - tree); - grub_memset (&info, 0, sizeof (info)); diff --git a/SOURCES/0264-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch b/SOURCES/0264-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch new file mode 100644 index 0000000..d25cf30 --- /dev/null +++ b/SOURCES/0264-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch @@ -0,0 +1,127 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 14:24:39 -0400 +Subject: [PATCH] efi: split allocation policy for kernel vs initrd memories. + +Currently in our kernel allocator, we use the same set of choices for +all of our various kernel and initramfs allocations, though they do not +have exactly the same constraints. + +This patch adds the concept of an allocation purpose, which currently +can be KERNEL_MEM or INITRD_MEM, and updates kernel_alloc() calls +appropriately, but does not change any current policy decision. It +also adds a few debug prints. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 35 +++++++++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 8 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 8daa070132..e6b8998e5e 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -55,7 +55,14 @@ struct grub_linuxefi_context { + + #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) + ++typedef enum { ++ NO_MEM, ++ KERNEL_MEM, ++ INITRD_MEM, ++} kernel_alloc_purpose_t; ++ + struct allocation_choice { ++ kernel_alloc_purpose_t purpose; + grub_efi_physical_address_t addr; + grub_efi_allocate_type_t alloc_type; + }; +@@ -64,6 +71,7 @@ enum { + KERNEL_PREF_ADDRESS, + KERNEL_4G_LIMIT, + KERNEL_NO_LIMIT, ++ INITRD_MAX_ADDRESS, + }; + + static struct allocation_choice max_addresses[] = +@@ -71,14 +79,17 @@ static struct allocation_choice max_addresses[] = + /* the kernel overrides this one with pref_address and + * GRUB_EFI_ALLOCATE_ADDRESS */ + [KERNEL_PREF_ADDRESS] = +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + /* If the flag in params is set, this one gets changed to be above 4GB. */ + [KERNEL_4G_LIMIT] = +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + /* this one is always below 4GB, which we still *prefer* even if the flag + * is set. */ + [KERNEL_NO_LIMIT] = +- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, ++ /* this is for the initrd */ ++ [INITRD_MAX_ADDRESS] = ++ { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + { NO_MEM, 0, 0 } + }; + static struct allocation_choice saved_addresses[4]; +@@ -95,7 +106,8 @@ kernel_free(void *addr, grub_efi_uintn_t size) + } + + static void * +-kernel_alloc(grub_efi_uintn_t size, ++kernel_alloc(kernel_alloc_purpose_t purpose, ++ grub_efi_uintn_t size, + grub_efi_memory_type_t memtype, + const char * const errmsg) + { +@@ -108,6 +120,9 @@ kernel_alloc(grub_efi_uintn_t size, + grub_uint64_t max = max_addresses[i].addr; + grub_efi_uintn_t pages; + ++ if (purpose != max_addresses[i].purpose) ++ continue; ++ + /* + * When we're *not* loading the kernel, or >4GB allocations aren't + * supported, these entries are basically all the same, so don't re-try +@@ -261,7 +276,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + } + +- initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, ++ grub_dprintf ("linux", "Trying to allocate initrd mem\n"); ++ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, + N_("can't allocate initrd")); + if (initrd_mem == NULL) + goto fail; +@@ -422,7 +438,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + +- params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, ++ params = kernel_alloc (KERNEL_MEM, sizeof(*params), ++ GRUB_EFI_RUNTIME_SERVICES_DATA, + "cannot allocate kernel parameters"); + if (!params) + goto fail; +@@ -445,7 +462,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linux", "new lh is at %p\n", lh); + + grub_dprintf ("linux", "setting up cmdline\n"); +- cmdline = kernel_alloc (lh->cmdline_size + 1, ++ cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, + GRUB_EFI_RUNTIME_SERVICES_DATA, + N_("can't allocate cmdline")); + if (!cmdline) +@@ -493,7 +510,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; + kernel_size = lh->init_size; +- kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, ++ grub_dprintf ("linux", "Trying to allocate kernel mem\n"); ++ kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, ++ GRUB_EFI_RUNTIME_SERVICES_CODE, + N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) diff --git a/SOURCES/0264-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch b/SOURCES/0264-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch deleted file mode 100644 index f2a8815..0000000 --- a/SOURCES/0264-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Darren Kenny -Date: Tue, 29 Mar 2022 15:52:46 +0000 -Subject: [PATCH] fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing - -The fuzzer is generating btrfs file systems that have chunks with -invalid combinations of stripes and substripes for the given RAID -configurations. - -After examining the Linux kernel fs/btrfs/tree-checker.c code, it -appears that sub-stripes should only be applied to RAID10, and in that -case there should only ever be 2 of them. - -Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4 -should have 2. 3 or 4 stripes respectively, which is what redundancy -corresponds. - -Some of the chunks ended up with a size of 0, which grub_malloc() still -returned memory for and in turn generated ASAN errors later when -accessed. - -While it would be possible to specifically limit the number of stripes, -a more correct test was on the combination of the chunk item, and the -number of stripes by the size of the chunk stripe structure in -comparison to the size of the chunk itself. - -Signed-off-by: Darren Kenny -Reviewed-by: Daniel Kiper -(cherry picked from commit 3849647b4b98a4419366708fc4b7f339c6f55ec7) -(cherry picked from commit fa5a02a8930bbd8a3b5ae6ed9612307611f18500) ---- - grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 55 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index f3ab64e098..b104da085c 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -941,6 +941,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - return grub_error (GRUB_ERR_BAD_FS, - "couldn't find the chunk descriptor"); - -+ if (!chsize) -+ { -+ grub_dprintf ("btrfs", "zero-size chunk\n"); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "got an invalid zero-size chunk"); -+ } - chunk = grub_malloc (chsize); - if (!chunk) - return grub_errno; -@@ -999,6 +1005,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size), - nstripes, - NULL); -+ -+ /* For single, there should be exactly 1 stripe. */ -+ if (grub_le_to_cpu16 (chunk->nstripes) != 1) -+ { -+ grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n", -+ grub_le_to_cpu16 (chunk->nstripes)); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid RAID_SINGLE: nstripes != 1 (%u)", -+ grub_le_to_cpu16 (chunk->nstripes)); -+ } - if (stripe_length == 0) - stripe_length = 512; - stripen = grub_divmod64 (off, stripe_length, &stripe_offset); -@@ -1018,6 +1034,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - stripen = 0; - stripe_offset = off; - csize = grub_le_to_cpu64 (chunk->size) - off; -+ -+ /* -+ * Redundancy, and substripes only apply to RAID10, and there -+ * should be exactly 2 sub-stripes. -+ */ -+ if (grub_le_to_cpu16 (chunk->nstripes) != redundancy) -+ { -+ grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n", -+ redundancy, grub_le_to_cpu16 (chunk->nstripes)); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid RAID1: nstripes != %u (%u)", -+ redundancy, grub_le_to_cpu16 (chunk->nstripes)); -+ } - break; - } - case GRUB_BTRFS_CHUNK_TYPE_RAID0: -@@ -1054,6 +1083,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - stripe_offset = low + chunk_stripe_length - * high; - csize = chunk_stripe_length - low; -+ -+ /* -+ * Substripes only apply to RAID10, and there -+ * should be exactly 2 sub-stripes. -+ */ -+ if (grub_le_to_cpu16 (chunk->nsubstripes) != 2) -+ { -+ grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)", -+ grub_le_to_cpu16 (chunk->nsubstripes)); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "invalid RAID10: nsubstripes != 2 (%u)", -+ grub_le_to_cpu16 (chunk->nsubstripes)); -+ } -+ - break; - } - case GRUB_BTRFS_CHUNK_TYPE_RAID5: -@@ -1153,6 +1196,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - - for (j = 0; j < 2; j++) - { -+ grub_size_t est_chunk_alloc = 0; -+ - grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T - "+0x%" PRIxGRUB_UINT64_T - " (%d stripes (%d substripes) of %" -@@ -1165,6 +1210,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n", - addr); - -+ if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe), -+ grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) || -+ grub_add (est_chunk_alloc, -+ sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) || -+ est_chunk_alloc > chunk->size) -+ { -+ err = GRUB_ERR_BAD_FS; -+ break; -+ } -+ - if (is_raid56) - { - err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/SOURCES/0265-efi-allocate-the-initrd-within-the-bounds-expressed-.patch b/SOURCES/0265-efi-allocate-the-initrd-within-the-bounds-expressed-.patch new file mode 100644 index 0000000..47e31e2 --- /dev/null +++ b/SOURCES/0265-efi-allocate-the-initrd-within-the-bounds-expressed-.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 14:07:50 -0400 +Subject: [PATCH] efi: allocate the initrd within the bounds expressed by the + kernel + +Currently on x86, only linux kernels built with CONFIG_RELOCATABLE for +x86_64 can be loaded above 4G, but the maximum address for the initramfs +is specified via a HdrS field. This allows us to utilize that value, +and unless loading the kernel above 4G, uses the value present there. +If loading kernel above 4G is allowed, we assume loading the initramfs +above 4G also works; in practice this has been true in the kernel code +for quite some time. + +Resolves: rhbz#2112134 + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index e6b8998e5e..d003b474ee 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -190,6 +190,8 @@ grub_linuxefi_unload (void *data) + cmd_initrdefi->data = 0; + grub_free (context); + ++ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ + return GRUB_ERR_NONE; + } + +@@ -426,11 +428,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + #endif + ++ max_addresses[INITRD_MAX_ADDRESS].addr = lh->initrd_addr_max; + #if defined(__x86_64__) + if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) + { + grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); + max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; ++ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_USABLE_ADDRESS; + } + else + { +@@ -560,6 +564,8 @@ fail: + + grub_dl_unref (my_mod); + ++ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; ++ + if (lh) + kernel_free (cmdline, lh->cmdline_size + 1); + diff --git a/SOURCES/0265-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch b/SOURCES/0265-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch deleted file mode 100644 index 01294d6..0000000 --- a/SOURCES/0265-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Darren Kenny -Date: Thu, 7 Apr 2022 15:18:12 +0000 -Subject: [PATCH] fs/btrfs: Fix more fuzz issues related to chunks - -The corpus we generating issues in grub_btrfs_read_logical() when -attempting to iterate over nstripes entries in the boot mapping. - -In most cases the reason for the failure was that the number of strips -exceeded the possible space statically allocated in superblock bootmapping -space. Each stripe entry in the bootmapping block consists of -a grub_btrfs_key followed by a grub_btrfs_chunk_stripe. - -Another issue that came up was that while calculating the chunk size, -in an earlier piece of code in that function, depending on the data -provided in the btrfs file system, it would end up calculating a size -that was too small to contain even 1 grub_btrfs_chunk_item, which is -obviously invalid too. - -Signed-off-by: Darren Kenny -Reviewed-by: Daniel Kiper -(cherry picked from commit e00cd76cbadcc897a9cc4087cb2fcb5dbe15e596) -(cherry picked from commit b74a6fc95b0839937acf4f2b7445ae9d179f49ec) ---- - grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c -index b104da085c..8ec885a93b 100644 ---- a/grub-core/fs/btrfs.c -+++ b/grub-core/fs/btrfs.c -@@ -947,6 +947,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - return grub_error (GRUB_ERR_BAD_FS, - "got an invalid zero-size chunk"); - } -+ -+ /* -+ * The space being allocated for a chunk should at least be able to -+ * contain one chunk item. -+ */ -+ if (chsize < sizeof (struct grub_btrfs_chunk_item)) -+ { -+ grub_dprintf ("btrfs", "chunk-size too small\n"); -+ return grub_error (GRUB_ERR_BAD_FS, -+ "got an invalid chunk size"); -+ } - chunk = grub_malloc (chsize); - if (!chunk) - return grub_errno; -@@ -1194,6 +1205,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - if (csize > (grub_uint64_t) size) - csize = size; - -+ /* -+ * The space for a chunk stripe is limited to the space provide in the super-block's -+ * bootstrap mapping with an initial btrfs key at the start of each chunk. -+ */ -+ grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) / -+ (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe)); -+ - for (j = 0; j < 2; j++) - { - grub_size_t est_chunk_alloc = 0; -@@ -1220,6 +1238,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, - break; - } - -+ if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes) -+ { -+ err = GRUB_ERR_BAD_FS; -+ break; -+ } -+ - if (is_raid56) - { - err = btrfs_read_from_chunk (data, chunk, stripen, diff --git a/SOURCES/0266-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch b/SOURCES/0266-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch new file mode 100644 index 0000000..8451dbf --- /dev/null +++ b/SOURCES/0266-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Aug 2022 13:04:43 -0400 +Subject: [PATCH] efi: use EFI_LOADER_(CODE|DATA) for kernel and initrd + allocations + +At some point due to an erroneous kernel warning, we switched kernel and +initramfs to being loaded in EFI_RUNTIME_SERVICES_CODE and +EFI_RUNTIME_SERVICES_DATA memory pools. This doesn't appear to be +correct according to the spec, and that kernel warning has gone away. + +This patch puts them back in EFI_LOADER_CODE and EFI_LOADER_DATA +allocations, respectively. + +Resolves: rhbz#2108456 + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index d003b474ee..ac5ef50bdb 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -279,7 +279,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) + } + + grub_dprintf ("linux", "Trying to allocate initrd mem\n"); +- initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, ++ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_LOADER_DATA, + N_("can't allocate initrd")); + if (initrd_mem == NULL) + goto fail; +@@ -443,7 +443,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + #endif + + params = kernel_alloc (KERNEL_MEM, sizeof(*params), +- GRUB_EFI_RUNTIME_SERVICES_DATA, ++ GRUB_EFI_LOADER_DATA, + "cannot allocate kernel parameters"); + if (!params) + goto fail; +@@ -467,7 +467,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + grub_dprintf ("linux", "setting up cmdline\n"); + cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, +- GRUB_EFI_RUNTIME_SERVICES_DATA, ++ GRUB_EFI_LOADER_DATA, + N_("can't allocate cmdline")); + if (!cmdline) + goto fail; +@@ -516,7 +516,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + kernel_size = lh->init_size; + grub_dprintf ("linux", "Trying to allocate kernel mem\n"); + kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, +- GRUB_EFI_RUNTIME_SERVICES_CODE, ++ GRUB_EFI_LOADER_CODE, + N_("can't allocate kernel")); + restore_addresses(); + if (!kernel_mem) diff --git a/SOURCES/0266-misc-Make-grub_min-and-grub_max-more-resilient.patch b/SOURCES/0266-misc-Make-grub_min-and-grub_max-more-resilient.patch deleted file mode 100644 index d34a0e3..0000000 --- a/SOURCES/0266-misc-Make-grub_min-and-grub_max-more-resilient.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 16:06:10 -0400 -Subject: [PATCH] misc: Make grub_min() and grub_max() more resilient. - -grub_min(a,b) and grub_max(a,b) use a relatively naive implementation -which leads to several problems: -- they evaluate their parameters more than once -- the naive way to address this, to declare temporary variables in a - statement-expression, isn't resilient against nested uses, because - MIN(a,MIN(b,c)) results in the temporary variables being declared in - two nested scopes, which may result in a build warning depending on - your build options. - -This patch changes our implementation to use a statement-expression -inside a helper macro, and creates the symbols for the temporary -variables with __COUNTER__ (A GNU C cpp extension) and token pasting to -create uniquely named internal variables. - -Signed-off-by: Peter Jones -(cherry picked from commit 2d6800450fa731d7b3ef9893986806e88e819eb6) ---- - grub-core/loader/multiboot_elfxx.c | 4 +--- - include/grub/misc.h | 25 +++++++++++++++++++++++-- - 2 files changed, 24 insertions(+), 5 deletions(-) - -diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c -index f2318e0d16..87f6e31aa6 100644 ---- a/grub-core/loader/multiboot_elfxx.c -+++ b/grub-core/loader/multiboot_elfxx.c -@@ -35,9 +35,7 @@ - #endif - - #include -- --#define CONCAT(a,b) CONCAT_(a, b) --#define CONCAT_(a,b) a ## b -+#include - - #pragma GCC diagnostic ignored "-Wcast-align" - -diff --git a/include/grub/misc.h b/include/grub/misc.h -index 6c4aa85ac5..cf84aec1db 100644 ---- a/include/grub/misc.h -+++ b/include/grub/misc.h -@@ -35,6 +35,14 @@ - #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) - #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } - -+#ifndef CONCAT_ -+#define CONCAT_(a, b) a ## b -+#endif -+ -+#ifndef CONCAT -+#define CONCAT(a, b) CONCAT_(a, b) -+#endif -+ - #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__) - - void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n); -@@ -498,8 +506,21 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, - #define grub_boot_time(...) - #endif - --#define grub_max(a, b) (((a) > (b)) ? (a) : (b)) --#define grub_min(a, b) (((a) < (b)) ? (a) : (b)) -+#define _grub_min(a, b, _a, _b) \ -+ ({ typeof (a) _a = (a); \ -+ typeof (b) _b = (b); \ -+ _a < _b ? _a : _b; }) -+#define grub_min(a, b) _grub_min(a, b, \ -+ CONCAT(_a_,__COUNTER__), \ -+ CONCAT(_b_,__COUNTER__)) -+ -+#define _grub_max(a, b, _a, _b) \ -+ ({ typeof (a) _a = (a); \ -+ typeof (b) _b = (b); \ -+ _a > _b ? _a : _b; }) -+#define grub_max(a, b) _grub_max(a, b, \ -+ CONCAT(_a_,__COUNTER__), \ -+ CONCAT(_b_,__COUNTER__)) - - #define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) - __builtin_clzll (n) - 1) - diff --git a/SOURCES/0267-BLS-create-etc-kernel-cmdline-during-mkconfig.patch b/SOURCES/0267-BLS-create-etc-kernel-cmdline-during-mkconfig.patch new file mode 100644 index 0000000..50ba0fb --- /dev/null +++ b/SOURCES/0267-BLS-create-etc-kernel-cmdline-during-mkconfig.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 2 Aug 2022 15:56:28 -0400 +Subject: [PATCH] BLS: create /etc/kernel/cmdline during mkconfig + +Signed-off-by: Robbie Harwood +--- + util/grub.d/10_linux.in | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 865af3d6c4..9ebff661a9 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -161,6 +161,12 @@ update_bls_cmdline() + local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + local -a files=($(get_sorted_bls)) + ++ if [[ ! -f /etc/kernel/cmdline ]]; then ++ # anaconda has the correct information to do this during install; ++ # afterward, grubby will take care of syncing on updates. ++ echo "$cmdline rhgb quiet" > /etc/kernel/cmdline ++ fi ++ + for bls in "${files[@]}"; do + local options="${cmdline}" + if [ -z "${bls##*debug*}" ]; then diff --git a/SOURCES/0267-ReiserFS-switch-to-using-grub_min-grub_max.patch b/SOURCES/0267-ReiserFS-switch-to-using-grub_min-grub_max.patch deleted file mode 100644 index e604215..0000000 --- a/SOURCES/0267-ReiserFS-switch-to-using-grub_min-grub_max.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 21 Apr 2022 16:31:17 -0400 -Subject: [PATCH] ReiserFS: switch to using grub_min()/grub_max() - -This is a minor cleanup patch to remove the bespoke MIN() and MAX() -definitions from the reiserfs driver, and uses grub_min() / grub_max() -instead. - -Signed-off-by: Peter Jones -(cherry picked from commit 5fc601574fce99b32fe4dfb55bd8f3ab0175fd6a) ---- - grub-core/fs/reiserfs.c | 28 +++++++++------------------- - 1 file changed, 9 insertions(+), 19 deletions(-) - -diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c -index af6a226a7f..b8253da7fe 100644 ---- a/grub-core/fs/reiserfs.c -+++ b/grub-core/fs/reiserfs.c -@@ -42,16 +42,6 @@ - - GRUB_MOD_LICENSE ("GPLv3+"); - --#define MIN(a, b) \ -- ({ typeof (a) _a = (a); \ -- typeof (b) _b = (b); \ -- _a < _b ? _a : _b; }) -- --#define MAX(a, b) \ -- ({ typeof (a) _a = (a); \ -- typeof (b) _b = (b); \ -- _a > _b ? _a : _b; }) -- - #define REISERFS_SUPER_BLOCK_OFFSET 0x10000 - #define REISERFS_MAGIC_LEN 12 - #define REISERFS_MAGIC_STRING "ReIsEr" -@@ -1076,7 +1066,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2); - initial_position = off; - current_position = 0; -- final_position = MIN (len + initial_position, node->size); -+ final_position = grub_min (len + initial_position, node->size); - grub_dprintf ("reiserfs", - "Reading from %lld to %lld (%lld instead of requested %ld)\n", - (unsigned long long) initial_position, -@@ -1115,8 +1105,8 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block); - if (initial_position < current_position + item_size) - { -- offset = MAX ((signed) (initial_position - current_position), 0); -- length = (MIN (item_size, final_position - current_position) -+ offset = grub_max ((signed) (initial_position - current_position), 0); -+ length = (grub_min (item_size, final_position - current_position) - - offset); - grub_dprintf ("reiserfs", - "Reading direct block %u from %u to %u...\n", -@@ -1161,9 +1151,9 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block); - if (current_position + block_size >= initial_position) - { -- offset = MAX ((signed) (initial_position - current_position), -- 0); -- length = (MIN (block_size, final_position - current_position) -+ offset = grub_max ((signed) (initial_position - current_position), -+ 0); -+ length = (grub_min (block_size, final_position - current_position) - - offset); - grub_dprintf ("reiserfs", - "Reading indirect block %u from %u to %u...\n", -@@ -1205,7 +1195,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - switch (found.type) - { - case GRUB_REISERFS_DIRECT: -- read_length = MIN (len, item_size - file->offset); -+ read_length = grub_min (len, item_size - file->offset); - grub_disk_read (found.data->disk, - (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE, - grub_le_to_cpu16 (found.header.item_location) + file->offset, -@@ -1224,12 +1214,12 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, - item_size, (char *) indirect_block_ptr); - if (grub_errno) - goto fail; -- len = MIN (len, file->size - file->offset); -+ len = grub_min (len, file->size - file->offset); - for (indirect_block = file->offset / block_size; - indirect_block < indirect_block_count && read_length < len; - indirect_block++) - { -- read = MIN (block_size, len - read_length); -+ read = grub_min (block_size, len - read_length); - grub_disk_read (found.data->disk, - (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE, - file->offset % block_size, read, diff --git a/SOURCES/0268-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch b/SOURCES/0268-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch deleted file mode 100644 index 64bbe31..0000000 --- a/SOURCES/0268-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 24 Mar 2022 14:40:01 -0400 -Subject: [PATCH] misc: make grub_boot_time() also call - grub_dprintf("boot",...) - -Currently grub_boot_time() includes valuable debugging messages, but if -you build without BOOT_TIME_STATS enabled, they are silently and -confusingly compiled away. - -This patch changes grub_boot_time() to also log when "boot" is enabled -in DEBUG, regardless of BOOT_TIME_STATS. - -Signed-off-by: Peter Jones -(cherry picked from commit 4fd282de00df05ce289467861deb7a0e186cfbd7) ---- - grub-core/kern/misc.c | 3 ++- - include/grub/misc.h | 2 +- - 2 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c -index a186ad3dd4..cb45461402 100644 ---- a/grub-core/kern/misc.c -+++ b/grub-core/kern/misc.c -@@ -1334,7 +1334,8 @@ grub_real_boot_time (const char *file, - n->next = 0; - - va_start (args, fmt); -- n->msg = grub_xvasprintf (fmt, args); -+ n->msg = grub_xvasprintf (fmt, args); -+ grub_dprintf ("boot", "%s\n", n->msg); - va_end (args); - - *boot_time_last = n; -diff --git a/include/grub/misc.h b/include/grub/misc.h -index cf84aec1db..faae0ae860 100644 ---- a/include/grub/misc.h -+++ b/include/grub/misc.h -@@ -503,7 +503,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, - const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 3, 4))); - #define grub_boot_time(...) grub_real_boot_time(GRUB_FILE, __LINE__, __VA_ARGS__) - #else --#define grub_boot_time(...) -+#define grub_boot_time(fmt, ...) grub_dprintf("boot", fmt "\n", ##__VA_ARGS__) - #endif - - #define _grub_min(a, b, _a, _b) \ diff --git a/SOURCES/0268-squish-don-t-dup-rhgb-quiet-check-mtimes.patch b/SOURCES/0268-squish-don-t-dup-rhgb-quiet-check-mtimes.patch new file mode 100644 index 0000000..67073ec --- /dev/null +++ b/SOURCES/0268-squish-don-t-dup-rhgb-quiet-check-mtimes.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 17 Aug 2022 10:26:07 -0400 +Subject: [PATCH] squish: don't dup rhgb quiet, check mtimes + +Signed-off-by: Robbie Harwood +--- + util/grub.d/10_linux.in | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 9ebff661a9..41c6cb1dc2 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -161,10 +161,16 @@ update_bls_cmdline() + local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + local -a files=($(get_sorted_bls)) + +- if [[ ! -f /etc/kernel/cmdline ]]; then +- # anaconda has the correct information to do this during install; +- # afterward, grubby will take care of syncing on updates. +- echo "$cmdline rhgb quiet" > /etc/kernel/cmdline ++ if [[ ! -f /etc/kernel/cmdline ]] || ++ [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then ++ # anaconda has the correct information to create this during install; ++ # afterward, grubby will take care of syncing on updates. If the user ++ # has modified /etc/default/grub, try to cope. ++ if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then ++ # ensure these only show up once ++ cmdline="$cmdline rhgb quiet" ++ fi ++ echo "$cmdline" > /etc/kernel/cmdline + fi + + for bls in "${files[@]}"; do diff --git a/SOURCES/0269-modules-make-.module_license-read-only.patch b/SOURCES/0269-modules-make-.module_license-read-only.patch deleted file mode 100644 index 51281a3..0000000 --- a/SOURCES/0269-modules-make-.module_license-read-only.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 24 Feb 2022 16:32:51 -0500 -Subject: [PATCH] modules: make .module_license read-only - -Currently .module_license is set writable (that is, the section has the -SHF_WRITE flag set) in the module's ELF headers. This probably never -actually matters, but it can't possibly be correct. - -This patch sets that data as "const", which causes that flag not to be -set. - -Signed-off-by: Peter Jones -(cherry picked from commit 2eff3e2c9d9e6b75daa81b840c96f112ef7d5de6) ---- - include/grub/dl.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 20d870f2a4..618ae6f474 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -121,7 +121,7 @@ grub_mod_fini (void) - #define ATTRIBUTE_USED __unused__ - #endif - #define GRUB_MOD_LICENSE(license) \ -- static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; -+ static const char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license; - #define GRUB_MOD_DEP(name) \ - static const char grub_module_depend_##name[] \ - __attribute__((section(GRUB_MOD_SECTION(moddeps)), ATTRIBUTE_USED)) = #name diff --git a/SOURCES/0269-squish-give-up-on-rhgb-quiet.patch b/SOURCES/0269-squish-give-up-on-rhgb-quiet.patch new file mode 100644 index 0000000..5858c91 --- /dev/null +++ b/SOURCES/0269-squish-give-up-on-rhgb-quiet.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 17 Aug 2022 11:30:30 -0400 +Subject: [PATCH] squish: give up on rhgb quiet + +Signed-off-by: Robbie Harwood +--- + util/grub.d/10_linux.in | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 41c6cb1dc2..5d1fa072f2 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -166,10 +166,6 @@ update_bls_cmdline() + # anaconda has the correct information to create this during install; + # afterward, grubby will take care of syncing on updates. If the user + # has modified /etc/default/grub, try to cope. +- if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then +- # ensure these only show up once +- cmdline="$cmdline rhgb quiet" +- fi + echo "$cmdline" > /etc/kernel/cmdline + fi + diff --git a/SOURCES/0270-modules-strip-.llvm_addrsig-sections-and-similar.patch b/SOURCES/0270-modules-strip-.llvm_addrsig-sections-and-similar.patch deleted file mode 100644 index 16528e4..0000000 --- a/SOURCES/0270-modules-strip-.llvm_addrsig-sections-and-similar.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 24 Feb 2022 16:40:11 -0500 -Subject: [PATCH] modules: strip .llvm_addrsig sections and similar. - -Currently grub modules built with clang or gcc have several sections -which we don't actually need or support. - -We already have a list of section to skip in genmod.sh, and this patch -adds the following sections to that list (as well as a few newlines): - -.note.gnu.property -.llvm* - -Note that the glob there won't work without a new enough linker, but the -failure is just reversion to the status quo, so that's not a big problem. - -Signed-off-by: Peter Jones -(cherry picked from commit e85d1c4d795f8135ad0acfa36d64760d12d6fed1) ---- - grub-core/genmod.sh.in | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in -index 1250589b3f..c2c5280d75 100644 ---- a/grub-core/genmod.sh.in -+++ b/grub-core/genmod.sh.in -@@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then - @TARGET_STRIP@ --strip-unneeded \ - -K grub_mod_init -K grub_mod_fini \ - -K _grub_mod_init -K _grub_mod_fini \ -- -R .note.gnu.gold-version -R .note.GNU-stack \ -+ -R .note.GNU-stack \ -+ -R .note.gnu.gold-version \ -+ -R .note.gnu.property \ - -R .gnu.build.attributes \ -+ -R '.llvm*' \ - -R .rel.gnu.build.attributes \ - -R .rela.gnu.build.attributes \ - -R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \ diff --git a/SOURCES/0270-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch b/SOURCES/0270-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch new file mode 100644 index 0000000..d5ac923 --- /dev/null +++ b/SOURCES/0270-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Wed, 17 Aug 2022 10:26:03 -0400 +Subject: [PATCH] squish: BLS: only write /etc/kernel/cmdline if writable + +On OSTree systems, `grub2-mkconfig` is run with `/etc` mounted read-only +because as part of the promise of transactional updates, we want to make +sure that we're not modifying the current deployment's state (`/etc` or +`/var`). + +This conflicts with 0837dcdf1 ("BLS: create /etc/kernel/cmdline during +mkconfig") which wants to write to `/etc/kernel/cmdline`. I'm not +exactly sure on the background there, but based on the comment I think +the intent is to fulfill grubby's expectation that the file exists. + +However, in systems like Silverblue, kernel arguments are managed by the +rpm-ostree stack and grubby is not shipped at all. + +Adjust the script slightly so that we only write `/etc/kernel/cmdline` +if the parent directory is writable. + +In the future, we're hoping to simplify things further on rpm-ostree +systems by not running `grub2-mkconfig` at all since libostree already +directly writes BLS entries. Doing that would also have avoided this, +but ratcheting it into existing systems needs more careful thought. + +Signed-off-by: Jonathan Lebon + +Fixes: https://github.com/fedora-silverblue/issue-tracker/issues/322 +--- + util/grub.d/10_linux.in | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 5d1fa072f2..4795a63b4c 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -161,12 +161,13 @@ update_bls_cmdline() + local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + local -a files=($(get_sorted_bls)) + +- if [[ ! -f /etc/kernel/cmdline ]] || +- [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then +- # anaconda has the correct information to create this during install; +- # afterward, grubby will take care of syncing on updates. If the user +- # has modified /etc/default/grub, try to cope. +- echo "$cmdline" > /etc/kernel/cmdline ++ if [ -w /etc/kernel ] && ++ [[ ! -f /etc/kernel/cmdline || ++ /etc/kernel/cmdline -ot /etc/default/grub ]]; then ++ # anaconda has the correct information to create this during install; ++ # afterward, grubby will take care of syncing on updates. If the user ++ # has modified /etc/default/grub, try to cope. ++ echo "$cmdline" > /etc/kernel/cmdline + fi + + for bls in "${files[@]}"; do diff --git a/SOURCES/0271-blscfg-Don-t-root-device-in-emu-builds.patch b/SOURCES/0271-blscfg-Don-t-root-device-in-emu-builds.patch new file mode 100644 index 0000000..3fe8baf --- /dev/null +++ b/SOURCES/0271-blscfg-Don-t-root-device-in-emu-builds.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 25 Aug 2022 17:57:55 -0400 +Subject: [PATCH] blscfg: Don't root device in emu builds + +Otherwise, we end up looking for kernel/initrd in /boot/boot which +doesn't work at all. Non-emu builds need to be looking in +($root)/boot/, which is what this is for. + +Signed-off-by: Robbie Harwood +--- + grub-core/commands/blscfg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c +index e907a6a5d2..dbd0899acf 100644 +--- a/grub-core/commands/blscfg.c ++++ b/grub-core/commands/blscfg.c +@@ -41,7 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + #define GRUB_BLS_CONFIG_PATH "/loader/entries/" + #ifdef GRUB_MACHINE_EMU +-#define GRUB_BOOT_DEVICE "/boot" ++#define GRUB_BOOT_DEVICE "" + #else + #define GRUB_BOOT_DEVICE "($root)" + #endif diff --git a/SOURCES/0271-modules-Don-t-allocate-space-for-non-allocable-secti.patch b/SOURCES/0271-modules-Don-t-allocate-space-for-non-allocable-secti.patch deleted file mode 100644 index 6599406..0000000 --- a/SOURCES/0271-modules-Don-t-allocate-space-for-non-allocable-secti.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 16:56:10 -0400 -Subject: [PATCH] modules: Don't allocate space for non-allocable sections. - -Currently when loading grub modules, we allocate space for all sections, -including those without SHF_ALLOC set. We then copy the sections that -/do/ have SHF_ALLOC set into the allocated memory, leaving some of our -allocation untouched forever. Additionally, on platforms with GOT -fixups and trampolines, we currently compute alignment round-ups for the -sections and sections with sh_size = 0. - -This patch removes the extra space from the allocation computation, and -makes the allocation computation loop skip empty sections as the loading -loop does. - -Signed-off-by: Peter Jones -(cherry picked from commit 03215e342f552396ab08125ea769b1e166417ec1) ---- - grub-core/kern/dl.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index f304494574..aef8af8aa7 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -289,6 +289,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - i < e->e_shnum; - i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) - { -+ if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) -+ continue; -+ - tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; - if (talign < s->sh_addralign) - talign = s->sh_addralign; diff --git a/SOURCES/0272-loader-arm64-linux-Remove-magic-number-header-field-.patch b/SOURCES/0272-loader-arm64-linux-Remove-magic-number-header-field-.patch new file mode 100644 index 0000000..faaa071 --- /dev/null +++ b/SOURCES/0272-loader-arm64-linux-Remove-magic-number-header-field-.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Thu, 11 Aug 2022 16:51:57 +0200 +Subject: [PATCH] loader/arm64/linux: Remove magic number header field check + +The "ARM\x64" magic number in the file header identifies an image as one +that implements the bare metal boot protocol, allowing the loader to +simply move the file to a suitably aligned address in memory, with +sufficient headroom for the trailing .bss segment (the required memory +size is described in the header as well). + +Note of this matters for GRUB, as it only supports EFI boot. EFI does +not care about this magic number, and nor should GRUB: this prevents us +from booting other PE linux images, such as the generic EFI zboot +decompressor, which is a pure PE/COFF image, and does not implement the +bare metal boot protocol. + +So drop the magic number check. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Daniel Kiper +Resolves: rhbz#2125069 +Signed-off-by: Jeremy Linton +(cherry-picked from commit 69edb31205602c29293a8c6e67363bba2a4a1e66) +Signed-off-by: Robbie Harwood +--- + grub-core/loader/arm64/linux.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index de85583487..489d0c7173 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -55,9 +55,6 @@ static grub_addr_t initrd_end; + grub_err_t + grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) + { +- if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) +- return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); +- + if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); diff --git a/SOURCES/0272-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch b/SOURCES/0272-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch deleted file mode 100644 index c3f2e0f..0000000 --- a/SOURCES/0272-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 25 Mar 2022 15:40:12 -0400 -Subject: [PATCH] pe: add the DOS header struct and fix some bad naming. - -In order to properly validate a loaded kernel's support for being loaded -without a writable stack or executable, we need to be able to properly -parse arbitrary PE headers. - -Currently, pe32.h is written in such a way that the MS-DOS header that -tells us where to find the PE header in the binary can't be accessed. -Further, for some reason it calls the DOS MZ magic "GRUB_PE32_MAGIC". - -This patch adds the structure for the DOS header, renames the DOS magic -define, and adds defines for the actual PE magic. - -Signed-off-by: Peter Jones -(cherry picked from commit 955f47aa8300387eecf18b0866d21dde7720593d) ---- - grub-core/loader/arm64/linux.c | 2 +- - include/grub/efi/pe32.h | 28 ++++++++++++++++++++++++++-- - 2 files changed, 27 insertions(+), 3 deletions(-) - -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index f18d90bd74..bcc6ef46e9 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -59,7 +59,7 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) - if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) - return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); - -- if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC) -+ if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); - -diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h -index a43adf2746..2a5e1ee003 100644 ---- a/include/grub/efi/pe32.h -+++ b/include/grub/efi/pe32.h -@@ -46,7 +46,30 @@ - - #define GRUB_PE32_MSDOS_STUB_SIZE 0x80 - --#define GRUB_PE32_MAGIC 0x5a4d -+#define GRUB_DOS_MAGIC 0x5a4d -+ -+struct grub_dos_header -+{ -+ grub_uint16_t magic; -+ grub_uint16_t cblp; -+ grub_uint16_t cp; -+ grub_uint16_t crlc; -+ grub_uint16_t cparhdr; -+ grub_uint16_t minalloc; -+ grub_uint16_t maxalloc; -+ grub_uint16_t ss; -+ grub_uint16_t sp; -+ grub_uint16_t csum; -+ grub_uint16_t ip; -+ grub_uint16_t cs; -+ grub_uint16_t lfarlc; -+ grub_uint16_t ovno; -+ grub_uint16_t res0[4]; -+ grub_uint16_t oemid; -+ grub_uint16_t oeminfo; -+ grub_uint16_t res1[10]; -+ grub_uint32_t lfanew; -+}; - - /* According to the spec, the minimal alignment is 512 bytes... - But some examples (such as EFI drivers in the Intel -@@ -280,7 +303,8 @@ struct grub_pe32_section_table - - - --#define GRUB_PE32_SIGNATURE_SIZE 4 -+#define GRUB_PE32_SIGNATURE_SIZE 4 -+#define GRUB_PE32_SIGNATURE "PE\0\0" - - struct grub_pe32_header - { diff --git a/SOURCES/0273-Correct-BSS-zeroing-on-aarch64.patch b/SOURCES/0273-Correct-BSS-zeroing-on-aarch64.patch new file mode 100644 index 0000000..4f9a2b7 --- /dev/null +++ b/SOURCES/0273-Correct-BSS-zeroing-on-aarch64.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jeremy Linton +Date: Tue, 6 Sep 2022 15:33:03 -0500 +Subject: [PATCH] Correct BSS zeroing on aarch64 + +The aarch64 loader doesn't use efi bootservices, and +therefor it has a very minimal loader which makes a lot +of assumptions about the kernel layout. With the ZBOOT +changes, the layout has changed a bit and we not should +really be parsing the PE sections to determine how much +data to copy, otherwise the BSS won't be setup properly. + +This code still makes a lot of assumptions about the +the kernel layout, so its far from ideal, but it works. + +Resolves: rhbz#2125069 + +Signed-off-by: Jeremy Linton +--- + grub-core/loader/arm64/linux.c | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 489d0c7173..419f2201df 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -316,10 +316,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + static grub_err_t + parse_pe_header (void *kernel, grub_uint64_t *total_size, + grub_uint32_t *entry_offset, +- grub_uint32_t *alignment) ++ grub_uint32_t *alignment,grub_uint32_t *code_size) + { + struct linux_arch_kernel_header *lh = kernel; + struct grub_armxx_linux_pe_header *pe; ++ grub_uint16_t i; ++ struct grub_pe32_section_table *sections; + + pe = (void *)((unsigned long)kernel + lh->hdr_offset); + +@@ -329,6 +331,19 @@ parse_pe_header (void *kernel, grub_uint64_t *total_size, + *total_size = pe->opt.image_size; + *entry_offset = pe->opt.entry_addr; + *alignment = pe->opt.section_alignment; ++ *code_size = pe->opt.section_alignment; ++ ++ sections = (struct grub_pe32_section_table *) ((char *)&pe->opt + ++ pe->coff.optional_header_size); ++ grub_dprintf ("linux", "num_sections : %d\n", pe->coff.num_sections ); ++ for (i = 0 ; i < pe->coff.num_sections; i++) ++ { ++ grub_dprintf ("linux", "raw_size : %lld\n", ++ (long long) sections[i].raw_data_size); ++ grub_dprintf ("linux", "virt_size : %lld\n", ++ (long long) sections[i].virtual_size); ++ *code_size += sections[i].raw_data_size; ++ } + + return GRUB_ERR_NONE; + } +@@ -341,6 +356,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_err_t err; + grub_off_t filelen; + grub_uint32_t align; ++ grub_uint32_t code_size; + void *kernel = NULL; + int nx_supported = 1; + +@@ -373,11 +389,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) + goto fail; +- if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) ++ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align, &code_size) != GRUB_ERR_NONE) + goto fail; + grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); + grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); + grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); ++ grub_dprintf ("linux", "kernel size : 0x%x\n", code_size); + + err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); + if (err != GRUB_ERR_NONE) +@@ -396,9 +413,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); +- grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); +- if (kernel_size > filelen) +- grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); ++ grub_memcpy (kernel_addr, kernel, grub_min(code_size, kernel_size)); ++ if (kernel_size > code_size) ++ grub_memset ((char *)kernel_addr + code_size, 0, kernel_size - code_size); + grub_free(kernel); + kernel = NULL; + diff --git a/SOURCES/0273-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch b/SOURCES/0273-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch deleted file mode 100644 index b306f15..0000000 --- a/SOURCES/0273-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 9 Feb 2022 16:08:20 -0500 -Subject: [PATCH] EFI: allocate kernel in EFI_RUNTIME_SERVICES_CODE instead of - EFI_LOADER_DATA. - -On some of the firmwares with more security mitigations, EFI_LOADER_DATA -doesn't get you executable memory, and we take a fault and reboot when -we enter kernel. - -This patch correctly allocates the kernel code as EFI_RUNTIME_SERVICES_CODE -rather than EFI_LOADER_DATA. - -Signed-off-by: Peter Jones -[rharwood: use kernel_size] -Signed-off-by: Robbie Harwood -(cherry picked from commit 8b31058a12d3e85f0f0180ac90b98d6465fccbb7) ---- - grub-core/loader/i386/efi/linux.c | 19 +++++++++++++------ - 1 file changed, 13 insertions(+), 6 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index d24553a79d..b832c85728 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -87,7 +87,9 @@ kernel_free(void *addr, grub_efi_uintn_t size) - } - - static void * --kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) -+kernel_alloc(grub_efi_uintn_t size, -+ grub_efi_memory_type_t memtype, -+ const char * const errmsg) - { - void *addr = 0; - unsigned int i; -@@ -113,7 +115,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg) - prev_max = max; - addr = grub_efi_allocate_pages_real (max, pages, - max_addresses[i].alloc_type, -- GRUB_EFI_LOADER_DATA); -+ memtype); - if (addr) - grub_dprintf ("linux", "Allocated at %p\n", addr); - } -@@ -243,7 +245,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - } - -- initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); -+ initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, -+ N_("can't allocate initrd")); - if (initrd_mem == NULL) - goto fail; - grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem); -@@ -406,7 +409,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -- params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters"); -+ params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, -+ "cannot allocate kernel parameters"); - if (!params) - goto fail; - grub_dprintf ("linux", "params = %p\n", params); -@@ -428,7 +432,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "new lh is at %p\n", lh); - - grub_dprintf ("linux", "setting up cmdline\n"); -- cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline")); -+ cmdline = kernel_alloc (lh->cmdline_size + 1, -+ GRUB_EFI_RUNTIME_SERVICES_DATA, -+ N_("can't allocate cmdline")); - if (!cmdline) - goto fail; - grub_dprintf ("linux", "cmdline = %p\n", cmdline); -@@ -474,7 +480,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - kernel_size = lh->init_size; -- kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel")); -+ kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, -+ N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) - goto fail; diff --git a/SOURCES/0274-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch b/SOURCES/0274-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch new file mode 100644 index 0000000..eff155d --- /dev/null +++ b/SOURCES/0274-linuxefi-Invalidate-i-cache-before-starting-the-kern.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dann frazier +Date: Thu, 25 Aug 2022 17:08:09 -0600 +Subject: [PATCH] linuxefi: Invalidate i-cache before starting the kernel + +We need to flush the memory range of the code we are about to execute +from the instruction cache before we can safely execute it. Not doing +so appears to be the source of rare synchronous exceptions a user +is seeing on a Cortex-A72-based platform while executing the Linux EFI +stub. Notably they seem to correlate with an instruction on a cache +line boundary. + +Signed-off-by: dann frazier +--- + grub-core/loader/efi/linux.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 277f352e0c..e413bdcc23 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -16,6 +16,7 @@ + * along with GRUB. If not, see . + */ + ++#include + #include + #include + #include +@@ -210,6 +211,9 @@ grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, + asm volatile ("cli"); + #endif + ++ /* Invalidate the instruction cache */ ++ grub_arch_sync_caches((void *)kernel_addr, kernel_size); ++ + hf = (handover_func)((char *)kernel_addr + handover_offset + offset); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); + diff --git a/SOURCES/0274-modules-load-module-sections-at-page-aligned-address.patch b/SOURCES/0274-modules-load-module-sections-at-page-aligned-address.patch deleted file mode 100644 index 1c703d8..0000000 --- a/SOURCES/0274-modules-load-module-sections-at-page-aligned-address.patch +++ /dev/null @@ -1,379 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 17:45:40 -0400 -Subject: [PATCH] modules: load module sections at page-aligned addresses - -Currently we load module sections at whatever alignment gcc+ld happened -to dump into the ELF section header, which is often pretty useless. For -example, by default time.mod has these sections on a current x86_64 -build: - -$ eu-readelf -a grub-core/time.mod |& grep ^Section -A13 -Section Headers: -[Nr] Name Type Addr Off Size ES Flags Lk Inf Al -[ 0] NULL 0 00000000 00000000 0 0 0 0 -[ 1] .text PROGBITS 0 00000040 0000015e 0 AX 0 0 1 -[ 2] .rela.text RELA 0 00000458 000001e0 24 I 8 1 8 -[ 3] .rodata.str1.1 PROGBITS 0 0000019e 000000a1 1 AMS 0 0 1 -[ 4] .module_license PROGBITS 0 00000240 0000000f 0 A 0 0 8 -[ 5] .data PROGBITS 0 0000024f 00000000 0 WA 0 0 1 -[ 6] .bss NOBITS 0 00000250 00000008 0 WA 0 0 8 -[ 7] .modname PROGBITS 0 00000250 00000005 0 0 0 1 -[ 8] .symtab SYMTAB 0 00000258 00000150 24 9 6 8 -[ 9] .strtab STRTAB 0 000003a8 000000ab 0 0 0 1 -[10] .shstrtab STRTAB 0 00000638 00000059 0 0 0 1 - -With NX protections being page based, loading sections with either a 1 -or 8 *byte* alignment does absolutely nothing to help us out. - -This patch switches most EFI platforms to load module sections at 4kB -page-aligned addresses. To do so, it adds an new per-arch function, -grub_arch_dl_min_alignment(), which returns the alignment needed for -dynamically loaded sections (in bytes). Currently it sets it to 4096 -when GRUB_MACHINE_EFI is true on x86_64, i386, arm, arm64, and emu, and -1-byte alignment on everything else. - -It then changes the allocation size computation and the loader code in -grub_dl_load_segments() to align the locations and sizes up to these -boundaries, and fills any added padding with zeros. - -All of this happens before relocations are applied, so the relocations -factor that in with no change. - -As an aside, initially Daniel Kiper and I thought that it might be a -better idea to split the modules up into top-level sections as -.text.modules, .rodata.modules, .data.modules, etc., so that their page -permissions would get set by the loader that's loading grub itself. -This turns out to have two significant downsides: 1) either in mkimage -or in grub_dl_relocate_symbols(), you wind up having to dynamically -process the relocations to accommodate the moved module sections, and 2) -you then need to change the permissions on the modules and change them -back while relocating them in grub_dl_relocate_symbols(), which means -that any loader that /does/ honor the section flags but does /not/ -generally support NX with the memory attributes API will cause grub to -fail. - -Signed-off-by: Peter Jones -(cherry picked from commit 31d52500b281619d92b03b2c2d30fe15aedaf326) ---- - grub-core/kern/arm/dl.c | 13 +++++++++++++ - grub-core/kern/arm64/dl.c | 13 +++++++++++++ - grub-core/kern/dl.c | 29 +++++++++++++++++++++-------- - grub-core/kern/emu/full.c | 13 +++++++++++++ - grub-core/kern/i386/dl.c | 13 +++++++++++++ - grub-core/kern/ia64/dl.c | 9 +++++++++ - grub-core/kern/mips/dl.c | 8 ++++++++ - grub-core/kern/powerpc/dl.c | 9 +++++++++ - grub-core/kern/riscv/dl.c | 13 +++++++++++++ - grub-core/kern/sparc64/dl.c | 9 +++++++++ - grub-core/kern/x86_64/dl.c | 13 +++++++++++++ - include/grub/dl.h | 2 ++ - docs/grub-dev.texi | 6 +++--- - 13 files changed, 139 insertions(+), 11 deletions(-) - -diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c -index eab9d17ff2..9260737936 100644 ---- a/grub-core/kern/arm/dl.c -+++ b/grub-core/kern/arm/dl.c -@@ -278,3 +278,16 @@ grub_arch_dl_check_header (void *ehdr) - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c -index 512e5a80b0..0d4a26857f 100644 ---- a/grub-core/kern/arm64/dl.c -+++ b/grub-core/kern/arm64/dl.c -@@ -196,3 +196,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index aef8af8aa7..8c7aacef39 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -277,7 +277,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - { - unsigned i; - const Elf_Shdr *s; -- grub_size_t tsize = 0, talign = 1; -+ grub_size_t tsize = 0, talign = 1, arch_addralign = 1; - #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) - grub_size_t tramp; - grub_size_t got; -@@ -285,16 +285,24 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - #endif - char *ptr; - -+ arch_addralign = grub_arch_dl_min_alignment (); -+ - for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) - { -+ grub_size_t sh_addralign; -+ grub_size_t sh_size; -+ - if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) - continue; - -- tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; -- if (talign < s->sh_addralign) -- talign = s->sh_addralign; -+ sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); -+ sh_size = ALIGN_UP(s->sh_size, sh_addralign); -+ -+ tsize = ALIGN_UP (tsize, sh_addralign) + sh_size; -+ if (talign < sh_addralign) -+ talign = sh_addralign; - } - - #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) -@@ -323,6 +331,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - i < e->e_shnum; - i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) - { -+ grub_size_t sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); -+ grub_size_t sh_size = ALIGN_UP(s->sh_size, sh_addralign); -+ - if (s->sh_flags & SHF_ALLOC) - { - grub_dl_segment_t seg; -@@ -335,17 +346,19 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - { - void *addr; - -- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign); -+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign); - addr = ptr; -- ptr += s->sh_size; -+ ptr += sh_size; - - switch (s->sh_type) - { - case SHT_PROGBITS: - grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size); -+ grub_memset ((char *)addr + s->sh_size, 0, -+ sh_size - s->sh_size); - break; - case SHT_NOBITS: -- grub_memset (addr, 0, s->sh_size); -+ grub_memset (addr, 0, sh_size); - break; - } - -@@ -354,7 +367,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - else - seg->addr = 0; - -- seg->size = s->sh_size; -+ seg->size = sh_size; - seg->section = i; - seg->next = mod->segment; - mod->segment = seg; -diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c -index e8d63b1f5f..1de1c28eb0 100644 ---- a/grub-core/kern/emu/full.c -+++ b/grub-core/kern/emu/full.c -@@ -67,3 +67,16 @@ grub_arch_dl_init_linker (void) - } - #endif - -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c -index 1346da5cc9..d6b4681fc9 100644 ---- a/grub-core/kern/i386/dl.c -+++ b/grub-core/kern/i386/dl.c -@@ -79,3 +79,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c -index db59300fea..92d82c5750 100644 ---- a/grub-core/kern/ia64/dl.c -+++ b/grub-core/kern/ia64/dl.c -@@ -148,3 +148,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - } - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c -index 5d7d299c74..6d83bd71e9 100644 ---- a/grub-core/kern/mips/dl.c -+++ b/grub-core/kern/mips/dl.c -@@ -272,3 +272,11 @@ grub_arch_dl_init_linker (void) - grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0); - } - -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c -index cdd61b305f..5d9ba2e158 100644 ---- a/grub-core/kern/powerpc/dl.c -+++ b/grub-core/kern/powerpc/dl.c -@@ -167,3 +167,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c -index f26b12aaa4..aa18f9e990 100644 ---- a/grub-core/kern/riscv/dl.c -+++ b/grub-core/kern/riscv/dl.c -@@ -343,3 +343,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c -index f3d960186b..f054f08241 100644 ---- a/grub-core/kern/sparc64/dl.c -+++ b/grub-core/kern/sparc64/dl.c -@@ -189,3 +189,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+ return 1; -+} -diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c -index e5a8bdcf4f..a105dc50ce 100644 ---- a/grub-core/kern/x86_64/dl.c -+++ b/grub-core/kern/x86_64/dl.c -@@ -119,3 +119,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - - return GRUB_ERR_NONE; - } -+ -+/* -+ * Tell the loader what our minimum section alignment is. -+ */ -+grub_size_t -+grub_arch_dl_min_alignment (void) -+{ -+#ifdef GRUB_MACHINE_EFI -+ return 4096; -+#else -+ return 1; -+#endif -+} -diff --git a/include/grub/dl.h b/include/grub/dl.h -index 618ae6f474..f36ed5cb17 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -280,6 +280,8 @@ grub_err_t grub_arch_dl_check_header (void *ehdr); - grub_err_t - grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - Elf_Shdr *s, grub_dl_segment_t seg); -+grub_size_t -+grub_arch_dl_min_alignment (void); - #endif - - #if defined (_mips) -diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi -index 90083772c8..c23ba313dc 100644 ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -755,9 +755,9 @@ declare startup asm file ($cpu_$platform_startup) as well as any other files - (e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c). - At this stage you will also need to add dummy dl.c and cache.S with functions - grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t --grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and --void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They --won't be used for now. -+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c), grub_uint32_t -+grub_arch_dl_min_alignment (void), and void grub_arch_sync_caches (void -+*address, grub_size_t len) (cache.S). They won't be used for now. - - You will need to create directory include/$cpu/$platform and a file - include/$cpu/types.h. The later folowing this template: diff --git a/SOURCES/0275-nx-add-memory-attribute-get-set-API.patch b/SOURCES/0275-nx-add-memory-attribute-get-set-API.patch deleted file mode 100644 index 9146ba1..0000000 --- a/SOURCES/0275-nx-add-memory-attribute-get-set-API.patch +++ /dev/null @@ -1,318 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 22 Mar 2022 10:56:21 -0400 -Subject: [PATCH] nx: add memory attribute get/set API - -For NX, we need to set the page access permission attributes for write -and execute permissions. - -This patch adds two new primitives, grub_set_mem_attrs() and -grub_clear_mem_attrs(), and associated constant definitions, to be used -for that purpose. - -For most platforms, it adds a dummy implementation that returns -GRUB_ERR_NONE. On EFI platforms, it adds a common helper function, -grub_efi_status_to_err(), which translates EFI error codes to grub error -codes, adds headers for the EFI Memory Attribute Protocol (still pending -standardization), and an implementation of the grub nx primitives using -it. - -Signed-off-by: Peter Jones -[rharwood: add pjones's none/nyi fixup] -Signed-off-by: Robbie Harwood -(cherry picked from commit 35de78a8d32b9fad5291ec96fd3cbb9cf2f4a80b) ---- - grub-core/kern/efi/efi.c | 36 +++++++++++++ - grub-core/kern/efi/mm.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ - include/grub/efi/api.h | 25 +++++++++ - include/grub/efi/efi.h | 2 + - include/grub/mm.h | 32 ++++++++++++ - 5 files changed, 226 insertions(+) - -diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c -index 7fcca69c17..4ac2b2754e 100644 ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -1096,3 +1096,39 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, - - return 0; - } -+ -+grub_err_t -+grub_efi_status_to_err (grub_efi_status_t status) -+{ -+ grub_err_t err; -+ switch (status) -+ { -+ case GRUB_EFI_SUCCESS: -+ err = GRUB_ERR_NONE; -+ break; -+ case GRUB_EFI_INVALID_PARAMETER: -+ default: -+ err = GRUB_ERR_BAD_ARGUMENT; -+ break; -+ case GRUB_EFI_OUT_OF_RESOURCES: -+ err = GRUB_ERR_OUT_OF_MEMORY; -+ break; -+ case GRUB_EFI_DEVICE_ERROR: -+ err = GRUB_ERR_IO; -+ break; -+ case GRUB_EFI_WRITE_PROTECTED: -+ err = GRUB_ERR_WRITE_ERROR; -+ break; -+ case GRUB_EFI_SECURITY_VIOLATION: -+ err = GRUB_ERR_ACCESS_DENIED; -+ break; -+ case GRUB_EFI_NOT_FOUND: -+ err = GRUB_ERR_FILE_NOT_FOUND; -+ break; -+ case GRUB_EFI_ABORTED: -+ err = GRUB_ERR_WAIT; -+ break; -+ } -+ -+ return err; -+} -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index e84961d078..2c33758ed7 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -738,3 +738,134 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) - return GRUB_ERR_NONE; - } - #endif -+ -+static inline grub_uint64_t -+grub_mem_attrs_to_uefi_mem_attrs (grub_uint64_t attrs) -+{ -+ grub_uint64_t ret = GRUB_EFI_MEMORY_RP | -+ GRUB_EFI_MEMORY_RO | -+ GRUB_EFI_MEMORY_XP; -+ -+ if (attrs & GRUB_MEM_ATTR_R) -+ ret &= ~GRUB_EFI_MEMORY_RP; -+ -+ if (attrs & GRUB_MEM_ATTR_W) -+ ret &= ~GRUB_EFI_MEMORY_RO; -+ -+ if (attrs & GRUB_MEM_ATTR_X) -+ ret &= ~GRUB_EFI_MEMORY_XP; -+ -+ return ret; -+} -+ -+static inline grub_uint64_t -+uefi_mem_attrs_to_grub_mem_attrs (grub_uint64_t attrs) -+{ -+ grub_uint64_t ret = GRUB_MEM_ATTR_R | -+ GRUB_MEM_ATTR_W | -+ GRUB_MEM_ATTR_X; -+ -+ if (attrs & GRUB_EFI_MEMORY_RP) -+ ret &= ~GRUB_MEM_ATTR_R; -+ -+ if (attrs & GRUB_EFI_MEMORY_RO) -+ ret &= ~GRUB_MEM_ATTR_W; -+ -+ if (attrs & GRUB_EFI_MEMORY_XP) -+ ret &= ~GRUB_MEM_ATTR_X; -+ -+ return ret; -+} -+ -+grub_err_t -+grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_uint64_t *attrs) -+{ -+ grub_efi_memory_attribute_protocol_t *proto; -+ grub_efi_physical_address_t physaddr = addr; -+ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; -+ grub_efi_status_t efi_status; -+ -+ proto = grub_efi_locate_protocol (&protocol_guid, 0); -+ if (!proto) -+ return GRUB_ERR_NOT_IMPLEMENTED_YET; -+ -+ if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL) -+ { -+ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" and attrs %p\n", -+ __func__, physaddr, physaddr+size-1, attrs); -+ return 0; -+ } -+ -+ efi_status = efi_call_4(proto->get_memory_attributes, -+ proto, physaddr, size, attrs); -+ *attrs = uefi_mem_attrs_to_grub_mem_attrs (*attrs); -+ -+ return grub_efi_status_to_err (efi_status); -+} -+ -+grub_err_t -+grub_update_mem_attrs (grub_addr_t addr, grub_size_t size, -+ grub_uint64_t set_attrs, grub_uint64_t clear_attrs) -+{ -+ grub_efi_memory_attribute_protocol_t *proto; -+ grub_efi_physical_address_t physaddr = addr; -+ grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; -+ grub_efi_status_t efi_status = GRUB_EFI_SUCCESS; -+ grub_uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs; -+ grub_err_t err; -+ -+ proto = grub_efi_locate_protocol (&protocol_guid, 0); -+ if (!proto) -+ return GRUB_ERR_NONE; -+ -+ err = grub_get_mem_attrs (addr, size, &before); -+ if (err) -+ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", -+ addr, size, &before, err); -+ -+ if (physaddr & 0xfff || size & 0xfff || size == 0) -+ { -+ grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" +%s%s%s -%s%s%s\n", -+ __func__, physaddr, physaddr + size - 1, -+ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); -+ return 0; -+ } -+ -+ uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs); -+ grub_dprintf ("nx", "translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs); -+ uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs); -+ grub_dprintf ("nx", "translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs); -+ if (uefi_set_attrs) -+ efi_status = efi_call_4(proto->set_memory_attributes, -+ proto, physaddr, size, uefi_set_attrs); -+ if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs) -+ efi_status = efi_call_4(proto->clear_memory_attributes, -+ proto, physaddr, size, uefi_clear_attrs); -+ -+ err = grub_get_mem_attrs (addr, size, &after); -+ if (err) -+ grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n", -+ addr, size, &after, err); -+ -+ grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" before:%c%c%c after:%c%c%c\n", -+ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ addr, addr + size - 1, -+ (before & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (before & GRUB_MEM_ATTR_W) ? 'w' : '-', -+ (before & GRUB_MEM_ATTR_X) ? 'x' : '-', -+ (after & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (after & GRUB_MEM_ATTR_W) ? 'w' : '-', -+ (after & GRUB_MEM_ATTR_X) ? 'x' : '-'); -+ -+ return grub_efi_status_to_err (efi_status); -+} -diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h -index f431f49973..464842ba37 100644 ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -363,6 +363,11 @@ - { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ - } - -+#define GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID \ -+ { 0xf4560cf6, 0x40ec, 0x4b4a, \ -+ { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \ -+ } -+ - struct grub_efi_sal_system_table - { - grub_uint32_t signature; -@@ -2102,6 +2107,26 @@ struct grub_efi_ip6_config_manual_address { - }; - typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; - -+struct grub_efi_memory_attribute_protocol -+{ -+ grub_efi_status_t (*get_memory_attributes) ( -+ struct grub_efi_memory_attribute_protocol *this, -+ grub_efi_physical_address_t base_address, -+ grub_efi_uint64_t length, -+ grub_efi_uint64_t *attributes); -+ grub_efi_status_t (*set_memory_attributes) ( -+ struct grub_efi_memory_attribute_protocol *this, -+ grub_efi_physical_address_t base_address, -+ grub_efi_uint64_t length, -+ grub_efi_uint64_t attributes); -+ grub_efi_status_t (*clear_memory_attributes) ( -+ struct grub_efi_memory_attribute_protocol *this, -+ grub_efi_physical_address_t base_address, -+ grub_efi_uint64_t length, -+ grub_efi_uint64_t attributes); -+}; -+typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t; -+ - #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ - || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ - || defined(__riscv) -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index ec52083c49..34825c4adc 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -164,4 +164,6 @@ struct grub_net_card; - grub_efi_handle_t - grub_efinet_get_device_handle (struct grub_net_card *card); - -+grub_err_t EXPORT_FUNC(grub_efi_status_to_err) (grub_efi_status_t status); -+ - #endif /* ! GRUB_EFI_EFI_HEADER */ -diff --git a/include/grub/mm.h b/include/grub/mm.h -index 9c38dd3ca5..d81623d226 100644 ---- a/include/grub/mm.h -+++ b/include/grub/mm.h -@@ -22,6 +22,7 @@ - - #include - #include -+#include - #include - - #ifndef NULL -@@ -38,6 +39,37 @@ void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size); - void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size); - #endif - -+#define GRUB_MEM_ATTR_R 0x0000000000000004LLU -+#define GRUB_MEM_ATTR_W 0x0000000000000002LLU -+#define GRUB_MEM_ATTR_X 0x0000000000000001LLU -+ -+#ifdef GRUB_MACHINE_EFI -+grub_err_t EXPORT_FUNC(grub_get_mem_attrs) (grub_addr_t addr, -+ grub_size_t size, -+ grub_uint64_t *attrs); -+grub_err_t EXPORT_FUNC(grub_update_mem_attrs) (grub_addr_t addr, -+ grub_size_t size, -+ grub_uint64_t set_attrs, -+ grub_uint64_t clear_attrs); -+#else /* !GRUB_MACHINE_EFI */ -+static inline grub_err_t -+grub_get_mem_attrs (grub_addr_t addr __attribute__((__unused__)), -+ grub_size_t size __attribute__((__unused__)), -+ grub_uint64_t *attrs __attribute__((__unused__))) -+{ -+ return GRUB_ERR_NONE; -+} -+ -+static inline grub_err_t -+grub_update_mem_attrs (grub_addr_t addr __attribute__((__unused__)), -+ grub_size_t size __attribute__((__unused__)), -+ grub_uint64_t set_attrs __attribute__((__unused__)), -+ grub_uint64_t clear_attrs __attribute__((__unused__))) -+{ -+ return GRUB_ERR_NONE; -+} -+#endif /* GRUB_MACHINE_EFI */ -+ - void grub_mm_check_real (const char *file, int line); - #define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__); - diff --git a/SOURCES/0275-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch b/SOURCES/0275-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch new file mode 100644 index 0000000..0079750 --- /dev/null +++ b/SOURCES/0275-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 11 Oct 2022 17:00:50 -0400 +Subject: [PATCH] x86-efi: Fix an incorrect array size in kernel allocation + +In 81a6ebf62bbe166ddc968463df2e8bd481bf697c ("efi: split allocation +policy for kernel vs initrd memories."), I introduced a split in the +kernel allocator to allow for different dynamic policies for the kernel +and the initrd allocations. + +Unfortunately, that change increased the size of the policy data used to +make decisions, but did not change the size of the temporary storage we +use to back it up and restore. This results in some of .data getting +clobbered at runtime, and hilarity ensues. + +This patch makes the size of the backup storage be based on the size of +the initial policy data. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index ac5ef50bdb..9854b0defa 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -92,7 +92,7 @@ static struct allocation_choice max_addresses[] = + { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, + { NO_MEM, 0, 0 } + }; +-static struct allocation_choice saved_addresses[4]; ++static struct allocation_choice saved_addresses[sizeof(max_addresses) / sizeof(max_addresses[0])]; + + #define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses)) + #define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses)) diff --git a/SOURCES/0276-commands-efi-tpm-Refine-the-status-of-log-event.patch b/SOURCES/0276-commands-efi-tpm-Refine-the-status-of-log-event.patch new file mode 100644 index 0000000..896e49b --- /dev/null +++ b/SOURCES/0276-commands-efi-tpm-Refine-the-status-of-log-event.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lu Ken +Date: Wed, 13 Jul 2022 10:06:10 +0800 +Subject: [PATCH] commands/efi/tpm: Refine the status of log event + +1. Use macro GRUB_ERR_NONE instead of hard code 0. +2. Keep lowercase of the first char for the status string of log event. + +Signed-off-by: Lu Ken +Reviewed-by: Daniel Kiper +(cherry picked from commit 922898573e37135f5dedc16f3e15a1d1d4c53f8a) +--- + grub-core/commands/efi/tpm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c +index a97d85368a..7acf510499 100644 +--- a/grub-core/commands/efi/tpm.c ++++ b/grub-core/commands/efi/tpm.c +@@ -135,17 +135,17 @@ grub_efi_log_event_status (grub_efi_status_t status) + switch (status) + { + case GRUB_EFI_SUCCESS: +- return 0; ++ return GRUB_ERR_NONE; + case GRUB_EFI_DEVICE_ERROR: +- return grub_error (GRUB_ERR_IO, N_("Command failed")); ++ return grub_error (GRUB_ERR_IO, N_("command failed")); + case GRUB_EFI_INVALID_PARAMETER: +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter")); + case GRUB_EFI_BUFFER_TOO_SMALL: +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small")); + case GRUB_EFI_NOT_FOUND: + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); + default: +- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unknown TPM error")); + } + } + diff --git a/SOURCES/0276-nx-set-page-permissions-for-loaded-modules.patch b/SOURCES/0276-nx-set-page-permissions-for-loaded-modules.patch deleted file mode 100644 index ad3c2aa..0000000 --- a/SOURCES/0276-nx-set-page-permissions-for-loaded-modules.patch +++ /dev/null @@ -1,264 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 21 Mar 2022 17:46:35 -0400 -Subject: [PATCH] nx: set page permissions for loaded modules. - -For NX, we need to set write and executable permissions on the sections -of grub modules when we load them. - -On sections with SHF_ALLOC set, which is typically everything except -.modname and the symbol and string tables, this patch clears the Read -Only flag on sections that have the ELF flag SHF_WRITE set, and clears -the No eXecute flag on sections with SHF_EXECINSTR set. In all other -cases it sets both flags. - -Signed-off-by: Peter Jones -[rharwood: arm tgptr -> tgaddr] -Signed-off-by: Robbie Harwood -(cherry-picked from commit ca74904ede0406b594cbedc52ce8e38a6633d2ae) ---- - grub-core/kern/dl.c | 120 +++++++++++++++++++++++++++++++++++++++------------- - include/grub/dl.h | 44 +++++++++++++++++++ - 2 files changed, 134 insertions(+), 30 deletions(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 8c7aacef39..d5de80186f 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -285,6 +285,8 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - #endif - char *ptr; - -+ grub_dprintf ("modules", "loading segments for \"%s\"\n", mod->name); -+ - arch_addralign = grub_arch_dl_min_alignment (); - - for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); -@@ -384,6 +386,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) - ptr += got; - #endif - -+ grub_dprintf ("modules", "done loading segments for \"%s\"\n", mod->name); - return GRUB_ERR_NONE; - } - -@@ -517,23 +520,6 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name) - return s; - return NULL; - } --static long --grub_dl_find_section_index (Elf_Ehdr *e, const char *name) --{ -- Elf_Shdr *s; -- const char *str; -- unsigned i; -- -- s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); -- str = (char *) e + s->sh_offset; -- -- for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); -- i < e->e_shnum; -- i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -- if (grub_strcmp (str + s->sh_name, name) == 0) -- return (long)i; -- return -1; --} - - /* Me, Vladimir Serbinenko, hereby I add this module check as per new - GNU module policy. Note that this license check is informative only. -@@ -662,6 +648,7 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) - Elf_Shdr *s; - unsigned i; - -+ grub_dprintf ("modules", "relocating symbols for \"%s\"\n", mod->name); - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -@@ -670,24 +657,95 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) - grub_dl_segment_t seg; - grub_err_t err; - -- /* Find the target segment. */ -- for (seg = mod->segment; seg; seg = seg->next) -- if (seg->section == s->sh_info) -- break; -+ seg = grub_dl_find_segment(mod, s->sh_info); -+ if (!seg) -+ continue; - -- if (seg) -- { -- if (!mod->symtab) -- return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); -+ if (!mod->symtab) -+ return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); - -- err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); -- if (err) -- return err; -- } -+ err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); -+ if (err) -+ return err; - } - -+ grub_dprintf ("modules", "done relocating symbols for \"%s\"\n", mod->name); - return GRUB_ERR_NONE; - } -+ -+static grub_err_t -+grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr) -+{ -+ unsigned i; -+ const Elf_Shdr *s; -+ const Elf_Ehdr *e = ehdr; -+#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) -+ grub_size_t arch_addralign = grub_arch_dl_min_alignment (); -+ grub_addr_t tgaddr; -+ grub_uint64_t tgsz; -+#endif -+ -+ grub_dprintf ("modules", "updating memory attributes for \"%s\"\n", -+ mod->name); -+ for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); -+ i < e->e_shnum; -+ i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) -+ { -+ grub_dl_segment_t seg; -+ grub_uint64_t set_attrs = GRUB_MEM_ATTR_R; -+ grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X; -+ -+ seg = grub_dl_find_segment(mod, i); -+ if (!seg) -+ continue; -+ -+ if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC)) -+ continue; -+ -+ if (s->sh_flags & SHF_WRITE) -+ { -+ set_attrs |= GRUB_MEM_ATTR_W; -+ clear_attrs &= ~GRUB_MEM_ATTR_W; -+ } -+ -+ if (s->sh_flags & SHF_EXECINSTR) -+ { -+ set_attrs |= GRUB_MEM_ATTR_X; -+ clear_attrs &= ~GRUB_MEM_ATTR_X; -+ } -+ -+ grub_dprintf ("modules", "setting memory attrs for section \"%s\" to -%s%s%s+%s%s%s\n", -+ grub_dl_get_section_name(e, s), -+ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", -+ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", -+ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", -+ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : ""); -+ grub_update_mem_attrs ((grub_addr_t)(seg->addr), seg->size, set_attrs, clear_attrs); -+ } -+ -+#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) -+ tgaddr = grub_min((grub_addr_t)mod->tramp, (grub_addr_t)mod->got); -+ tgsz = grub_max((grub_addr_t)mod->trampptr, (grub_addr_t)mod->gotptr) - tgaddr; -+ -+ if (tgsz) -+ { -+ tgsz = ALIGN_UP(tgsz, arch_addralign); -+ -+ grub_dprintf ("modules", "updating attributes for GOT and trampolines\n", -+ mod->name); -+ grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X, -+ GRUB_MEM_ATTR_W); -+ } -+#endif -+ -+ grub_dprintf ("modules", "done updating module memory attributes for \"%s\"\n", -+ mod->name); -+ -+ return GRUB_ERR_NONE; -+} -+ - static void - grub_dl_print_gdb_info (grub_dl_t mod, Elf_Ehdr *e) - { -@@ -753,6 +811,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) - mod->ref_count = 1; - - grub_dprintf ("modules", "relocating to %p\n", mod); -+ - /* Me, Vladimir Serbinenko, hereby I add this module check as per new - GNU module policy. Note that this license check is informative only. - Modules have to be licensed under GPLv3 or GPLv3+ (optionally -@@ -766,7 +825,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) - || grub_dl_resolve_dependencies (mod, e) - || grub_dl_load_segments (mod, e) - || grub_dl_resolve_symbols (mod, e) -- || grub_dl_relocate_symbols (mod, e)) -+ || grub_dl_relocate_symbols (mod, e) -+ || grub_dl_set_mem_attrs (mod, e)) - { - mod->fini = 0; - grub_dl_unload (mod); -diff --git a/include/grub/dl.h b/include/grub/dl.h -index f36ed5cb17..45ac8e339f 100644 ---- a/include/grub/dl.h -+++ b/include/grub/dl.h -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #endif - - /* -@@ -268,6 +269,49 @@ grub_dl_is_persistent (grub_dl_t mod) - return mod->persistent; - } - -+static inline const char * -+grub_dl_get_section_name (const Elf_Ehdr *e, const Elf_Shdr *s) -+{ -+ Elf_Shdr *str_s; -+ const char *str; -+ -+ str_s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); -+ str = (char *) e + str_s->sh_offset; -+ -+ return str + s->sh_name; -+} -+ -+static inline long -+grub_dl_find_section_index (Elf_Ehdr *e, const char *name) -+{ -+ Elf_Shdr *s; -+ const char *str; -+ unsigned i; -+ -+ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); -+ str = (char *) e + s->sh_offset; -+ -+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); -+ i < e->e_shnum; -+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) -+ if (grub_strcmp (str + s->sh_name, name) == 0) -+ return (long)i; -+ return -1; -+} -+ -+/* Return the segment for a section of index N */ -+static inline grub_dl_segment_t -+grub_dl_find_segment (grub_dl_t mod, unsigned n) -+{ -+ grub_dl_segment_t seg; -+ -+ for (seg = mod->segment; seg; seg = seg->next) -+ if (seg->section == n) -+ return seg; -+ -+ return NULL; -+} -+ - #endif - - void * EXPORT_FUNC(grub_resolve_symbol) (const char *name); diff --git a/SOURCES/0277-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch b/SOURCES/0277-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch new file mode 100644 index 0000000..e04dcbc --- /dev/null +++ b/SOURCES/0277-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lu Ken +Date: Wed, 13 Jul 2022 10:06:11 +0800 +Subject: [PATCH] commands/efi/tpm: Use grub_strcpy() instead of grub_memcpy() + +The event description is a string, so using grub_strcpy() is cleaner than +using grub_memcpy(). + +Signed-off-by: Lu Ken +Reviewed-by: Daniel Kiper +(cherry picked from commit ef8679b645a63eb9eb191bb9539d7d25a9d6ff3b) +--- + grub-core/commands/efi/tpm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c +index 7acf510499..bb59599721 100644 +--- a/grub-core/commands/efi/tpm.c ++++ b/grub-core/commands/efi/tpm.c +@@ -175,7 +175,7 @@ grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + event->PCRIndex = pcr; + event->EventType = EV_IPL; + event->EventSize = grub_strlen (description) + 1; +- grub_memcpy (event->Event, description, event->EventSize); ++ grub_strcpy ((char *) event->Event, description); + + algorithm = TCG_ALG_SHA; + status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size, +@@ -212,7 +212,7 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + event->Header.EventType = EV_IPL; + event->Size = + sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1; +- grub_memcpy (event->Event, description, grub_strlen (description) + 1); ++ grub_strcpy ((char *) event->Event, description); + + status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf, + (grub_uint64_t) size, event); diff --git a/SOURCES/0277-nx-set-attrs-in-our-kernel-loaders.patch b/SOURCES/0277-nx-set-attrs-in-our-kernel-loaders.patch deleted file mode 100644 index 9beee6a..0000000 --- a/SOURCES/0277-nx-set-attrs-in-our-kernel-loaders.patch +++ /dev/null @@ -1,571 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 22 Mar 2022 10:57:07 -0400 -Subject: [PATCH] nx: set attrs in our kernel loaders - -For NX, our kernel loaders need to set write and execute page -permissions on allocated pages and the stack. - -This patch adds those calls. - -Signed-off-by: Peter Jones -[rharwood: fix aarch64 callsites] -(cherry-picked from commit a9f79a997f01a83b36cdfa89ef2e72ac2a17c06c) -[rharwood: uninitialized stack_attrs, double verification] -Signed-off-by: Robbie Harwood ---- - grub-core/kern/efi/mm.c | 78 ++++++++++++++++++ - grub-core/loader/arm64/linux.c | 16 +++- - grub-core/loader/arm64/xen_boot.c | 4 +- - grub-core/loader/efi/chainloader.c | 11 +++ - grub-core/loader/efi/linux.c | 164 ++++++++++++++++++++++++++++++++++++- - grub-core/loader/i386/efi/linux.c | 26 +++++- - grub-core/loader/i386/linux.c | 5 ++ - include/grub/efi/efi.h | 6 +- - include/grub/efi/linux.h | 17 +++- - include/grub/efi/pe32.h | 2 + - 10 files changed, 314 insertions(+), 15 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 2c33758ed7..88364d764c 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -610,6 +610,82 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, - } - #endif - -+grub_addr_t grub_stack_addr = (grub_addr_t)-1ll; -+grub_size_t grub_stack_size = 0; -+ -+static void -+grub_nx_init (void) -+{ -+ grub_uint64_t attrs, stack_attrs; -+ grub_err_t err; -+ grub_addr_t stack_current, stack_end; -+ const grub_uint64_t page_size = 4096; -+ const grub_uint64_t page_mask = ~(page_size - 1); -+ -+ /* -+ * These are to confirm that the flags are working as expected when -+ * debugging. -+ */ -+ attrs = 0; -+ stack_current = (grub_addr_t)grub_nx_init & page_mask; -+ err = grub_get_mem_attrs (stack_current, page_size, &attrs); -+ if (err) -+ { -+ grub_dprintf ("nx", -+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", -+ stack_current, err); -+ grub_error_pop (); -+ } -+ else -+ grub_dprintf ("nx", "page attrs for grub_nx_init (%p) are %c%c%c\n", -+ grub_dl_load_core, -+ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); -+ -+ stack_current = (grub_addr_t)&stack_current & page_mask; -+ err = grub_get_mem_attrs (stack_current, page_size, &stack_attrs); -+ if (err) -+ { -+ grub_dprintf ("nx", -+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", -+ stack_current, err); -+ grub_error_pop (); -+ } -+ else -+ { -+ attrs = stack_attrs; -+ grub_dprintf ("nx", "page attrs for stack (%p) are %c%c%c\n", -+ &attrs, -+ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', -+ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); -+ } -+ -+ for (stack_end = stack_current + page_size ; -+ !(attrs & GRUB_MEM_ATTR_R); -+ stack_end += page_size) -+ { -+ err = grub_get_mem_attrs (stack_current, page_size, &attrs); -+ if (err) -+ { -+ grub_dprintf ("nx", -+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", -+ stack_current, err); -+ grub_error_pop (); -+ break; -+ } -+ } -+ if (stack_end > stack_current) -+ { -+ grub_stack_addr = stack_current; -+ grub_stack_size = stack_end - stack_current; -+ grub_dprintf ("nx", -+ "detected stack from 0x%"PRIxGRUB_ADDR" to 0x%"PRIxGRUB_ADDR"\n", -+ grub_stack_addr, grub_stack_addr + grub_stack_size - 1); -+ } -+} -+ - void - grub_efi_mm_init (void) - { -@@ -623,6 +699,8 @@ grub_efi_mm_init (void) - grub_efi_uint64_t required_pages; - int mm_status; - -+ grub_nx_init (); -+ - /* Prepare a memory region to store two memory maps. */ - memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); - if (! memory_map) -diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c -index bcc6ef46e9..70db5a6e0b 100644 ---- a/grub-core/loader/arm64/linux.c -+++ b/grub-core/loader/arm64/linux.c -@@ -173,7 +173,8 @@ free_params (void) - } - - grub_err_t --grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) -+grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args, -+ int nx_supported) - { - grub_err_t retval; - -@@ -183,7 +184,8 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) - - grub_dprintf ("linux", "linux command line: '%s'\n", args); - -- retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr); -+ retval = grub_efi_linux_boot (addr, size, handover_offset, -+ (void *)addr, nx_supported); - - /* Never reached... */ - free_params(); -@@ -193,7 +195,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) - static grub_err_t - grub_linux_boot (void) - { -- return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args)); -+ return grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, -+ (grub_size_t)kernel_size, -+ linux_args, -+ 0); - } - - static grub_err_t -@@ -342,6 +347,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_uint32_t align; - void *kernel = NULL; - int rc; -+ int nx_supported = 1; - - grub_dl_ref (my_mod); - -@@ -389,6 +395,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); - grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); - -+ err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); -+ if (err != GRUB_ERR_NONE) -+ goto fail; -+ - grub_loader_unset(); - - kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); -diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c -index d9b7a9ba40..6e7e920416 100644 ---- a/grub-core/loader/arm64/xen_boot.c -+++ b/grub-core/loader/arm64/xen_boot.c -@@ -266,7 +266,9 @@ xen_boot (void) - return err; - - return grub_arch_efi_linux_boot_image (xen_hypervisor->start, -- xen_hypervisor->cmdline); -+ xen_hypervisor->size, -+ xen_hypervisor->cmdline, -+ 0); - } - - static void -diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c -index 8ef508beca..6ac69f0f59 100644 ---- a/grub-core/loader/efi/chainloader.c -+++ b/grub-core/loader/efi/chainloader.c -@@ -1071,6 +1071,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } - -+ /* -+ * The OS kernel is going to set its own permissions when it takes over -+ * paging a few million instructions from now, and load_image() will set up -+ * anything that's needed based on the section headers, so there's no point -+ * in doing anything but clearing the protection bits here. -+ */ -+ grub_dprintf("nx", "setting attributes for %p (%lu bytes) to %llx\n", -+ (void *)(grub_addr_t)address, fsize, 0llu); -+ grub_update_mem_attrs (address, fsize, -+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X, 0); -+ - #if defined (__i386__) || defined (__x86_64__) - if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) - { -diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c -index 9260731c10..dcc9ea40ea 100644 ---- a/grub-core/loader/efi/linux.c -+++ b/grub-core/loader/efi/linux.c -@@ -66,16 +66,127 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size) - - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" -+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" -+ -+grub_err_t -+grub_efi_check_nx_image_support (grub_addr_t kernel_addr, -+ grub_size_t kernel_size, -+ int *nx_supported) -+{ -+ struct grub_dos_header *doshdr; -+ grub_size_t sz = sizeof (*doshdr); -+ -+ struct grub_pe32_header_32 *pe32; -+ struct grub_pe32_header_64 *pe64; -+ -+ int image_is_compatible = 0; -+ int is_64_bit; -+ -+ if (kernel_size < sz) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); -+ -+ doshdr = (void *)kernel_addr; -+ -+ if ((doshdr->magic & 0xffff) != GRUB_DOS_MAGIC) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel DOS magic is invalid")); -+ -+ sz = doshdr->lfanew + sizeof (*pe32); -+ if (kernel_size < sz) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); -+ -+ pe32 = (struct grub_pe32_header_32 *)(kernel_addr + doshdr->lfanew); -+ pe64 = (struct grub_pe32_header_64 *)pe32; -+ -+ if (grub_memcmp (pe32->signature, GRUB_PE32_SIGNATURE, -+ GRUB_PE32_SIGNATURE_SIZE) != 0) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel PE magic is invalid")); -+ -+ switch (pe32->coff_header.machine) -+ { -+ case GRUB_PE32_MACHINE_ARMTHUMB_MIXED: -+ case GRUB_PE32_MACHINE_I386: -+ case GRUB_PE32_MACHINE_RISCV32: -+ is_64_bit = 0; -+ break; -+ case GRUB_PE32_MACHINE_ARM64: -+ case GRUB_PE32_MACHINE_IA64: -+ case GRUB_PE32_MACHINE_RISCV64: -+ case GRUB_PE32_MACHINE_X86_64: -+ is_64_bit = 1; -+ break; -+ default: -+ return grub_error (GRUB_ERR_BAD_OS, N_("PE machine type 0x%04hx unknown"), -+ pe32->coff_header.machine); -+ } -+ -+ if (is_64_bit) -+ { -+ sz = doshdr->lfanew + sizeof (*pe64); -+ if (kernel_size < sz) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); -+ -+ if (pe64->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) -+ image_is_compatible = 1; -+ } -+ else -+ { -+ if (pe32->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) -+ image_is_compatible = 1; -+ } -+ -+ *nx_supported = image_is_compatible; -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_efi_check_nx_required (int *nx_required) -+{ -+ grub_efi_status_t status; -+ grub_efi_guid_t guid = GRUB_EFI_SHIM_LOCK_GUID; -+ grub_size_t mok_policy_sz = 0; -+ char *mok_policy = NULL; -+ grub_uint32_t mok_policy_attrs = 0; -+ -+ status = grub_efi_get_variable_with_attributes ("MokPolicy", &guid, -+ &mok_policy_sz, -+ (void **)&mok_policy, -+ &mok_policy_attrs); -+ if (status == GRUB_EFI_NOT_FOUND || -+ mok_policy_sz == 0 || -+ mok_policy == NULL) -+ { -+ *nx_required = 0; -+ return GRUB_ERR_NONE; -+ } -+ -+ *nx_required = 0; -+ if (mok_policy_sz < 1 || -+ mok_policy_attrs != (GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | -+ GRUB_EFI_VARIABLE_RUNTIME_ACCESS) || -+ (mok_policy[mok_policy_sz-1] & GRUB_MOK_POLICY_NX_REQUIRED)) -+ *nx_required = 1; -+ -+ return GRUB_ERR_NONE; -+} - - typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); - - grub_err_t --grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, -- void *kernel_params) -+grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, -+ grub_off_t handover_offset, void *kernel_params, -+ int nx_supported) - { - grub_efi_loaded_image_t *loaded_image = NULL; - handover_func hf; - int offset = 0; -+ grub_uint64_t stack_set_attrs = GRUB_MEM_ATTR_R | -+ GRUB_MEM_ATTR_W | -+ GRUB_MEM_ATTR_X; -+ grub_uint64_t stack_clear_attrs = 0; -+ grub_uint64_t kernel_set_attrs = stack_set_attrs; -+ grub_uint64_t kernel_clear_attrs = stack_clear_attrs; -+ grub_uint64_t attrs; -+ int nx_required = 0; - - #ifdef __x86_64__ - offset = 512; -@@ -88,12 +199,57 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, - */ - loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (loaded_image) -- loaded_image->image_base = kernel_addr; -+ loaded_image->image_base = (void *)kernel_addr; - else - grub_dprintf ("linux", "Loaded Image base address could not be set\n"); - - grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", -- kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); -+ (void *)kernel_addr, (void *)handover_offset, kernel_params); -+ -+ -+ if (nx_required && !nx_supported) -+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel does not support NX loading required by policy")); -+ -+ if (nx_supported) -+ { -+ kernel_set_attrs &= ~GRUB_MEM_ATTR_W; -+ kernel_clear_attrs |= GRUB_MEM_ATTR_W; -+ stack_set_attrs &= ~GRUB_MEM_ATTR_X; -+ stack_clear_attrs |= GRUB_MEM_ATTR_X; -+ } -+ -+ grub_dprintf ("nx", "Setting attributes for 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to r%cx\n", -+ kernel_addr, kernel_addr + kernel_size - 1, -+ (kernel_set_attrs & GRUB_MEM_ATTR_W) ? 'w' : '-'); -+ grub_update_mem_attrs (kernel_addr, kernel_size, -+ kernel_set_attrs, kernel_clear_attrs); -+ -+ grub_get_mem_attrs (kernel_addr, 4096, &attrs); -+ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", -+ (grub_addr_t)kernel_addr, -+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", -+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", -+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); -+ if (grub_stack_addr != (grub_addr_t)-1ll) -+ { -+ grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n", -+ grub_stack_addr, grub_stack_addr + grub_stack_size - 1, -+ (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-'); -+ grub_update_mem_attrs (grub_stack_addr, grub_stack_size, -+ stack_set_attrs, stack_clear_attrs); -+ -+ grub_get_mem_attrs (grub_stack_addr, 4096, &attrs); -+ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", -+ grub_stack_addr, -+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", -+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", -+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); -+ } -+ -+#if defined(__i386__) || defined(__x86_64__) -+ asm volatile ("cli"); -+#endif -+ - hf = (handover_func)((char *)kernel_addr + handover_offset + offset); - hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index b832c85728..dc98077378 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -45,7 +45,7 @@ struct grub_linuxefi_context { - grub_uint32_t handover_offset; - struct linux_kernel_params *params; - char *cmdline; -- -+ int nx_supported; - void *initrd_mem; - }; - -@@ -111,13 +111,19 @@ kernel_alloc(grub_efi_uintn_t size, - pages = BYTES_TO_PAGES(size); - grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", - (unsigned long)pages, (void *)(unsigned long)max); -+ size = pages * GRUB_EFI_PAGE_SIZE; - - prev_max = max; - addr = grub_efi_allocate_pages_real (max, pages, - max_addresses[i].alloc_type, - memtype); - if (addr) -- grub_dprintf ("linux", "Allocated at %p\n", addr); -+ { -+ grub_dprintf ("linux", "Allocated at %p\n", addr); -+ grub_update_mem_attrs ((grub_addr_t)addr, size, -+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, -+ GRUB_MEM_ATTR_X); -+ } - } - - while (grub_error_pop ()) -@@ -138,9 +144,11 @@ grub_linuxefi_boot (void *data) - - asm volatile ("cli"); - -- return grub_efi_linux_boot ((char *)context->kernel_mem, -+ return grub_efi_linux_boot ((grub_addr_t)context->kernel_mem, -+ context->kernel_size, - context->handover_offset, -- context->params); -+ context->params, -+ context->nx_supported); - } - - static grub_err_t -@@ -306,7 +314,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_uint32_t handover_offset; - struct linux_kernel_params *params = 0; - char *cmdline = 0; -+ int nx_supported = 1; - struct grub_linuxefi_context *context = 0; -+ grub_err_t err; - - grub_dl_ref (my_mod); - -@@ -347,6 +357,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - } - -+ err = grub_efi_check_nx_image_support ((grub_addr_t)kernel, filelen, -+ &nx_supported); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ grub_dprintf ("linux", "nx is%s supported by this kernel\n", -+ nx_supported ? "" : " not"); -+ - lh = (struct linux_i386_kernel_header *)kernel; - grub_dprintf ("linux", "original lh is at %p\n", kernel); - -@@ -511,6 +528,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - context->handover_offset = handover_offset; - context->params = params; - context->cmdline = cmdline; -+ context->nx_supported = nx_supported; - - grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); - -diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c -index 4aeb0e4b9a..3c1ff64763 100644 ---- a/grub-core/loader/i386/linux.c -+++ b/grub-core/loader/i386/linux.c -@@ -805,6 +805,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - kernel_offset += len; - } - -+ grub_dprintf("efi", "setting attributes for %p (%zu bytes) to +rw-x\n", -+ &linux_params, sizeof (lh) + len); -+ grub_update_mem_attrs ((grub_addr_t)&linux_params, sizeof (lh) + len, -+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, GRUB_MEM_ATTR_X); -+ - linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR; - linux_params.kernel_alignment = (1 << align); - linux_params.ps_mouse = linux_params.padding11 = 0; -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index 34825c4adc..449e55269f 100644 ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -140,12 +140,16 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, - char **device, - char **path); - -+extern grub_addr_t EXPORT_VAR(grub_stack_addr); -+extern grub_size_t EXPORT_VAR(grub_stack_size); -+ - #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) - void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); - grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); - #include - grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); --grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args); -+grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size, -+ char *args, int nx_enabled); - #endif - - grub_addr_t grub_efi_section_addr (const char *section); -diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h -index 0033d9305a..8130b19590 100644 ---- a/include/grub/efi/linux.h -+++ b/include/grub/efi/linux.h -@@ -22,10 +22,23 @@ - #include - #include - -+#define GRUB_MOK_POLICY_NX_REQUIRED 0x1 -+ - int - EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); -+ - grub_err_t --EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, -- void *kernel_param); -+EXPORT_FUNC(grub_efi_linux_boot) (grub_addr_t kernel_address, -+ grub_size_t kernel_size, -+ grub_off_t handover_offset, -+ void *kernel_param, int nx_enabled); -+ -+grub_err_t -+EXPORT_FUNC(grub_efi_check_nx_image_support) (grub_addr_t kernel_addr, -+ grub_size_t kernel_size, -+ int *nx_supported); -+ -+grub_err_t -+EXPORT_FUNC(grub_efi_check_nx_required) (int *nx_required); - - #endif /* ! GRUB_EFI_LINUX_HEADER */ -diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h -index 2a5e1ee003..a5e623eb04 100644 ---- a/include/grub/efi/pe32.h -+++ b/include/grub/efi/pe32.h -@@ -181,6 +181,8 @@ struct grub_pe32_optional_header - struct grub_pe32_data_directory reserved_entry; - }; - -+#define GRUB_PE32_NX_COMPAT 0x0100 -+ - struct grub_pe64_optional_header - { - grub_uint16_t magic; diff --git a/SOURCES/0278-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch b/SOURCES/0278-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch new file mode 100644 index 0000000..610c81a --- /dev/null +++ b/SOURCES/0278-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch @@ -0,0 +1,258 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lu Ken +Date: Wed, 13 Jul 2022 10:06:12 +0800 +Subject: [PATCH] efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support + +The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware +in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL. +It was proposed by Intel and ARM and approved by UEFI organization. + +It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 . +The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h . + +Signed-off-by: Lu Ken +Reviewed-by: Daniel Kiper +(cherry picked from commit 4c76565b6cb885b7e144dc27f3612066844e2d19) +--- + grub-core/commands/efi/tpm.c | 48 ++++++++++++++ + include/grub/efi/cc.h | 151 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 199 insertions(+) + create mode 100644 include/grub/efi/cc.h + +diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c +index bb59599721..ae09c1bf8b 100644 +--- a/grub-core/commands/efi/tpm.c ++++ b/grub-core/commands/efi/tpm.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -31,6 +32,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t; + + static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; + static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; ++static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID; + + static grub_efi_handle_t *grub_tpm_handle; + static grub_uint8_t grub_tpm_version; +@@ -221,6 +223,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + return grub_efi_log_event_status (status); + } + ++static void ++grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ grub_efi_cc_event_t *event; ++ grub_efi_status_t status; ++ grub_efi_cc_protocol_t *cc; ++ grub_efi_cc_mr_index_t mr; ++ ++ cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL); ++ if (cc == NULL) ++ return; ++ ++ status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_efi_log_event_status (status); ++ return; ++ } ++ ++ event = grub_zalloc (sizeof (grub_efi_cc_event_t) + ++ grub_strlen (description) + 1); ++ if (event == NULL) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer")); ++ return; ++ } ++ ++ event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t); ++ event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION; ++ event->Header.MrIndex = mr; ++ event->Header.EventType = EV_IPL; ++ event->Size = sizeof (*event) + grub_strlen (description) + 1; ++ grub_strcpy ((char *) event->Event, description); ++ ++ status = efi_call_5 (cc->hash_log_extend_event, cc, 0, ++ (grub_efi_physical_address_t)(grub_addr_t) buf, ++ (grub_efi_uint64_t) size, event); ++ grub_free (event); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_efi_log_event_status (status); ++} ++ + grub_err_t + grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +@@ -228,6 +274,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + grub_efi_handle_t tpm_handle; + grub_efi_uint8_t protocol_version; + ++ grub_cc_log_event(buf, size, pcr, description); ++ + if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) + return 0; + +diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h +new file mode 100644 +index 0000000000..8960306890 +--- /dev/null ++++ b/include/grub/efi/cc.h +@@ -0,0 +1,151 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_CC_H ++#define GRUB_EFI_CC_H 1 ++ ++#include ++#include ++#include ++ ++#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \ ++ { 0x96751a3d, 0x72f4, 0x41a6, \ ++ { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \ ++ }; ++ ++struct grub_efi_cc_version ++{ ++ grub_efi_uint8_t Major; ++ grub_efi_uint8_t Minor; ++}; ++typedef struct grub_efi_cc_version grub_efi_cc_version_t; ++ ++/* EFI_CC Type/SubType definition. */ ++#define GRUB_EFI_CC_TYPE_NONE 0 ++#define GRUB_EFI_CC_TYPE_SEV 1 ++#define GRUB_EFI_CC_TYPE_TDX 2 ++ ++struct grub_efi_cc_type ++{ ++ grub_efi_uint8_t Type; ++ grub_efi_uint8_t SubType; ++}; ++typedef struct grub_efi_cc_type grub_efi_cc_type_t; ++ ++typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t; ++typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t; ++typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t; ++typedef grub_efi_uint32_t grub_efi_cc_mr_index_t; ++ ++/* Intel TDX measure register index. */ ++#define GRUB_TDX_MR_INDEX_MRTD 0 ++#define GRUB_TDX_MR_INDEX_RTMR0 1 ++#define GRUB_TDX_MR_INDEX_RTMR1 2 ++#define GRUB_TDX_MR_INDEX_RTMR2 3 ++#define GRUB_TDX_MR_INDEX_RTMR3 4 ++ ++#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002 ++#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004 ++#define GRUB_EFI_CC_EVENT_HEADER_VERSION 1 ++ ++struct grub_efi_cc_event_header ++{ ++ /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */ ++ grub_efi_uint32_t HeaderSize; ++ ++ /* ++ * Header version. For this version of this specification, ++ * the value shall be 1. ++ */ ++ grub_efi_uint16_t HeaderVersion; ++ ++ /* Index of the MR that shall be extended. */ ++ grub_efi_cc_mr_index_t MrIndex; ++ ++ /* Type of the event that shall be extended (and optionally logged). */ ++ grub_efi_uint32_t EventType; ++} GRUB_PACKED; ++typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t; ++ ++struct grub_efi_cc_event ++{ ++ /* Total size of the event including the Size component, the header and the Event data. */ ++ grub_efi_uint32_t Size; ++ grub_efi_cc_event_header_t Header; ++ grub_efi_uint8_t Event[0]; ++} GRUB_PACKED; ++typedef struct grub_efi_cc_event grub_efi_cc_event_t; ++ ++struct grub_efi_cc_boot_service_capability ++{ ++ /* Allocated size of the structure. */ ++ grub_efi_uint8_t Size; ++ ++ /* ++ * Version of the grub_efi_cc_boot_service_capability_t structure itself. ++ * For this version of the protocol, the Major version shall be set to 1 ++ * and the Minor version shall be set to 1. ++ */ ++ grub_efi_cc_version_t StructureVersion; ++ ++ /* ++ * Version of the EFI TD protocol. ++ * For this version of the protocol, the Major version shall be set to 1 ++ * and the Minor version shall be set to 1. ++ */ ++ grub_efi_cc_version_t ProtocolVersion; ++ ++ /* Supported hash algorithms. */ ++ grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap; ++ ++ /* Bitmap of supported event log formats. */ ++ grub_efi_cc_event_log_bitmap_t SupportedEventLogs; ++ ++ /* Indicates the CC type. */ ++ grub_efi_cc_type_t CcType; ++}; ++typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t; ++ ++struct grub_efi_cc_protocol ++{ ++ grub_efi_status_t ++ (*get_capability) (struct grub_efi_cc_protocol *this, ++ grub_efi_cc_boot_service_capability_t *ProtocolCapability); ++ ++ grub_efi_status_t ++ (*get_event_log) (struct grub_efi_cc_protocol *this, ++ grub_efi_cc_event_log_format_t EventLogFormat, ++ grub_efi_physical_address_t *EventLogLocation, ++ grub_efi_physical_address_t *EventLogLastEntry, ++ grub_efi_boolean_t *EventLogTruncated); ++ ++ grub_efi_status_t ++ (*hash_log_extend_event) (struct grub_efi_cc_protocol *this, ++ grub_efi_uint64_t Flags, ++ grub_efi_physical_address_t DataToHash, ++ grub_efi_uint64_t DataToHashLen, ++ grub_efi_cc_event_t *EfiCcEvent); ++ ++ grub_efi_status_t ++ (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this, ++ grub_efi_uint32_t PcrIndex, ++ grub_efi_cc_mr_index_t *MrIndex); ++}; ++typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t; ++ ++#endif diff --git a/SOURCES/0278-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch b/SOURCES/0278-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch deleted file mode 100644 index 8b5075b..0000000 --- a/SOURCES/0278-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 22 Mar 2022 10:57:20 -0400 -Subject: [PATCH] nx: set the nx compatible flag in EFI grub images - -For NX, we need the grub binary to announce that it is compatible with -the NX feature. This implies that when loading the executable grub -image, several attributes are true: - -- the binary doesn't need an executable stack -- the binary doesn't need sections to be both executable and writable -- the binary knows how to use the EFI Memory Attributes protocol on code - it is loading. - -This patch adds a definition for the PE DLL Characteristics flag -GRUB_PE32_NX_COMPAT, and changes grub-mkimage to set that flag. - -Signed-off-by: Peter Jones -(cherry picked from commit 0c7f1aed5a87f75051b421903a900ccb4bbd795a) ---- - util/mkimage.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/util/mkimage.c b/util/mkimage.c -index 8319e8dfbd..c3d33aaac8 100644 ---- a/util/mkimage.c -+++ b/util/mkimage.c -@@ -1418,6 +1418,7 @@ grub_install_generate_image (const char *dir, const char *prefix, - section = (struct grub_pe32_section_table *)(o64 + 1); - } - -+ PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 (GRUB_PE32_NX_COMPAT); - PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size); - PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address); - PE_OHDR (o32, o64, image_base) = 0; diff --git a/SOURCES/0279-Make-debug-file-show-which-file-filters-get-run.patch b/SOURCES/0279-Make-debug-file-show-which-file-filters-get-run.patch deleted file mode 100644 index 475b3b4..0000000 --- a/SOURCES/0279-Make-debug-file-show-which-file-filters-get-run.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 29 Jul 2022 15:56:00 -0400 -Subject: [PATCH] Make debug=file show which file filters get run. - -If one of the file filters breaks things, it's hard to figure out where -it has happened. - -This makes grub log which filter is being run, which makes it easier to -figure out where you are in the sequence of events. - -Signed-off-by: Peter Jones -(cherry picked from commit d3d6518a13b5440a3be6c66b0ae47447182f2891) ---- - grub-core/kern/file.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c -index ed69fc0f0f..3f175630ea 100644 ---- a/grub-core/kern/file.c -+++ b/grub-core/kern/file.c -@@ -30,6 +30,14 @@ void (*EXPORT_VAR (grub_grubnet_fini)) (void); - - grub_file_filter_t grub_file_filters[GRUB_FILE_FILTER_MAX]; - -+static char *filter_names[] = { -+ [GRUB_FILE_FILTER_VERIFY] = "GRUB_FILE_FILTER_VERIFY", -+ [GRUB_FILE_FILTER_GZIO] = "GRUB_FILE_FILTER_GZIO", -+ [GRUB_FILE_FILTER_XZIO] = "GRUB_FILE_FILTER_XZIO", -+ [GRUB_FILE_FILTER_LZOPIO] = "GRUB_FILE_FILTER_LZOPIO", -+ [GRUB_FILE_FILTER_MAX] = "GRUB_FILE_FILTER_MAX" -+}; -+ - /* Get the device part of the filename NAME. It is enclosed by parentheses. */ - char * - grub_file_get_device_name (const char *name) -@@ -121,6 +129,9 @@ grub_file_open (const char *name, enum grub_file_type type) - if (grub_file_filters[filter]) - { - last_file = file; -+ if (filter < GRUB_FILE_FILTER_MAX) -+ grub_dprintf ("file", "Running %s file filter\n", -+ filter_names[filter]); - file = grub_file_filters[filter] (file, type); - if (file && file != last_file) - { diff --git a/SOURCES/0279-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch b/SOURCES/0279-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch new file mode 100644 index 0000000..e0dd347 --- /dev/null +++ b/SOURCES/0279-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Wed, 3 Aug 2022 19:45:33 +0800 +Subject: [PATCH] font: Reject glyphs exceeds font->max_glyph_width or + font->max_glyph_height + +Check glyph's width and height against limits specified in font's +metadata. Reject the glyph (and font) if such limits are exceeded. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 5760fcfd466cc757540ea0d591bad6a08caeaa16) +--- + grub-core/font/font.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index d09bb38d89..2f09a4a55b 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -760,7 +760,9 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) + || read_be_uint16 (font->file, &height) != 0 + || read_be_int16 (font->file, &xoff) != 0 + || read_be_int16 (font->file, &yoff) != 0 +- || read_be_int16 (font->file, &dwidth) != 0) ++ || read_be_int16 (font->file, &dwidth) != 0 ++ || width > font->max_char_width ++ || height > font->max_char_height) + { + remove_font (font); + return 0; diff --git a/SOURCES/0280-efi-make-the-default-arena-most-of-ram.patch b/SOURCES/0280-efi-make-the-default-arena-most-of-ram.patch deleted file mode 100644 index 6821cde..0000000 --- a/SOURCES/0280-efi-make-the-default-arena-most-of-ram.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 29 Jul 2022 15:57:57 -0400 -Subject: [PATCH] efi: make the default arena most of ram - -Currently when populating the initial memory arena on EFI systems, we -count the available regions below GRUB_EFI_MAX_ALLOCATION_ADDRESS from -the EFI memory map and then allocates one quarter of that for our arena. - -Because many systems come up without IOMMUs, we currently set -GRUB_EFI_MAX_ALLOCATION_ADDRESS to 0x7fffffff, i.e. all addresses -allocated must be below 2G[0]. Due to firmware and other -considerations, this makes the most memory we can possibly have in our -arena 512M. - -Because our EFI loader doesn't get kernel and initrd memory from grub's -allocator, but rather reserves it directly from UEFI and then simply -marks those as allocated if they're within grub's arena, it was -historically possible to have initrds that are larger than 512M, because -we could use any memory region below 4G, without concern for grub's -choice of arena size. - -Unfortunately, when we switched to using the "verifiers" API (and thus -the file_filter_t API) to do measurement of kernel and initrd, this -introduced a pattern that allocates the entire file when we call -grub_file_open(), and buffers it to pass to the filter. This results in -needing to have enough space for the initramfs in the grub arena. - -This is bad. - -Since it's unlikely you're going to do anything *other* than loading a -kernel and initramfs that takes much of the available free memory from -UEFI, this patch introduces a workaround by changing the amount we give -to the arena be three quarters of the available memory, rather than one -quarter, thus changing our theoretical initrd limit to 1.5G. In -practice, it may still be smaller than that depending on allocation -fragmentation, but generally it will be most of it. - -Note that this doesn't fix the underlying flaw, which is that there is -no safe way to do the validation correctly using the "verifiers" system -with the current file API without buffering the whole file before -grub_file_read() is ever called, and thus you can't set an allocation -policy for the initial buffer of the file at all, so unless we raise the -allocation limit to >4G, it can't be allocated in the big region. - -[0] I'm not sure there was a good reason not to pick 4G, but even if we - had, at least one common firmware routes the first 2G of physical - RAM to 0x0, and any additional memory starting at 0x100000000. - -Related: rhbz#2112134 - -Signed-off-by: Peter Jones -(cherry picked from commit 005a0aaaad2a00a1fa1e60d94cc4fd5407c22e7d) ---- - grub-core/kern/efi/mm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 88364d764c..0288eab361 100644 ---- a/grub-core/kern/efi/mm.c -+++ b/grub-core/kern/efi/mm.c -@@ -738,10 +738,10 @@ grub_efi_mm_init (void) - filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, - desc_size, memory_map_end); - -- /* By default, request a quarter of the available memory. */ -+ /* By default, request three quarters of the available memory. */ - total_pages = get_total_pages (filtered_memory_map, desc_size, - filtered_memory_map_end); -- required_pages = (total_pages >> 2); -+ required_pages = (total_pages >> 1) + (total_pages >> 2); - if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) - required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); - else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) diff --git a/SOURCES/0280-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch b/SOURCES/0280-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch new file mode 100644 index 0000000..b5f10f6 --- /dev/null +++ b/SOURCES/0280-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 00:51:20 +0800 +Subject: [PATCH] font: Fix size overflow in grub_font_get_glyph_internal() + +The length of memory allocation and file read may overflow. This patch +fixes the problem by using safemath macros. + +There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe +if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz(). +It is safe replacement for such code. It has safemath-like prototype. + +This patch also introduces grub_cast(value, pointer), it casts value to +typeof(*pointer) then store the value to *pointer. It returns true when +overflow occurs or false if there is no overflow. The semantics of arguments +and return value are designed to be consistent with other safemath macros. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 941d10ad6f1dcbd12fb613002249e29ba035f985) +--- + grub-core/font/font.c | 17 +++++++++++++---- + include/grub/bitmap.h | 18 ++++++++++++++++++ + include/grub/safemath.h | 2 ++ + 3 files changed, 33 insertions(+), 4 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 2f09a4a55b..6a3fbebbd8 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) + grub_int16_t xoff; + grub_int16_t yoff; + grub_int16_t dwidth; +- int len; ++ grub_ssize_t len; ++ grub_size_t sz; + + if (index_entry->glyph) + /* Return cached glyph. */ +@@ -768,9 +769,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) + return 0; + } + +- len = (width * height + 7) / 8; +- glyph = grub_malloc (sizeof (struct grub_font_glyph) + len); +- if (!glyph) ++ /* Calculate real struct size of current glyph. */ ++ if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) || ++ grub_add (sizeof (struct grub_font_glyph), len, &sz)) ++ { ++ remove_font (font); ++ return 0; ++ } ++ ++ /* Allocate and initialize the glyph struct. */ ++ glyph = grub_malloc (sz); ++ if (glyph == NULL) + { + remove_font (font); + return 0; +diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h +index 5728f8ca3a..0d9603f619 100644 +--- a/include/grub/bitmap.h ++++ b/include/grub/bitmap.h +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + struct grub_video_bitmap + { +@@ -79,6 +80,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap) + return bitmap->mode_info.height; + } + ++/* ++ * Calculate and store the size of data buffer of 1bit bitmap in result. ++ * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs. ++ * Return true when overflow occurs or false if there is no overflow. ++ * This function is intentionally implemented as a macro instead of ++ * an inline function. Although a bit awkward, it preserves data types for ++ * safemath macros and reduces macro side effects as much as possible. ++ * ++ * XXX: Will report false overflow if width * height > UINT64_MAX. ++ */ ++#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \ ++({ \ ++ grub_uint64_t _bitmap_pixels; \ ++ grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \ ++ grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \ ++}) ++ + void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap, + struct grub_video_mode_info *mode_info); + +diff --git a/include/grub/safemath.h b/include/grub/safemath.h +index c17b89bba1..bb0f826de1 100644 +--- a/include/grub/safemath.h ++++ b/include/grub/safemath.h +@@ -30,6 +30,8 @@ + #define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res) + #define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res) + ++#define grub_cast(a, res) grub_add ((a), 0, (res)) ++ + #else + #error gcc 5.1 or newer or clang 3.8 or newer is required + #endif diff --git a/SOURCES/0281-efi-use-enumerated-array-positions-for-our-allocatio.patch b/SOURCES/0281-efi-use-enumerated-array-positions-for-our-allocatio.patch deleted file mode 100644 index de5671c..0000000 --- a/SOURCES/0281-efi-use-enumerated-array-positions-for-our-allocatio.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 14:06:30 -0400 -Subject: [PATCH] efi: use enumerated array positions for our allocation - choices - -In our kernel allocator on EFI systems, we currently have a growing -amount of code that references the various allocation policies by -position in the array, and of course maintenance of this code scales -very poorly. - -This patch changes them to be enumerated, so they're easier to refer to -farther along in the code without confusion. - -Signed-off-by: Peter Jones -(cherry picked from commit 6768026270cca015d7fef0ecc8a4119e9b3d3923) ---- - grub-core/loader/i386/efi/linux.c | 31 ++++++++++++++++++++----------- - 1 file changed, 20 insertions(+), 11 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index dc98077378..781a333162 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -61,17 +61,26 @@ struct allocation_choice { - grub_efi_allocate_type_t alloc_type; - }; - --static struct allocation_choice max_addresses[4] = -+enum { -+ KERNEL_PREF_ADDRESS, -+ KERNEL_4G_LIMIT, -+ KERNEL_NO_LIMIT, -+}; -+ -+static struct allocation_choice max_addresses[] = - { - /* the kernel overrides this one with pref_address and - * GRUB_EFI_ALLOCATE_ADDRESS */ -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ [KERNEL_PREF_ADDRESS] = -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ /* If the flag in params is set, this one gets changed to be above 4GB. */ -+ [KERNEL_4G_LIMIT] = -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - /* this one is always below 4GB, which we still *prefer* even if the flag - * is set. */ -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -- /* If the flag in params is set, this one gets changed to be above 4GB. */ -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -- { 0, 0 } -+ [KERNEL_NO_LIMIT] = -+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { NO_MEM, 0, 0 } - }; - static struct allocation_choice saved_addresses[4]; - -@@ -418,7 +427,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) - { - grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); -- max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS; -+ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; - } - else - { -@@ -491,11 +500,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address); - if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS) - { -- max_addresses[0].addr = lh->pref_address; -- max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; -+ max_addresses[KERNEL_PREF_ADDRESS].addr = lh->pref_address; -+ max_addresses[KERNEL_PREF_ADDRESS].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS; - } -- max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -- max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - kernel_size = lh->init_size; - kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, - N_("can't allocate kernel")); diff --git a/SOURCES/0281-font-Fix-several-integer-overflows-in-grub_font_cons.patch b/SOURCES/0281-font-Fix-several-integer-overflows-in-grub_font_cons.patch new file mode 100644 index 0000000..3c76eb4 --- /dev/null +++ b/SOURCES/0281-font-Fix-several-integer-overflows-in-grub_font_cons.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 01:58:27 +0800 +Subject: [PATCH] font: Fix several integer overflows in + grub_font_construct_glyph() + +This patch fixes several integer overflows in grub_font_construct_glyph(). +Glyphs of invalid size, zero or leading to an overflow, are rejected. +The inconsistency between "glyph" and "max_glyph_size" when grub_malloc() +returns NULL is fixed too. + +Fixes: CVE-2022-2601 + +Reported-by: Zhang Boyang +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit b1805f251b31a9d3cfae5c3572ddfa630145dbbf) +--- + grub-core/font/font.c | 29 +++++++++++++++++------------ + 1 file changed, 17 insertions(+), 12 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 6a3fbebbd8..1fa181d4ca 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1517,6 +1517,7 @@ grub_font_construct_glyph (grub_font_t hinted_font, + struct grub_video_signed_rect bounds; + static struct grub_font_glyph *glyph = 0; + static grub_size_t max_glyph_size = 0; ++ grub_size_t cur_glyph_size; + + ensure_comb_space (glyph_id); + +@@ -1533,29 +1534,33 @@ grub_font_construct_glyph (grub_font_t hinted_font, + if (!glyph_id->ncomb && !glyph_id->attributes) + return main_glyph; + +- if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) ++ if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) || ++ grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size)) ++ return main_glyph; ++ ++ if (max_glyph_size < cur_glyph_size) + { + grub_free (glyph); +- max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2; +- if (max_glyph_size < 8) +- max_glyph_size = 8; +- glyph = grub_malloc (max_glyph_size); ++ if (grub_mul (cur_glyph_size, 2, &max_glyph_size)) ++ max_glyph_size = 0; ++ glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL; + } + if (!glyph) + { ++ max_glyph_size = 0; + grub_errno = GRUB_ERR_NONE; + return main_glyph; + } + +- grub_memset (glyph, 0, sizeof (*glyph) +- + (bounds.width * bounds.height +- + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT); ++ grub_memset (glyph, 0, cur_glyph_size); + + glyph->font = main_glyph->font; +- glyph->width = bounds.width; +- glyph->height = bounds.height; +- glyph->offset_x = bounds.x; +- glyph->offset_y = bounds.y; ++ if (bounds.width == 0 || bounds.height == 0 || ++ grub_cast (bounds.width, &glyph->width) || ++ grub_cast (bounds.height, &glyph->height) || ++ grub_cast (bounds.x, &glyph->offset_x) || ++ grub_cast (bounds.y, &glyph->offset_y)) ++ return main_glyph; + + if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR) + grub_font_blit_glyph_mirror (glyph, main_glyph, diff --git a/SOURCES/0282-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch b/SOURCES/0282-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch deleted file mode 100644 index 4eccd77..0000000 --- a/SOURCES/0282-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 14:24:39 -0400 -Subject: [PATCH] efi: split allocation policy for kernel vs initrd memories. - -Currently in our kernel allocator, we use the same set of choices for -all of our various kernel and initramfs allocations, though they do not -have exactly the same constraints. - -This patch adds the concept of an allocation purpose, which currently -can be KERNEL_MEM or INITRD_MEM, and updates kernel_alloc() calls -appropriately, but does not change any current policy decision. It -also adds a few debug prints. - -Signed-off-by: Peter Jones -(cherry picked from commit 36307bed28cd838116fc4af26a30719660d62d4c) ---- - grub-core/loader/i386/efi/linux.c | 35 +++++++++++++++++++++++++++-------- - 1 file changed, 27 insertions(+), 8 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 781a333162..b9cd443a9a 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -56,7 +56,14 @@ struct grub_linuxefi_context { - - #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) - -+typedef enum { -+ NO_MEM, -+ KERNEL_MEM, -+ INITRD_MEM, -+} kernel_alloc_purpose_t; -+ - struct allocation_choice { -+ kernel_alloc_purpose_t purpose; - grub_efi_physical_address_t addr; - grub_efi_allocate_type_t alloc_type; - }; -@@ -65,6 +72,7 @@ enum { - KERNEL_PREF_ADDRESS, - KERNEL_4G_LIMIT, - KERNEL_NO_LIMIT, -+ INITRD_MAX_ADDRESS, - }; - - static struct allocation_choice max_addresses[] = -@@ -72,14 +80,17 @@ static struct allocation_choice max_addresses[] = - /* the kernel overrides this one with pref_address and - * GRUB_EFI_ALLOCATE_ADDRESS */ - [KERNEL_PREF_ADDRESS] = -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - /* If the flag in params is set, this one gets changed to be above 4GB. */ - [KERNEL_4G_LIMIT] = -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - /* this one is always below 4GB, which we still *prefer* even if the flag - * is set. */ - [KERNEL_NO_LIMIT] = -- { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, -+ /* this is for the initrd */ -+ [INITRD_MAX_ADDRESS] = -+ { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - { NO_MEM, 0, 0 } - }; - static struct allocation_choice saved_addresses[4]; -@@ -96,7 +107,8 @@ kernel_free(void *addr, grub_efi_uintn_t size) - } - - static void * --kernel_alloc(grub_efi_uintn_t size, -+kernel_alloc(kernel_alloc_purpose_t purpose, -+ grub_efi_uintn_t size, - grub_efi_memory_type_t memtype, - const char * const errmsg) - { -@@ -109,6 +121,9 @@ kernel_alloc(grub_efi_uintn_t size, - grub_uint64_t max = max_addresses[i].addr; - grub_efi_uintn_t pages; - -+ if (purpose != max_addresses[i].purpose) -+ continue; -+ - /* - * When we're *not* loading the kernel, or >4GB allocations aren't - * supported, these entries are basically all the same, so don't re-try -@@ -262,7 +277,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - } - -- initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA, -+ grub_dprintf ("linux", "Trying to allocate initrd mem\n"); -+ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, - N_("can't allocate initrd")); - if (initrd_mem == NULL) - goto fail; -@@ -435,7 +451,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -- params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA, -+ params = kernel_alloc (KERNEL_MEM, sizeof(*params), -+ GRUB_EFI_RUNTIME_SERVICES_DATA, - "cannot allocate kernel parameters"); - if (!params) - goto fail; -@@ -458,7 +475,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - grub_dprintf ("linux", "new lh is at %p\n", lh); - - grub_dprintf ("linux", "setting up cmdline\n"); -- cmdline = kernel_alloc (lh->cmdline_size + 1, -+ cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, - GRUB_EFI_RUNTIME_SERVICES_DATA, - N_("can't allocate cmdline")); - if (!cmdline) -@@ -506,7 +523,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; - kernel_size = lh->init_size; -- kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE, -+ grub_dprintf ("linux", "Trying to allocate kernel mem\n"); -+ kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, -+ GRUB_EFI_RUNTIME_SERVICES_CODE, - N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) diff --git a/SOURCES/0282-font-Remove-grub_font_dup_glyph.patch b/SOURCES/0282-font-Remove-grub_font_dup_glyph.patch new file mode 100644 index 0000000..4c3db92 --- /dev/null +++ b/SOURCES/0282-font-Remove-grub_font_dup_glyph.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 02:13:29 +0800 +Subject: [PATCH] font: Remove grub_font_dup_glyph() + +Remove grub_font_dup_glyph() since nobody is using it since 2013, and +I'm too lazy to fix the integer overflow problem in it. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 25ad31c19c331aaa2dbd9bd2b2e2655de5766a9d) +--- + grub-core/font/font.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 1fa181d4ca..a115a63b0c 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1055,20 +1055,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) + return best_glyph; + } + +-#if 0 +-static struct grub_font_glyph * +-grub_font_dup_glyph (struct grub_font_glyph *glyph) +-{ +- static struct grub_font_glyph *ret; +- ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8); +- if (!ret) +- return NULL; +- grub_memcpy (ret, glyph, sizeof (*ret) +- + (glyph->width * glyph->height + 7) / 8); +- return ret; +-} +-#endif +- + /* FIXME: suboptimal. */ + static void + grub_font_blit_glyph (struct grub_font_glyph *target, diff --git a/SOURCES/0283-efi-allocate-the-initrd-within-the-bounds-expressed-.patch b/SOURCES/0283-efi-allocate-the-initrd-within-the-bounds-expressed-.patch deleted file mode 100644 index a58a8b6..0000000 --- a/SOURCES/0283-efi-allocate-the-initrd-within-the-bounds-expressed-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 14:07:50 -0400 -Subject: [PATCH] efi: allocate the initrd within the bounds expressed by the - kernel - -Currently on x86, only linux kernels built with CONFIG_RELOCATABLE for -x86_64 can be loaded above 4G, but the maximum address for the initramfs -is specified via a HdrS field. This allows us to utilize that value, -and unless loading the kernel above 4G, uses the value present there. -If loading kernel above 4G is allowed, we assume loading the initramfs -above 4G also works; in practice this has been true in the kernel code -for quite some time. - -Resolves: rhbz#2112134 - -Signed-off-by: Peter Jones -(cherry picked from commit 3e08c35f316990913718a4457665e8f653ecaa52) ---- - grub-core/loader/i386/efi/linux.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index b9cd443a9a..801e663fee 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -191,6 +191,8 @@ grub_linuxefi_unload (void *data) - cmd_initrdefi->data = 0; - grub_free (context); - -+ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ - return GRUB_ERR_NONE; - } - -@@ -439,11 +441,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - } - #endif - -+ max_addresses[INITRD_MAX_ADDRESS].addr = lh->initrd_addr_max; - #if defined(__x86_64__) - if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G) - { - grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n"); - max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS; -+ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_USABLE_ADDRESS; - } - else - { -@@ -573,6 +577,8 @@ fail: - - grub_dl_unref (my_mod); - -+ max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS; -+ - if (lh) - kernel_free (cmdline, lh->cmdline_size + 1); - diff --git a/SOURCES/0283-font-Fix-integer-overflow-in-ensure_comb_space.patch b/SOURCES/0283-font-Fix-integer-overflow-in-ensure_comb_space.patch new file mode 100644 index 0000000..6b73038 --- /dev/null +++ b/SOURCES/0283-font-Fix-integer-overflow-in-ensure_comb_space.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 5 Aug 2022 02:27:05 +0800 +Subject: [PATCH] font: Fix integer overflow in ensure_comb_space() + +In fact it can't overflow at all because glyph_id->ncomb is only 8-bit +wide. But let's keep safe if somebody changes the width of glyph_id->ncomb +in the future. This patch also fixes the inconsistency between +render_max_comb_glyphs and render_combining_glyphs when grub_malloc() +returns NULL. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit b2740b7e4a03bb8331d48b54b119afea76bb9d5f) +--- + grub-core/font/font.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index a115a63b0c..d0e6340404 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1468,14 +1468,18 @@ ensure_comb_space (const struct grub_unicode_glyph *glyph_id) + if (glyph_id->ncomb <= render_max_comb_glyphs) + return; + +- render_max_comb_glyphs = 2 * glyph_id->ncomb; +- if (render_max_comb_glyphs < 8) ++ if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs)) ++ render_max_comb_glyphs = 0; ++ if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8) + render_max_comb_glyphs = 8; + grub_free (render_combining_glyphs); +- render_combining_glyphs = grub_malloc (render_max_comb_glyphs +- * sizeof (render_combining_glyphs[0])); ++ render_combining_glyphs = (render_max_comb_glyphs > 0) ? ++ grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL; + if (!render_combining_glyphs) +- grub_errno = 0; ++ { ++ render_max_comb_glyphs = 0; ++ grub_errno = GRUB_ERR_NONE; ++ } + } + + int diff --git a/SOURCES/0284-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch b/SOURCES/0284-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch deleted file mode 100644 index 5ae7c7e..0000000 --- a/SOURCES/0284-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 1 Aug 2022 13:04:43 -0400 -Subject: [PATCH] efi: use EFI_LOADER_(CODE|DATA) for kernel and initrd - allocations - -At some point due to an erroneous kernel warning, we switched kernel and -initramfs to being loaded in EFI_RUNTIME_SERVICES_CODE and -EFI_RUNTIME_SERVICES_DATA memory pools. This doesn't appear to be -correct according to the spec, and that kernel warning has gone away. - -This patch puts them back in EFI_LOADER_CODE and EFI_LOADER_DATA -allocations, respectively. - -Resolves: rhbz#2108456 - -Signed-off-by: Peter Jones -(cherry picked from commit 35b5d5fa47bc394c76022e6595b173e68f53225e) ---- - grub-core/loader/i386/efi/linux.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 801e663fee..f23b3f7b01 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -280,7 +280,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[]) - } - - grub_dprintf ("linux", "Trying to allocate initrd mem\n"); -- initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA, -+ initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_LOADER_DATA, - N_("can't allocate initrd")); - if (initrd_mem == NULL) - goto fail; -@@ -456,7 +456,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - #endif - - params = kernel_alloc (KERNEL_MEM, sizeof(*params), -- GRUB_EFI_RUNTIME_SERVICES_DATA, -+ GRUB_EFI_LOADER_DATA, - "cannot allocate kernel parameters"); - if (!params) - goto fail; -@@ -480,7 +480,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - grub_dprintf ("linux", "setting up cmdline\n"); - cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1, -- GRUB_EFI_RUNTIME_SERVICES_DATA, -+ GRUB_EFI_LOADER_DATA, - N_("can't allocate cmdline")); - if (!cmdline) - goto fail; -@@ -529,7 +529,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - kernel_size = lh->init_size; - grub_dprintf ("linux", "Trying to allocate kernel mem\n"); - kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size, -- GRUB_EFI_RUNTIME_SERVICES_CODE, -+ GRUB_EFI_LOADER_CODE, - N_("can't allocate kernel")); - restore_addresses(); - if (!kernel_mem) diff --git a/SOURCES/0284-font-Fix-integer-overflow-in-BMP-index.patch b/SOURCES/0284-font-Fix-integer-overflow-in-BMP-index.patch new file mode 100644 index 0000000..5e10699 --- /dev/null +++ b/SOURCES/0284-font-Fix-integer-overflow-in-BMP-index.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Mon, 15 Aug 2022 02:04:58 +0800 +Subject: [PATCH] font: Fix integer overflow in BMP index + +The BMP index (font->bmp_idx) is designed as a reverse lookup table of +char entries (font->char_index), in order to speed up lookups for BMP +chars (i.e. code < 0x10000). The values in BMP index are the subscripts +of the corresponding char entries, stored in grub_uint16_t, while 0xffff +means not found. + +This patch fixes the problem of large subscript truncated to grub_uint16_t, +leading BMP index to return wrong char entry or report false miss. The +code now checks for bounds and uses BMP index as a hint, and fallbacks +to binary-search if necessary. + +On the occasion add a comment about BMP index is initialized to 0xffff. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit afda8b60ba0712abe01ae1e64c5f7a067a0e6492) +--- + grub-core/font/font.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index d0e6340404..b208a28717 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -300,6 +300,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct + font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); + if (!font->bmp_idx) + return 1; ++ ++ /* Init the BMP index array to 0xffff. */ + grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t)); + + +@@ -328,7 +330,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct + return 1; + } + +- if (entry->code < 0x10000) ++ if (entry->code < 0x10000 && i < 0xffff) + font->bmp_idx[entry->code] = i; + + last_code = entry->code; +@@ -696,9 +698,12 @@ find_glyph (const grub_font_t font, grub_uint32_t code) + /* Use BMP index if possible. */ + if (code < 0x10000 && font->bmp_idx) + { +- if (font->bmp_idx[code] == 0xffff) +- return 0; +- return &table[font->bmp_idx[code]]; ++ if (font->bmp_idx[code] < 0xffff) ++ return &table[font->bmp_idx[code]]; ++ /* ++ * When we are here then lookup in BMP index result in miss, ++ * fallthough to binary-search. ++ */ + } + + /* Do a binary search in `char_index', which is ordered by code point. */ diff --git a/SOURCES/0285-BLS-create-etc-kernel-cmdline-during-mkconfig.patch b/SOURCES/0285-BLS-create-etc-kernel-cmdline-during-mkconfig.patch deleted file mode 100644 index 8d7405e..0000000 --- a/SOURCES/0285-BLS-create-etc-kernel-cmdline-during-mkconfig.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Tue, 2 Aug 2022 15:56:28 -0400 -Subject: [PATCH] BLS: create /etc/kernel/cmdline during mkconfig - -Signed-off-by: Robbie Harwood -(cherry picked from commit 0837dcdf17ac0429bafa4dbf063b2a94385c04ca) ---- - util/grub.d/10_linux.in | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 6ee0a2cf3d..ec529eb814 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -166,6 +166,12 @@ update_bls_cmdline() - local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - local -a files=($(get_sorted_bls)) - -+ if [[ ! -f /etc/kernel/cmdline ]]; then -+ # anaconda has the correct information to do this during install; -+ # afterward, grubby will take care of syncing on updates. -+ echo "$cmdline rhgb quiet" > /etc/kernel/cmdline -+ fi -+ - for bls in "${files[@]}"; do - local options="${cmdline}" - if [ -z "${bls##*debug*}" ]; then diff --git a/SOURCES/0285-font-Fix-integer-underflow-in-binary-search-of-char-.patch b/SOURCES/0285-font-Fix-integer-underflow-in-binary-search-of-char-.patch new file mode 100644 index 0000000..e81824b --- /dev/null +++ b/SOURCES/0285-font-Fix-integer-underflow-in-binary-search-of-char-.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sun, 14 Aug 2022 18:09:38 +0800 +Subject: [PATCH] font: Fix integer underflow in binary search of char index + +If search target is less than all entries in font->index then "hi" +variable is set to -1, which translates to SIZE_MAX and leads to errors. + +This patch fixes the problem by replacing the entire binary search code +with the libstdc++'s std::lower_bound() implementation. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit c140a086838e7c9af87842036f891b8393a8c4bc) +--- + grub-core/font/font.c | 40 ++++++++++++++++++++++------------------ + 1 file changed, 22 insertions(+), 18 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index b208a28717..193dfec045 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -688,12 +688,12 @@ read_be_int16 (grub_file_t file, grub_int16_t * value) + static inline struct char_index_entry * + find_glyph (const grub_font_t font, grub_uint32_t code) + { +- struct char_index_entry *table; +- grub_size_t lo; +- grub_size_t hi; +- grub_size_t mid; ++ struct char_index_entry *table, *first, *end; ++ grub_size_t len; + + table = font->char_index; ++ if (table == NULL) ++ return NULL; + + /* Use BMP index if possible. */ + if (code < 0x10000 && font->bmp_idx) +@@ -706,25 +706,29 @@ find_glyph (const grub_font_t font, grub_uint32_t code) + */ + } + +- /* Do a binary search in `char_index', which is ordered by code point. */ +- lo = 0; +- hi = font->num_chars - 1; ++ /* ++ * Do a binary search in char_index which is ordered by code point. ++ * The code below is the same as libstdc++'s std::lower_bound(). ++ */ ++ first = table; ++ len = font->num_chars; ++ end = first + len; + +- if (!table) +- return 0; +- +- while (lo <= hi) ++ while (len > 0) + { +- mid = lo + (hi - lo) / 2; +- if (code < table[mid].code) +- hi = mid - 1; +- else if (code > table[mid].code) +- lo = mid + 1; ++ grub_size_t half = len >> 1; ++ struct char_index_entry *middle = first + half; ++ ++ if (middle->code < code) ++ { ++ first = middle + 1; ++ len = len - half - 1; ++ } + else +- return &table[mid]; ++ len = half; + } + +- return 0; ++ return (first < end && first->code == code) ? first : NULL; + } + + /* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded diff --git a/SOURCES/0286-ieee1275-implement-vec5-for-cas-negotiation.patch b/SOURCES/0286-ieee1275-implement-vec5-for-cas-negotiation.patch deleted file mode 100644 index f9f2170..0000000 --- a/SOURCES/0286-ieee1275-implement-vec5-for-cas-negotiation.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Diego Domingos -Date: Thu, 25 Aug 2022 11:37:56 -0400 -Subject: [PATCH] ieee1275: implement vec5 for cas negotiation - -As a legacy support, if the vector 5 is not implemented, Power -Hypervisor will consider the max CPUs as 64 instead 256 currently -supported during client-architecture-support negotiation. - -This patch implements the vector 5 and set the MAX CPUs to 256 while -setting the others values to 0 (default). - -Signed-off-by: Diego Domingos -Signed-off-by: Robbie Harwood -(cherry picked from commit f735c65b6da8a9d4251242b37774e1a517511253) ---- - grub-core/kern/ieee1275/init.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c -index ef55107467..6a51c9efab 100644 ---- a/grub-core/kern/ieee1275/init.c -+++ b/grub-core/kern/ieee1275/init.c -@@ -311,6 +311,18 @@ struct option_vector2 { - grub_uint8_t max_pft_size; - } __attribute__((packed)); - -+struct option_vector5 { -+ grub_uint8_t byte1; -+ grub_uint8_t byte2; -+ grub_uint8_t byte3; -+ grub_uint8_t cmo; -+ grub_uint8_t associativity; -+ grub_uint8_t bin_opts; -+ grub_uint8_t micro_checkpoint; -+ grub_uint8_t reserved0; -+ grub_uint32_t max_cpus; -+} __attribute__((packed)); -+ - struct pvr_entry { - grub_uint32_t mask; - grub_uint32_t entry; -@@ -329,6 +341,8 @@ struct cas_vector { - grub_uint16_t vec3; - grub_uint8_t vec4_size; - grub_uint16_t vec4; -+ grub_uint8_t vec5_size; -+ struct option_vector5 vec5; - } __attribute__((packed)); - - /* Call ibm,client-architecture-support to try to get more RMA. -@@ -349,7 +363,7 @@ grub_ieee1275_ibm_cas (void) - } args; - struct cas_vector vector = { - .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ -- .num_vecs = 4 - 1, -+ .num_vecs = 5 - 1, - .vec1_size = 0, - .vec1 = 0x80, /* ignore */ - .vec2_size = 1 + sizeof(struct option_vector2) - 2, -@@ -360,6 +374,10 @@ grub_ieee1275_ibm_cas (void) - .vec3 = 0x00e0, // ask for FP + VMX + DFP but don't halt if unsatisfied - .vec4_size = 2 - 1, - .vec4 = 0x0001, // set required minimum capacity % to the lowest value -+ .vec5_size = 1 + sizeof(struct option_vector5) - 2, -+ .vec5 = { -+ 0, 0, 0, 0, 0, 0, 0, 0, 256 -+ } - }; - - INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); diff --git a/SOURCES/0286-kern-efi-sb-Enforce-verification-of-font-files.patch b/SOURCES/0286-kern-efi-sb-Enforce-verification-of-font-files.patch new file mode 100644 index 0000000..1a381b0 --- /dev/null +++ b/SOURCES/0286-kern-efi-sb-Enforce-verification-of-font-files.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sun, 14 Aug 2022 15:51:54 +0800 +Subject: [PATCH] kern/efi/sb: Enforce verification of font files + +As a mitigation and hardening measure enforce verification of font +files. Then only trusted font files can be load. This will reduce the +attack surface at cost of losing the ability of end-users to customize +fonts if e.g. UEFI Secure Boot is enabled. Vendors can always customize +fonts because they have ability to pack fonts into their GRUB bundles. + +This goal is achieved by: + + * Removing GRUB_FILE_TYPE_FONT from shim lock verifier's + skip-verification list. + + * Adding GRUB_FILE_TYPE_FONT to lockdown verifier's defer-auth list, + so font files must be verified by a verifier before they can be loaded. + +Suggested-by: Daniel Kiper +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 630deb8c0d8b02b670ced4b7030414bcf17aa080) +--- + grub-core/kern/efi/sb.c | 1 - + grub-core/kern/lockdown.c | 1 + + 2 files changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c +index 89c4bb3fd1..db42c2539f 100644 +--- a/grub-core/kern/efi/sb.c ++++ b/grub-core/kern/efi/sb.c +@@ -145,7 +145,6 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + case GRUB_FILE_TYPE_PRINT_BLOCKLIST: + case GRUB_FILE_TYPE_TESTLOAD: + case GRUB_FILE_TYPE_GET_SIZE: +- case GRUB_FILE_TYPE_FONT: + case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: + case GRUB_FILE_TYPE_CAT: + case GRUB_FILE_TYPE_HEXCAT: +diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c +index 0bc70fd42d..af6d493cd3 100644 +--- a/grub-core/kern/lockdown.c ++++ b/grub-core/kern/lockdown.c +@@ -51,6 +51,7 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)), + case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: + case GRUB_FILE_TYPE_ACPI_TABLE: + case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: ++ case GRUB_FILE_TYPE_FONT: + *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; + + /* Fall through. */ diff --git a/SOURCES/0287-fbutil-Fix-integer-overflow.patch b/SOURCES/0287-fbutil-Fix-integer-overflow.patch new file mode 100644 index 0000000..4d32dbd --- /dev/null +++ b/SOURCES/0287-fbutil-Fix-integer-overflow.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Tue, 6 Sep 2022 03:03:21 +0800 +Subject: [PATCH] fbutil: Fix integer overflow + +Expressions like u64 = u32 * u32 are unsafe because their products are +truncated to u32 even if left hand side is u64. This patch fixes all +problems like that one in fbutil. + +To get right result not only left hand side have to be u64 but it's also +necessary to cast at least one of the operands of all leaf operators of +right hand side to u64, e.g. u64 = u32 * u32 + u32 * u32 should be +u64 = (u64)u32 * u32 + (u64)u32 * u32. + +For 1-bit bitmaps grub_uint64_t have to be used. It's safe because any +combination of values in (grub_uint64_t)u32 * u32 + u32 expression will +not overflow grub_uint64_t. + +Other expressions like ptr + u32 * u32 + u32 * u32 are also vulnerable. +They should be ptr + (grub_addr_t)u32 * u32 + (grub_addr_t)u32 * u32. + +This patch also adds a comment to grub_video_fb_get_video_ptr() which +says it's arguments must be valid and no sanity check is performed +(like its siblings in grub-core/video/fb/fbutil.c). + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 50a11a81bc842c58962244a2dc86bbd31a426e12) +--- + grub-core/video/fb/fbutil.c | 4 ++-- + include/grub/fbutil.h | 13 +++++++++---- + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c +index b98bb51fe8..25ef39f47d 100644 +--- a/grub-core/video/fb/fbutil.c ++++ b/grub-core/video/fb/fbutil.c +@@ -67,7 +67,7 @@ get_pixel (struct grub_video_fbblit_info *source, + case 1: + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) + { +- int bit_index = y * source->mode_info->width + x; ++ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; + grub_uint8_t *ptr = source->data + bit_index / 8; + int bit_pos = 7 - bit_index % 8; + color = (*ptr >> bit_pos) & 0x01; +@@ -138,7 +138,7 @@ set_pixel (struct grub_video_fbblit_info *source, + case 1: + if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) + { +- int bit_index = y * source->mode_info->width + x; ++ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; + grub_uint8_t *ptr = source->data + bit_index / 8; + int bit_pos = 7 - bit_index % 8; + *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos); +diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h +index 4205eb917f..78a1ab3b45 100644 +--- a/include/grub/fbutil.h ++++ b/include/grub/fbutil.h +@@ -31,14 +31,19 @@ struct grub_video_fbblit_info + grub_uint8_t *data; + }; + +-/* Don't use for 1-bit bitmaps, addressing needs to be done at the bit level +- and it doesn't make sense, in general, to ask for a pointer +- to a particular pixel's data. */ ++/* ++ * Don't use for 1-bit bitmaps, addressing needs to be done at the bit level ++ * and it doesn't make sense, in general, to ask for a pointer ++ * to a particular pixel's data. ++ * ++ * This function assumes that bounds checking has been done in previous phase ++ * and they are opted out in here. ++ */ + static inline void * + grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, + unsigned int x, unsigned int y) + { +- return source->data + y * source->mode_info->pitch + x * source->mode_info->bytes_per_pixel; ++ return source->data + (grub_addr_t) y * source->mode_info->pitch + (grub_addr_t) x * source->mode_info->bytes_per_pixel; + } + + /* Advance pointer by VAL bytes. If there is no unaligned access available, diff --git a/SOURCES/0287-squish-don-t-dup-rhgb-quiet-check-mtimes.patch b/SOURCES/0287-squish-don-t-dup-rhgb-quiet-check-mtimes.patch deleted file mode 100644 index 9498f71..0000000 --- a/SOURCES/0287-squish-don-t-dup-rhgb-quiet-check-mtimes.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 17 Aug 2022 10:26:07 -0400 -Subject: [PATCH] squish: don't dup rhgb quiet, check mtimes - -Signed-off-by: Robbie Harwood -(cherry picked from commit 275a0487c74e309cfd0a8c670740f6c34e729c45) ---- - util/grub.d/10_linux.in | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index ec529eb814..becf5ba9c6 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -166,10 +166,16 @@ update_bls_cmdline() - local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - local -a files=($(get_sorted_bls)) - -- if [[ ! -f /etc/kernel/cmdline ]]; then -- # anaconda has the correct information to do this during install; -- # afterward, grubby will take care of syncing on updates. -- echo "$cmdline rhgb quiet" > /etc/kernel/cmdline -+ if [[ ! -f /etc/kernel/cmdline ]] || -+ [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then -+ # anaconda has the correct information to create this during install; -+ # afterward, grubby will take care of syncing on updates. If the user -+ # has modified /etc/default/grub, try to cope. -+ if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then -+ # ensure these only show up once -+ cmdline="$cmdline rhgb quiet" -+ fi -+ echo "$cmdline" > /etc/kernel/cmdline - fi - - for bls in "${files[@]}"; do diff --git a/SOURCES/0288-font-Fix-an-integer-underflow-in-blit_comb.patch b/SOURCES/0288-font-Fix-an-integer-underflow-in-blit_comb.patch new file mode 100644 index 0000000..72f4308 --- /dev/null +++ b/SOURCES/0288-font-Fix-an-integer-underflow-in-blit_comb.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Mon, 24 Oct 2022 08:05:35 +0800 +Subject: [PATCH] font: Fix an integer underflow in blit_comb() + +The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may +evaluate to a very big invalid value even if both ctx.bounds.height and +combining_glyphs[i]->height are small integers. For example, if +ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this +expression evaluates to 2147483647 (expected -1). This is because +coordinates are allowed to be negative but ctx.bounds.height is an +unsigned int. So, the subtraction operates on unsigned ints and +underflows to a very big value. The division makes things even worse. +The quotient is still an invalid value even if converted back to int. + +This patch fixes the problem by casting ctx.bounds.height to int. As +a result the subtraction will operate on int and grub_uint16_t which +will be promoted to an int. So, the underflow will no longer happen. Other +uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, +to ensure coordinates are always calculated on signed integers. + +Fixes: CVE-2022-3775 + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 6d2668dea3774ed74c4cd1eadd146f1b846bc3d4) +--- + grub-core/font/font.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 193dfec045..12a5f0d08c 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + ctx.bounds.height = main_glyph->height; + + above_rightx = main_glyph->offset_x + main_glyph->width; +- above_righty = ctx.bounds.y + ctx.bounds.height; ++ above_righty = ctx.bounds.y + (int) ctx.bounds.height; + + above_leftx = main_glyph->offset_x; +- above_lefty = ctx.bounds.y + ctx.bounds.height; ++ above_lefty = ctx.bounds.y + (int) ctx.bounds.height; + +- below_rightx = ctx.bounds.x + ctx.bounds.width; ++ below_rightx = ctx.bounds.x + (int) ctx.bounds.width; + below_righty = ctx.bounds.y; + + comb = grub_unicode_get_comb (glyph_id); +@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + + if (!combining_glyphs[i]) + continue; +- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; ++ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; + /* CGJ is to avoid diacritics reordering. */ + if (comb[i].code + == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) +@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + case GRUB_UNICODE_COMB_OVERLAY: + do_blit (combining_glyphs[i], + targetx, +- (ctx.bounds.height - combining_glyphs[i]->height) / 2 +- - (ctx.bounds.height + ctx.bounds.y), &ctx); ++ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 ++ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); + if (min_devwidth < combining_glyphs[i]->width) + min_devwidth = combining_glyphs[i]->width; + break; +@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + /* Fallthrough. */ + case GRUB_UNICODE_STACK_ATTACHED_ABOVE: + do_blit (combining_glyphs[i], targetx, +- -(ctx.bounds.height + ctx.bounds.y + space ++ -((int) ctx.bounds.height + ctx.bounds.y + space + + combining_glyphs[i]->height), &ctx); + if (min_devwidth < combining_glyphs[i]->width) + min_devwidth = combining_glyphs[i]->width; +@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + + case GRUB_UNICODE_COMB_HEBREW_DAGESH: + do_blit (combining_glyphs[i], targetx, +- -(ctx.bounds.height / 2 + ctx.bounds.y ++ -((int) ctx.bounds.height / 2 + ctx.bounds.y + + combining_glyphs[i]->height / 2), &ctx); + if (min_devwidth < combining_glyphs[i]->width) + min_devwidth = combining_glyphs[i]->width; diff --git a/SOURCES/0288-squish-give-up-on-rhgb-quiet.patch b/SOURCES/0288-squish-give-up-on-rhgb-quiet.patch deleted file mode 100644 index 6e994ed..0000000 --- a/SOURCES/0288-squish-give-up-on-rhgb-quiet.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -Date: Wed, 17 Aug 2022 11:30:30 -0400 -Subject: [PATCH] squish: give up on rhgb quiet - -Signed-off-by: Robbie Harwood -(cherry picked from commit 12354f586f0748efc5c016b7d2053330f784ab4e) ---- - util/grub.d/10_linux.in | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index becf5ba9c6..5a7e5326da 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -171,10 +171,6 @@ update_bls_cmdline() - # anaconda has the correct information to create this during install; - # afterward, grubby will take care of syncing on updates. If the user - # has modified /etc/default/grub, try to cope. -- if [[ ! "$cmdline" =~ "rhgb quiet" ]]; then -- # ensure these only show up once -- cmdline="$cmdline rhgb quiet" -- fi - echo "$cmdline" > /etc/kernel/cmdline - fi - diff --git a/SOURCES/0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch b/SOURCES/0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch new file mode 100644 index 0000000..5207c12 --- /dev/null +++ b/SOURCES/0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Mon, 24 Oct 2022 07:15:41 +0800 +Subject: [PATCH] font: Harden grub_font_blit_glyph() and + grub_font_blit_glyph_mirror() + +As a mitigation and hardening measure add sanity checks to +grub_font_blit_glyph() and grub_font_blit_glyph_mirror(). This patch +makes these two functions do nothing if target blitting area isn't fully +contained in target bitmap. Therefore, if complex calculations in caller +overflows and malicious coordinates are given, we are still safe because +any coordinates which result in out-of-bound-write are rejected. However, +this patch only checks for invalid coordinates, and doesn't provide any +protection against invalid source glyph or destination glyph, e.g. +mismatch between glyph size and buffer size. + +This hardening measure is designed to mitigate possible overflows in +blit_comb(). If overflow occurs, it may return invalid bounding box +during dry run and call grub_font_blit_glyph() with malicious +coordinates during actual blitting. However, we are still safe because +the scratch glyph itself is valid, although its size makes no sense, and +any invalid coordinates are rejected. + +It would be better to call grub_fatal() if illegal parameter is detected. +However, doing this may end up in a dangerous recursion because grub_fatal() +would print messages to the screen and we are in the progress of drawing +characters on the screen. + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit fcd7aa0c278f7cf3fb9f93f1a3966e1792339eb6) +--- + grub-core/font/font.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 12a5f0d08c..29fbb94294 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -1069,8 +1069,15 @@ static void + grub_font_blit_glyph (struct grub_font_glyph *target, + struct grub_font_glyph *src, unsigned dx, unsigned dy) + { ++ grub_uint16_t max_x, max_y; + unsigned src_bit, tgt_bit, src_byte, tgt_byte; + unsigned i, j; ++ ++ /* Harden against out-of-bound writes. */ ++ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || ++ (grub_add (dy, src->height, &max_y) || max_y > target->height)) ++ return; ++ + for (i = 0; i < src->height; i++) + { + src_bit = (src->width * i) % 8; +@@ -1102,9 +1109,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target, + struct grub_font_glyph *src, + unsigned dx, unsigned dy) + { ++ grub_uint16_t max_x, max_y; + unsigned tgt_bit, src_byte, tgt_byte; + signed src_bit; + unsigned i, j; ++ ++ /* Harden against out-of-bound writes. */ ++ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || ++ (grub_add (dy, src->height, &max_y) || max_y > target->height)) ++ return; ++ + for (i = 0; i < src->height; i++) + { + src_bit = (src->width * i + src->width - 1) % 8; diff --git a/SOURCES/0289-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch b/SOURCES/0289-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch deleted file mode 100644 index e1e6a87..0000000 --- a/SOURCES/0289-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jonathan Lebon -Date: Wed, 17 Aug 2022 10:26:03 -0400 -Subject: [PATCH] squish: BLS: only write /etc/kernel/cmdline if writable - -On OSTree systems, `grub2-mkconfig` is run with `/etc` mounted read-only -because as part of the promise of transactional updates, we want to make -sure that we're not modifying the current deployment's state (`/etc` or -`/var`). - -This conflicts with 0837dcdf1 ("BLS: create /etc/kernel/cmdline during -mkconfig") which wants to write to `/etc/kernel/cmdline`. I'm not -exactly sure on the background there, but based on the comment I think -the intent is to fulfill grubby's expectation that the file exists. - -However, in systems like Silverblue, kernel arguments are managed by the -rpm-ostree stack and grubby is not shipped at all. - -Adjust the script slightly so that we only write `/etc/kernel/cmdline` -if the parent directory is writable. - -In the future, we're hoping to simplify things further on rpm-ostree -systems by not running `grub2-mkconfig` at all since libostree already -directly writes BLS entries. Doing that would also have avoided this, -but ratcheting it into existing systems needs more careful thought. - -Signed-off-by: Jonathan Lebon - -Fixes: https://github.com/fedora-silverblue/issue-tracker/issues/322 -(cherry picked from commit 3c3d1a3c4a2dc4adfb38c2724618fefc913a63fc) ---- - util/grub.d/10_linux.in | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in -index 5a7e5326da..b1b9255c32 100644 ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -166,12 +166,13 @@ update_bls_cmdline() - local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - local -a files=($(get_sorted_bls)) - -- if [[ ! -f /etc/kernel/cmdline ]] || -- [[ /etc/kernel/cmdline -ot /etc/default/grub ]]; then -- # anaconda has the correct information to create this during install; -- # afterward, grubby will take care of syncing on updates. If the user -- # has modified /etc/default/grub, try to cope. -- echo "$cmdline" > /etc/kernel/cmdline -+ if [ -w /etc/kernel ] && -+ [[ ! -f /etc/kernel/cmdline || -+ /etc/kernel/cmdline -ot /etc/default/grub ]]; then -+ # anaconda has the correct information to create this during install; -+ # afterward, grubby will take care of syncing on updates. If the user -+ # has modified /etc/default/grub, try to cope. -+ echo "$cmdline" > /etc/kernel/cmdline - fi - - for bls in "${files[@]}"; do diff --git a/SOURCES/0290-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch b/SOURCES/0290-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch new file mode 100644 index 0000000..c2bcc18 --- /dev/null +++ b/SOURCES/0290-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 28 Oct 2022 17:29:16 +0800 +Subject: [PATCH] font: Assign null_font to glyphs in ascii_font_glyph[] + +The calculations in blit_comb() need information from glyph's font, e.g. +grub_font_get_xheight(main_glyph->font). However, main_glyph->font is +NULL if main_glyph comes from ascii_font_glyph[]. Therefore +grub_font_get_*() crashes because of NULL pointer. + +There is already a solution, the null_font. So, assign it to those glyphs +in ascii_font_glyph[]. + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit dd539d695482069d28b40f2d3821f710cdcf6ee6) +--- + grub-core/font/font.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 29fbb94294..e6616e610c 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -137,7 +137,7 @@ ascii_glyph_lookup (grub_uint32_t code) + ascii_font_glyph[current]->offset_x = 0; + ascii_font_glyph[current]->offset_y = -2; + ascii_font_glyph[current]->device_width = 8; +- ascii_font_glyph[current]->font = NULL; ++ ascii_font_glyph[current]->font = &null_font; + + grub_memcpy (ascii_font_glyph[current]->bitmap, + &ascii_bitmaps[current * ASCII_BITMAP_SIZE], diff --git a/SOURCES/0290-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch b/SOURCES/0290-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch deleted file mode 100644 index 12c3525..0000000 --- a/SOURCES/0290-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 11 Oct 2022 17:00:50 -0400 -Subject: [PATCH] x86-efi: Fix an incorrect array size in kernel allocation - -In 81a6ebf62bbe166ddc968463df2e8bd481bf697c ("efi: split allocation -policy for kernel vs initrd memories."), I introduced a split in the -kernel allocator to allow for different dynamic policies for the kernel -and the initrd allocations. - -Unfortunately, that change increased the size of the policy data used to -make decisions, but did not change the size of the temporary storage we -use to back it up and restore. This results in some of .data getting -clobbered at runtime, and hilarity ensues. - -This patch makes the size of the backup storage be based on the size of -the initial policy data. - -Signed-off-by: Peter Jones -(cherry picked from commit 37747b22342499a798ca3a8895770cd93b6e1258) ---- - grub-core/loader/i386/efi/linux.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index f23b3f7b01..18aadc3e07 100644 ---- a/grub-core/loader/i386/efi/linux.c -+++ b/grub-core/loader/i386/efi/linux.c -@@ -93,7 +93,7 @@ static struct allocation_choice max_addresses[] = - { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS }, - { NO_MEM, 0, 0 } - }; --static struct allocation_choice saved_addresses[4]; -+static struct allocation_choice saved_addresses[sizeof(max_addresses) / sizeof(max_addresses[0])]; - - #define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses)) - #define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses)) diff --git a/SOURCES/0291-commands-efi-tpm-Refine-the-status-of-log-event.patch b/SOURCES/0291-commands-efi-tpm-Refine-the-status-of-log-event.patch deleted file mode 100644 index 12315fd..0000000 --- a/SOURCES/0291-commands-efi-tpm-Refine-the-status-of-log-event.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lu Ken -Date: Wed, 13 Jul 2022 10:06:10 +0800 -Subject: [PATCH] commands/efi/tpm: Refine the status of log event - -1. Use macro GRUB_ERR_NONE instead of hard code 0. -2. Keep lowercase of the first char for the status string of log event. - -Signed-off-by: Lu Ken -Reviewed-by: Daniel Kiper -(cherry picked from commit 922898573e37135f5dedc16f3e15a1d1d4c53f8a) -(cherry picked from commit a326f1247c4d3a1d1079eacbe7e58b35b9a287e2) ---- - grub-core/commands/efi/tpm.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c -index a97d85368a..7acf510499 100644 ---- a/grub-core/commands/efi/tpm.c -+++ b/grub-core/commands/efi/tpm.c -@@ -135,17 +135,17 @@ grub_efi_log_event_status (grub_efi_status_t status) - switch (status) - { - case GRUB_EFI_SUCCESS: -- return 0; -+ return GRUB_ERR_NONE; - case GRUB_EFI_DEVICE_ERROR: -- return grub_error (GRUB_ERR_IO, N_("Command failed")); -+ return grub_error (GRUB_ERR_IO, N_("command failed")); - case GRUB_EFI_INVALID_PARAMETER: -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter")); - case GRUB_EFI_BUFFER_TOO_SMALL: -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small")); - case GRUB_EFI_NOT_FOUND: - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); - default: -- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unknown TPM error")); - } - } - diff --git a/SOURCES/0291-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch b/SOURCES/0291-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch new file mode 100644 index 0000000..ec2184f --- /dev/null +++ b/SOURCES/0291-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Fri, 28 Oct 2022 21:31:39 +0800 +Subject: [PATCH] normal/charset: Fix an integer overflow in + grub_unicode_aglomerate_comb() + +The out->ncomb is a bit-field of 8 bits. So, the max possible value is 255. +However, code in grub_unicode_aglomerate_comb() doesn't check for an +overflow when incrementing out->ncomb. If out->ncomb is already 255, +after incrementing it will get 0 instead of 256, and cause illegal +memory access in subsequent processing. + +This patch introduces GRUB_UNICODE_NCOMB_MAX to represent the max +acceptable value of ncomb. The code now checks for this limit and +ignores additional combining characters when limit is reached. + +Reported-by: Daniel Axtens +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit da90d62316a3b105d2fbd7334d6521936bd6dcf6) +--- + grub-core/normal/charset.c | 3 +++ + include/grub/unicode.h | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c +index 7a5a7c153c..c243ca6dae 100644 +--- a/grub-core/normal/charset.c ++++ b/grub-core/normal/charset.c +@@ -472,6 +472,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, + if (!haveout) + continue; + ++ if (out->ncomb == GRUB_UNICODE_NCOMB_MAX) ++ continue; ++ + if (comb_type == GRUB_UNICODE_COMB_MC + || comb_type == GRUB_UNICODE_COMB_ME + || comb_type == GRUB_UNICODE_COMB_MN) +diff --git a/include/grub/unicode.h b/include/grub/unicode.h +index 4de986a857..c4f6fca043 100644 +--- a/include/grub/unicode.h ++++ b/include/grub/unicode.h +@@ -147,7 +147,9 @@ struct grub_unicode_glyph + grub_uint8_t bidi_level:6; /* minimum: 6 */ + enum grub_bidi_type bidi_type:5; /* minimum: :5 */ + ++#define GRUB_UNICODE_NCOMB_MAX ((1 << 8) - 1) + unsigned ncomb:8; ++ + /* Hint by unicode subsystem how wide this character usually is. + Real width is determined by font. Set only in UTF-8 stream. */ + int estimated_width:8; diff --git a/SOURCES/0292-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch b/SOURCES/0292-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch deleted file mode 100644 index 3e8d899..0000000 --- a/SOURCES/0292-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lu Ken -Date: Wed, 13 Jul 2022 10:06:11 +0800 -Subject: [PATCH] commands/efi/tpm: Use grub_strcpy() instead of grub_memcpy() - -The event description is a string, so using grub_strcpy() is cleaner than -using grub_memcpy(). - -Signed-off-by: Lu Ken -Reviewed-by: Daniel Kiper -(cherry picked from commit ef8679b645a63eb9eb191bb9539d7d25a9d6ff3b) -(cherry picked from commit 6d0d478585c435cce50d4025d2301dc0413bc5c0) ---- - grub-core/commands/efi/tpm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c -index 7acf510499..bb59599721 100644 ---- a/grub-core/commands/efi/tpm.c -+++ b/grub-core/commands/efi/tpm.c -@@ -175,7 +175,7 @@ grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, - event->PCRIndex = pcr; - event->EventType = EV_IPL; - event->EventSize = grub_strlen (description) + 1; -- grub_memcpy (event->Event, description, event->EventSize); -+ grub_strcpy ((char *) event->Event, description); - - algorithm = TCG_ALG_SHA; - status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size, -@@ -212,7 +212,7 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, - event->Header.EventType = EV_IPL; - event->Size = - sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1; -- grub_memcpy (event->Event, description, grub_strlen (description) + 1); -+ grub_strcpy ((char *) event->Event, description); - - status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf, - (grub_uint64_t) size, event); diff --git a/SOURCES/0292-font-Try-opening-fonts-from-the-bundled-memdisk.patch b/SOURCES/0292-font-Try-opening-fonts-from-the-bundled-memdisk.patch new file mode 100644 index 0000000..bad9d90 --- /dev/null +++ b/SOURCES/0292-font-Try-opening-fonts-from-the-bundled-memdisk.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Wed, 16 Nov 2022 14:40:04 +0000 +Subject: [PATCH] font: Try opening fonts from the bundled memdisk + +Signed-off-by: Robbie Harwood +--- + grub-core/font/font.c | 48 +++++++++++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 17 deletions(-) + +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index e6616e610c..e421d1ae6f 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -409,6 +409,27 @@ read_section_as_short (struct font_file_section *section, + return 0; + } + ++static grub_file_t ++try_open_from_prefix (const char *prefix, const char *filename) ++{ ++ grub_file_t file; ++ char *fullname, *ptr; ++ ++ fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 ++ + sizeof ("/fonts/") + sizeof (".pf2")); ++ if (!fullname) ++ return 0; ++ ptr = grub_stpcpy (fullname, prefix); ++ ptr = grub_stpcpy (ptr, "/fonts/"); ++ ptr = grub_stpcpy (ptr, filename); ++ ptr = grub_stpcpy (ptr, ".pf2"); ++ *ptr = 0; ++ ++ file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); ++ grub_free (fullname); ++ return file; ++} ++ + /* Load a font and add it to the beginning of the global font list. + Returns 0 upon success, nonzero upon failure. */ + grub_font_t +@@ -427,25 +448,18 @@ grub_font_load (const char *filename) + file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024); + else + { +- const char *prefix = grub_env_get ("prefix"); +- char *fullname, *ptr; +- if (!prefix) ++ file = try_open_from_prefix ("(memdisk)", filename); ++ if (!file) + { +- grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), +- "prefix"); +- goto fail; ++ const char *prefix = grub_env_get ("prefix"); ++ if (!prefix) ++ { ++ grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), ++ "prefix"); ++ goto fail; ++ } ++ file = try_open_from_prefix (prefix, filename); + } +- fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 +- + sizeof ("/fonts/") + sizeof (".pf2")); +- if (!fullname) +- goto fail; +- ptr = grub_stpcpy (fullname, prefix); +- ptr = grub_stpcpy (ptr, "/fonts/"); +- ptr = grub_stpcpy (ptr, filename); +- ptr = grub_stpcpy (ptr, ".pf2"); +- *ptr = 0; +- file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); +- grub_free (fullname); + } + if (!file) + goto fail; diff --git a/SOURCES/0293-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch b/SOURCES/0293-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch deleted file mode 100644 index c8b703b..0000000 --- a/SOURCES/0293-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lu Ken -Date: Wed, 13 Jul 2022 10:06:12 +0800 -Subject: [PATCH] efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support - -The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware -in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL. -It was proposed by Intel and ARM and approved by UEFI organization. - -It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 . -The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h . - -Signed-off-by: Lu Ken -Reviewed-by: Daniel Kiper -(cherry picked from commit 4c76565b6cb885b7e144dc27f3612066844e2d19) -(cherry picked from commit cad2fc1ff659390a228efb474a72f7ed7ab21697) ---- - grub-core/commands/efi/tpm.c | 48 ++++++++++++++ - include/grub/efi/cc.h | 151 +++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 199 insertions(+) - create mode 100644 include/grub/efi/cc.h - -diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c -index bb59599721..ae09c1bf8b 100644 ---- a/grub-core/commands/efi/tpm.c -+++ b/grub-core/commands/efi/tpm.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -31,6 +32,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t; - - static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; - static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; -+static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID; - - static grub_efi_handle_t *grub_tpm_handle; - static grub_uint8_t grub_tpm_version; -@@ -221,6 +223,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, - return grub_efi_log_event_status (status); - } - -+static void -+grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, -+ const char *description) -+{ -+ grub_efi_cc_event_t *event; -+ grub_efi_status_t status; -+ grub_efi_cc_protocol_t *cc; -+ grub_efi_cc_mr_index_t mr; -+ -+ cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL); -+ if (cc == NULL) -+ return; -+ -+ status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr); -+ if (status != GRUB_EFI_SUCCESS) -+ { -+ grub_efi_log_event_status (status); -+ return; -+ } -+ -+ event = grub_zalloc (sizeof (grub_efi_cc_event_t) + -+ grub_strlen (description) + 1); -+ if (event == NULL) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer")); -+ return; -+ } -+ -+ event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t); -+ event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION; -+ event->Header.MrIndex = mr; -+ event->Header.EventType = EV_IPL; -+ event->Size = sizeof (*event) + grub_strlen (description) + 1; -+ grub_strcpy ((char *) event->Event, description); -+ -+ status = efi_call_5 (cc->hash_log_extend_event, cc, 0, -+ (grub_efi_physical_address_t)(grub_addr_t) buf, -+ (grub_efi_uint64_t) size, event); -+ grub_free (event); -+ -+ if (status != GRUB_EFI_SUCCESS) -+ grub_efi_log_event_status (status); -+} -+ - grub_err_t - grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, - const char *description) -@@ -228,6 +274,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, - grub_efi_handle_t tpm_handle; - grub_efi_uint8_t protocol_version; - -+ grub_cc_log_event(buf, size, pcr, description); -+ - if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) - return 0; - -diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h -new file mode 100644 -index 0000000000..8960306890 ---- /dev/null -+++ b/include/grub/efi/cc.h -@@ -0,0 +1,151 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_EFI_CC_H -+#define GRUB_EFI_CC_H 1 -+ -+#include -+#include -+#include -+ -+#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \ -+ { 0x96751a3d, 0x72f4, 0x41a6, \ -+ { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \ -+ }; -+ -+struct grub_efi_cc_version -+{ -+ grub_efi_uint8_t Major; -+ grub_efi_uint8_t Minor; -+}; -+typedef struct grub_efi_cc_version grub_efi_cc_version_t; -+ -+/* EFI_CC Type/SubType definition. */ -+#define GRUB_EFI_CC_TYPE_NONE 0 -+#define GRUB_EFI_CC_TYPE_SEV 1 -+#define GRUB_EFI_CC_TYPE_TDX 2 -+ -+struct grub_efi_cc_type -+{ -+ grub_efi_uint8_t Type; -+ grub_efi_uint8_t SubType; -+}; -+typedef struct grub_efi_cc_type grub_efi_cc_type_t; -+ -+typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t; -+typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t; -+typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t; -+typedef grub_efi_uint32_t grub_efi_cc_mr_index_t; -+ -+/* Intel TDX measure register index. */ -+#define GRUB_TDX_MR_INDEX_MRTD 0 -+#define GRUB_TDX_MR_INDEX_RTMR0 1 -+#define GRUB_TDX_MR_INDEX_RTMR1 2 -+#define GRUB_TDX_MR_INDEX_RTMR2 3 -+#define GRUB_TDX_MR_INDEX_RTMR3 4 -+ -+#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002 -+#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004 -+#define GRUB_EFI_CC_EVENT_HEADER_VERSION 1 -+ -+struct grub_efi_cc_event_header -+{ -+ /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */ -+ grub_efi_uint32_t HeaderSize; -+ -+ /* -+ * Header version. For this version of this specification, -+ * the value shall be 1. -+ */ -+ grub_efi_uint16_t HeaderVersion; -+ -+ /* Index of the MR that shall be extended. */ -+ grub_efi_cc_mr_index_t MrIndex; -+ -+ /* Type of the event that shall be extended (and optionally logged). */ -+ grub_efi_uint32_t EventType; -+} GRUB_PACKED; -+typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t; -+ -+struct grub_efi_cc_event -+{ -+ /* Total size of the event including the Size component, the header and the Event data. */ -+ grub_efi_uint32_t Size; -+ grub_efi_cc_event_header_t Header; -+ grub_efi_uint8_t Event[0]; -+} GRUB_PACKED; -+typedef struct grub_efi_cc_event grub_efi_cc_event_t; -+ -+struct grub_efi_cc_boot_service_capability -+{ -+ /* Allocated size of the structure. */ -+ grub_efi_uint8_t Size; -+ -+ /* -+ * Version of the grub_efi_cc_boot_service_capability_t structure itself. -+ * For this version of the protocol, the Major version shall be set to 1 -+ * and the Minor version shall be set to 1. -+ */ -+ grub_efi_cc_version_t StructureVersion; -+ -+ /* -+ * Version of the EFI TD protocol. -+ * For this version of the protocol, the Major version shall be set to 1 -+ * and the Minor version shall be set to 1. -+ */ -+ grub_efi_cc_version_t ProtocolVersion; -+ -+ /* Supported hash algorithms. */ -+ grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap; -+ -+ /* Bitmap of supported event log formats. */ -+ grub_efi_cc_event_log_bitmap_t SupportedEventLogs; -+ -+ /* Indicates the CC type. */ -+ grub_efi_cc_type_t CcType; -+}; -+typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t; -+ -+struct grub_efi_cc_protocol -+{ -+ grub_efi_status_t -+ (*get_capability) (struct grub_efi_cc_protocol *this, -+ grub_efi_cc_boot_service_capability_t *ProtocolCapability); -+ -+ grub_efi_status_t -+ (*get_event_log) (struct grub_efi_cc_protocol *this, -+ grub_efi_cc_event_log_format_t EventLogFormat, -+ grub_efi_physical_address_t *EventLogLocation, -+ grub_efi_physical_address_t *EventLogLastEntry, -+ grub_efi_boolean_t *EventLogTruncated); -+ -+ grub_efi_status_t -+ (*hash_log_extend_event) (struct grub_efi_cc_protocol *this, -+ grub_efi_uint64_t Flags, -+ grub_efi_physical_address_t DataToHash, -+ grub_efi_uint64_t DataToHashLen, -+ grub_efi_cc_event_t *EfiCcEvent); -+ -+ grub_efi_status_t -+ (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this, -+ grub_efi_uint32_t PcrIndex, -+ grub_efi_cc_mr_index_t *MrIndex); -+}; -+typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t; -+ -+#endif diff --git a/SOURCES/0293-mm-Clarify-grub_real_malloc.patch b/SOURCES/0293-mm-Clarify-grub_real_malloc.patch new file mode 100644 index 0000000..0a99c08 --- /dev/null +++ b/SOURCES/0293-mm-Clarify-grub_real_malloc.patch @@ -0,0 +1,183 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:46 +1100 +Subject: [PATCH] mm: Clarify grub_real_malloc() + +When iterating through the singly linked list of free blocks, +grub_real_malloc() uses p and q for the current and previous blocks +respectively. This isn't super clear, so swap to using prev and cur. + +This makes another quirk more obvious. The comment at the top of +grub_real_malloc() might lead you to believe that the function will +allocate from *first if there is space in that block. + +It actually doesn't do that, and it can't do that with the current +data structures. If we used up all of *first, we would need to change +the ->next of the previous block to point to *first->next, but we +can't do that because it's a singly linked list and we don't have +access to *first's previous block. + +What grub_real_malloc() actually does is set *first to the initial +previous block, and *first->next is the block we try to allocate +from. That allows us to keep all the data structures consistent. + +Document that. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 246ad6a44c281bb13486ddea0a26bb661db73106) +--- + grub-core/kern/mm.c | 76 +++++++++++++++++++++++++++++------------------------ + 1 file changed, 41 insertions(+), 35 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index d8c8377578..fb20e93acf 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -178,13 +178,20 @@ grub_mm_init_region (void *addr, grub_size_t size) + } + + /* Allocate the number of units N with the alignment ALIGN from the ring +- buffer starting from *FIRST. ALIGN must be a power of two. Both N and +- ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, +- otherwise return NULL. */ ++ * buffer given in *FIRST. ALIGN must be a power of two. Both N and ++ * ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, ++ * otherwise return NULL. ++ * ++ * Note: because in certain circumstances we need to adjust the ->next ++ * pointer of the previous block, we iterate over the singly linked ++ * list with the pair (prev, cur). *FIRST is our initial previous, and ++ * *FIRST->next is our initial current pointer. So we will actually ++ * allocate from *FIRST->next first and *FIRST itself last. ++ */ + static void * + grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + { +- grub_mm_header_t p, q; ++ grub_mm_header_t cur, prev; + + /* When everything is allocated side effect is that *first will have alloc + magic marked, meaning that there is no room in this region. */ +@@ -192,24 +199,24 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + return 0; + + /* Try to search free slot for allocation in this memory region. */ +- for (q = *first, p = q->next; ; q = p, p = p->next) ++ for (prev = *first, cur = prev->next; ; prev = cur, cur = cur->next) + { + grub_off_t extra; + +- extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); ++ extra = ((grub_addr_t) (cur + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); + if (extra) + extra = align - extra; + +- if (! p) ++ if (! cur) + grub_fatal ("null in the ring"); + +- if (p->magic != GRUB_MM_FREE_MAGIC) +- grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic); ++ if (cur->magic != GRUB_MM_FREE_MAGIC) ++ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); + +- if (p->size >= n + extra) ++ if (cur->size >= n + extra) + { +- extra += (p->size - extra - n) & (~(align - 1)); +- if (extra == 0 && p->size == n) ++ extra += (cur->size - extra - n) & (~(align - 1)); ++ if (extra == 0 && cur->size == n) + { + /* There is no special alignment requirement and memory block + is complete match. +@@ -222,9 +229,9 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + | alloc, size=n | | + +---------------+ v + */ +- q->next = p->next; ++ prev->next = cur->next; + } +- else if (align == 1 || p->size == n + extra) ++ else if (align == 1 || cur->size == n + extra) + { + /* There might be alignment requirement, when taking it into + account memory block fits in. +@@ -241,23 +248,22 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + | alloc, size=n | | + +---------------+ v + */ +- +- p->size -= n; +- p += p->size; ++ cur->size -= n; ++ cur += cur->size; + } + else if (extra == 0) + { + grub_mm_header_t r; + +- r = p + extra + n; ++ r = cur + extra + n; + r->magic = GRUB_MM_FREE_MAGIC; +- r->size = p->size - extra - n; +- r->next = p->next; +- q->next = r; ++ r->size = cur->size - extra - n; ++ r->next = cur->next; ++ prev->next = r; + +- if (q == p) ++ if (prev == cur) + { +- q = r; ++ prev = r; + r->next = r; + } + } +@@ -284,32 +290,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + */ + grub_mm_header_t r; + +- r = p + extra + n; ++ r = cur + extra + n; + r->magic = GRUB_MM_FREE_MAGIC; +- r->size = p->size - extra - n; +- r->next = p; ++ r->size = cur->size - extra - n; ++ r->next = cur; + +- p->size = extra; +- q->next = r; +- p += extra; ++ cur->size = extra; ++ prev->next = r; ++ cur += extra; + } + +- p->magic = GRUB_MM_ALLOC_MAGIC; +- p->size = n; ++ cur->magic = GRUB_MM_ALLOC_MAGIC; ++ cur->size = n; + + /* Mark find as a start marker for next allocation to fasten it. + This will have side effect of fragmenting memory as small + pieces before this will be un-used. */ + /* So do it only for chunks under 64K. */ + if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) +- || *first == p) +- *first = q; ++ || *first == cur) ++ *first = prev; + +- return p + 1; ++ return cur + 1; + } + + /* Search was completed without result. */ +- if (p == *first) ++ if (cur == *first) + break; + } + diff --git a/SOURCES/0294-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch b/SOURCES/0294-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch deleted file mode 100644 index e264b09..0000000 --- a/SOURCES/0294-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Wed, 3 Aug 2022 19:45:33 +0800 -Subject: [PATCH] font: Reject glyphs exceeds font->max_glyph_width or - font->max_glyph_height - -Check glyph's width and height against limits specified in font's -metadata. Reject the glyph (and font) if such limits are exceeded. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 5760fcfd466cc757540ea0d591bad6a08caeaa16) -(cherry picked from commit 3b410ef4bb95e607cadeba2193fa90ae9bddb98d) ---- - grub-core/font/font.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index d09bb38d89..2f09a4a55b 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -760,7 +760,9 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) - || read_be_uint16 (font->file, &height) != 0 - || read_be_int16 (font->file, &xoff) != 0 - || read_be_int16 (font->file, &yoff) != 0 -- || read_be_int16 (font->file, &dwidth) != 0) -+ || read_be_int16 (font->file, &dwidth) != 0 -+ || width > font->max_char_width -+ || height > font->max_char_height) - { - remove_font (font); - return 0; diff --git a/SOURCES/0294-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch b/SOURCES/0294-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch new file mode 100644 index 0000000..a5601c9 --- /dev/null +++ b/SOURCES/0294-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:47 +1100 +Subject: [PATCH] mm: grub_real_malloc(): Make small allocs comment match code + +Small allocations move the region's *first pointer. The comment +says that this happens for allocations under 64K. The code says +it's for allocations under 32K. Commit 45bf8b3a7549 changed the +code intentionally: make the comment match. + +Fixes: 45bf8b3a7549 (* grub-core/kern/mm.c (grub_real_malloc): Decrease cut-off of moving the) + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit a847895a8d000bdf27ad4d4326f883a0eed769ca) +--- + grub-core/kern/mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index fb20e93acf..db7e0b2a5b 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -306,7 +306,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) + /* Mark find as a start marker for next allocation to fasten it. + This will have side effect of fragmenting memory as small + pieces before this will be un-used. */ +- /* So do it only for chunks under 64K. */ ++ /* So do it only for chunks under 32K. */ + if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) + || *first == cur) + *first = prev; diff --git a/SOURCES/0295-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch b/SOURCES/0295-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch deleted file mode 100644 index 7ec23ab..0000000 --- a/SOURCES/0295-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 00:51:20 +0800 -Subject: [PATCH] font: Fix size overflow in grub_font_get_glyph_internal() - -The length of memory allocation and file read may overflow. This patch -fixes the problem by using safemath macros. - -There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe -if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz(). -It is safe replacement for such code. It has safemath-like prototype. - -This patch also introduces grub_cast(value, pointer), it casts value to -typeof(*pointer) then store the value to *pointer. It returns true when -overflow occurs or false if there is no overflow. The semantics of arguments -and return value are designed to be consistent with other safemath macros. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 941d10ad6f1dcbd12fb613002249e29ba035f985) -(cherry picked from commit 6bca9693878bdf61dd62b8c784862a48e75f569a) ---- - grub-core/font/font.c | 17 +++++++++++++---- - include/grub/bitmap.h | 18 ++++++++++++++++++ - include/grub/safemath.h | 2 ++ - 3 files changed, 33 insertions(+), 4 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 2f09a4a55b..6a3fbebbd8 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) - grub_int16_t xoff; - grub_int16_t yoff; - grub_int16_t dwidth; -- int len; -+ grub_ssize_t len; -+ grub_size_t sz; - - if (index_entry->glyph) - /* Return cached glyph. */ -@@ -768,9 +769,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) - return 0; - } - -- len = (width * height + 7) / 8; -- glyph = grub_malloc (sizeof (struct grub_font_glyph) + len); -- if (!glyph) -+ /* Calculate real struct size of current glyph. */ -+ if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) || -+ grub_add (sizeof (struct grub_font_glyph), len, &sz)) -+ { -+ remove_font (font); -+ return 0; -+ } -+ -+ /* Allocate and initialize the glyph struct. */ -+ glyph = grub_malloc (sz); -+ if (glyph == NULL) - { - remove_font (font); - return 0; -diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h -index 5728f8ca3a..0d9603f619 100644 ---- a/include/grub/bitmap.h -+++ b/include/grub/bitmap.h -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - struct grub_video_bitmap - { -@@ -79,6 +80,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap) - return bitmap->mode_info.height; - } - -+/* -+ * Calculate and store the size of data buffer of 1bit bitmap in result. -+ * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs. -+ * Return true when overflow occurs or false if there is no overflow. -+ * This function is intentionally implemented as a macro instead of -+ * an inline function. Although a bit awkward, it preserves data types for -+ * safemath macros and reduces macro side effects as much as possible. -+ * -+ * XXX: Will report false overflow if width * height > UINT64_MAX. -+ */ -+#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \ -+({ \ -+ grub_uint64_t _bitmap_pixels; \ -+ grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \ -+ grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \ -+}) -+ - void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap, - struct grub_video_mode_info *mode_info); - -diff --git a/include/grub/safemath.h b/include/grub/safemath.h -index c17b89bba1..bb0f826de1 100644 ---- a/include/grub/safemath.h -+++ b/include/grub/safemath.h -@@ -30,6 +30,8 @@ - #define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res) - #define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res) - -+#define grub_cast(a, res) grub_add ((a), 0, (res)) -+ - #else - #error gcc 5.1 or newer or clang 3.8 or newer is required - #endif diff --git a/SOURCES/0295-mm-Document-grub_free.patch b/SOURCES/0295-mm-Document-grub_free.patch new file mode 100644 index 0000000..6c9b7cc --- /dev/null +++ b/SOURCES/0295-mm-Document-grub_free.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:48 +1100 +Subject: [PATCH] mm: Document grub_free() + +The grub_free() possesses a surprising number of quirks, and also +uses single-letter variable names confusingly to iterate through +the free list. + +Document what's going on. + +Use prev and cur to iterate over the free list. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 1f8d0b01738e49767d662d6426af3570a64565f0) +--- + grub-core/kern/mm.c | 63 ++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 41 insertions(+), 22 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index db7e0b2a5b..0351171cf9 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -446,54 +446,73 @@ grub_free (void *ptr) + } + else + { +- grub_mm_header_t q, s; ++ grub_mm_header_t cur, prev; + + #if 0 +- q = r->first; ++ cur = r->first; + do + { + grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n", +- GRUB_FILE, __LINE__, q, q->size, q->magic); +- q = q->next; ++ GRUB_FILE, __LINE__, cur, cur->size, cur->magic); ++ cur = cur->next; + } +- while (q != r->first); ++ while (cur != r->first); + #endif +- +- for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q = s->next) ++ /* Iterate over all blocks in the free ring. ++ * ++ * The free ring is arranged from high addresses to low ++ * addresses, modulo wraparound. ++ * ++ * We are looking for a block with a higher address than p or ++ * whose next address is lower than p. ++ */ ++ for (prev = r->first, cur = prev->next; cur <= p || cur->next >= p; ++ prev = cur, cur = prev->next) + { +- if (q->magic != GRUB_MM_FREE_MAGIC) +- grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic); ++ if (cur->magic != GRUB_MM_FREE_MAGIC) ++ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); + +- if (q <= q->next && (q > p || q->next < p)) ++ /* Deal with wrap-around */ ++ if (cur <= cur->next && (cur > p || cur->next < p)) + break; + } + ++ /* mark p as free and insert it between cur and cur->next */ + p->magic = GRUB_MM_FREE_MAGIC; +- p->next = q->next; +- q->next = p; ++ p->next = cur->next; ++ cur->next = p; + ++ /* ++ * If the block we are freeing can be merged with the next ++ * free block, do that. ++ */ + if (p->next + p->next->size == p) + { + p->magic = 0; + + p->next->size += p->size; +- q->next = p->next; ++ cur->next = p->next; + p = p->next; + } + +- r->first = q; ++ r->first = cur; + +- if (q == p + p->size) ++ /* Likewise if can be merged with the preceeding free block */ ++ if (cur == p + p->size) + { +- q->magic = 0; +- p->size += q->size; +- if (q == s) +- s = p; +- s->next = p; +- q = s; ++ cur->magic = 0; ++ p->size += cur->size; ++ if (cur == prev) ++ prev = p; ++ prev->next = p; ++ cur = prev; + } + +- r->first = q; ++ /* ++ * Set r->first such that the just free()d block is tried first. ++ * (An allocation is tried from *first->next, and cur->next == p.) ++ */ ++ r->first = cur; + } + } + diff --git a/SOURCES/0296-font-Fix-several-integer-overflows-in-grub_font_cons.patch b/SOURCES/0296-font-Fix-several-integer-overflows-in-grub_font_cons.patch deleted file mode 100644 index fcc1d3c..0000000 --- a/SOURCES/0296-font-Fix-several-integer-overflows-in-grub_font_cons.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 01:58:27 +0800 -Subject: [PATCH] font: Fix several integer overflows in - grub_font_construct_glyph() - -This patch fixes several integer overflows in grub_font_construct_glyph(). -Glyphs of invalid size, zero or leading to an overflow, are rejected. -The inconsistency between "glyph" and "max_glyph_size" when grub_malloc() -returns NULL is fixed too. - -Fixes: CVE-2022-2601 - -Reported-by: Zhang Boyang -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit b1805f251b31a9d3cfae5c3572ddfa630145dbbf) -(cherry picked from commit b91eb9bd6c724339b7d7bb4765b9d36f1ee88b84) ---- - grub-core/font/font.c | 29 +++++++++++++++++------------ - 1 file changed, 17 insertions(+), 12 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 6a3fbebbd8..1fa181d4ca 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1517,6 +1517,7 @@ grub_font_construct_glyph (grub_font_t hinted_font, - struct grub_video_signed_rect bounds; - static struct grub_font_glyph *glyph = 0; - static grub_size_t max_glyph_size = 0; -+ grub_size_t cur_glyph_size; - - ensure_comb_space (glyph_id); - -@@ -1533,29 +1534,33 @@ grub_font_construct_glyph (grub_font_t hinted_font, - if (!glyph_id->ncomb && !glyph_id->attributes) - return main_glyph; - -- if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) -+ if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) || -+ grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size)) -+ return main_glyph; -+ -+ if (max_glyph_size < cur_glyph_size) - { - grub_free (glyph); -- max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2; -- if (max_glyph_size < 8) -- max_glyph_size = 8; -- glyph = grub_malloc (max_glyph_size); -+ if (grub_mul (cur_glyph_size, 2, &max_glyph_size)) -+ max_glyph_size = 0; -+ glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL; - } - if (!glyph) - { -+ max_glyph_size = 0; - grub_errno = GRUB_ERR_NONE; - return main_glyph; - } - -- grub_memset (glyph, 0, sizeof (*glyph) -- + (bounds.width * bounds.height -- + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT); -+ grub_memset (glyph, 0, cur_glyph_size); - - glyph->font = main_glyph->font; -- glyph->width = bounds.width; -- glyph->height = bounds.height; -- glyph->offset_x = bounds.x; -- glyph->offset_y = bounds.y; -+ if (bounds.width == 0 || bounds.height == 0 || -+ grub_cast (bounds.width, &glyph->width) || -+ grub_cast (bounds.height, &glyph->height) || -+ grub_cast (bounds.x, &glyph->offset_x) || -+ grub_cast (bounds.y, &glyph->offset_y)) -+ return main_glyph; - - if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR) - grub_font_blit_glyph_mirror (glyph, main_glyph, diff --git a/SOURCES/0296-mm-Document-grub_mm_init_region.patch b/SOURCES/0296-mm-Document-grub_mm_init_region.patch new file mode 100644 index 0000000..0173f04 --- /dev/null +++ b/SOURCES/0296-mm-Document-grub_mm_init_region.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:49 +1100 +Subject: [PATCH] mm: Document grub_mm_init_region() + +The grub_mm_init_region() does some things that seem magical, especially +around region merging. Make it a bit clearer. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 246d69b7ea619fc1e77dcc5960e37aea45a9808c) +--- + grub-core/kern/mm.c | 31 ++++++++++++++++++++++++++++++- + 1 file changed, 30 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 0351171cf9..1cbf98c7ab 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -128,23 +128,52 @@ grub_mm_init_region (void *addr, grub_size_t size) + if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size) + size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr; + ++ /* Attempt to merge this region with every existing region */ + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) ++ /* ++ * Is the new region immediately below an existing region? That ++ * is, is the address of the memory we're adding now (addr) + size ++ * of the memory we're adding (size) + the bytes we couldn't use ++ * at the start of the region we're considering (q->pre_size) ++ * equal to the address of q? In other words, does the memory ++ * looks like this? ++ * ++ * addr q ++ * |----size-----|-q->pre_size-|| ++ */ + if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) + { ++ /* ++ * Yes, we can merge the memory starting at addr into the ++ * existing region from below. Align up addr to GRUB_MM_ALIGN ++ * so that our new region has proper alignment. ++ */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); ++ /* Copy the region data across */ + *r = *q; ++ /* Consider all the new size as pre-size */ + r->pre_size += size; +- ++ ++ /* ++ * If we have enough pre-size to create a block, create a ++ * block with it. Mark it as allocated and pass it to ++ * grub_free (), which will sort out getting it into the free ++ * list. ++ */ + if (r->pre_size >> GRUB_MM_ALIGN_LOG2) + { + h = (grub_mm_header_t) (r + 1); ++ /* block size is pre-size converted to cells */ + h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); + h->magic = GRUB_MM_ALLOC_MAGIC; ++ /* region size grows by block size converted back to bytes */ + r->size += h->size << GRUB_MM_ALIGN_LOG2; ++ /* adjust pre_size to be accurate */ + r->pre_size &= (GRUB_MM_ALIGN - 1); + *p = r; + grub_free (h + 1); + } ++ /* Replace the old region with the new region */ + *p = r; + return; + } diff --git a/SOURCES/0297-font-Remove-grub_font_dup_glyph.patch b/SOURCES/0297-font-Remove-grub_font_dup_glyph.patch deleted file mode 100644 index a3493f6..0000000 --- a/SOURCES/0297-font-Remove-grub_font_dup_glyph.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 02:13:29 +0800 -Subject: [PATCH] font: Remove grub_font_dup_glyph() - -Remove grub_font_dup_glyph() since nobody is using it since 2013, and -I'm too lazy to fix the integer overflow problem in it. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 25ad31c19c331aaa2dbd9bd2b2e2655de5766a9d) -(cherry picked from commit ad950e1e033318bb50222ed268a6dcfb97389035) ---- - grub-core/font/font.c | 14 -------------- - 1 file changed, 14 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 1fa181d4ca..a115a63b0c 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1055,20 +1055,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) - return best_glyph; - } - --#if 0 --static struct grub_font_glyph * --grub_font_dup_glyph (struct grub_font_glyph *glyph) --{ -- static struct grub_font_glyph *ret; -- ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8); -- if (!ret) -- return NULL; -- grub_memcpy (ret, glyph, sizeof (*ret) -- + (glyph->width * glyph->height + 7) / 8); -- return ret; --} --#endif -- - /* FIXME: suboptimal. */ - static void - grub_font_blit_glyph (struct grub_font_glyph *target, diff --git a/SOURCES/0297-mm-Document-GRUB-internal-memory-management-structur.patch b/SOURCES/0297-mm-Document-GRUB-internal-memory-management-structur.patch new file mode 100644 index 0000000..c793926 --- /dev/null +++ b/SOURCES/0297-mm-Document-GRUB-internal-memory-management-structur.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 25 Nov 2021 02:22:45 +1100 +Subject: [PATCH] mm: Document GRUB internal memory management structures + +I spent more than a trivial quantity of time figuring out pre_size and +whether a memory region's size contains the header cell or not. + +Document the meanings of all the properties. Hopefully now no-one else +has to figure it out! + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit a6c5c52ccffd2674d43db25fb4baa9c528526aa0) +--- + include/grub/mm_private.h | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h +index c2c4cb1511..203533cc3d 100644 +--- a/include/grub/mm_private.h ++++ b/include/grub/mm_private.h +@@ -21,15 +21,27 @@ + + #include + ++/* For context, see kern/mm.c */ ++ + /* Magic words. */ + #define GRUB_MM_FREE_MAGIC 0x2d3c2808 + #define GRUB_MM_ALLOC_MAGIC 0x6db08fa4 + ++/* A header describing a block of memory - either allocated or free */ + typedef struct grub_mm_header + { ++ /* ++ * The 'next' free block in this region's circular free list. ++ * Only meaningful if the block is free. ++ */ + struct grub_mm_header *next; ++ /* The block size, not in bytes but the number of cells of ++ * GRUB_MM_ALIGN bytes. Includes the header cell. ++ */ + grub_size_t size; ++ /* either free or alloc magic, depending on the block type. */ + grub_size_t magic; ++ /* pad to cell size: see the top of kern/mm.c. */ + #if GRUB_CPU_SIZEOF_VOID_P == 4 + char padding[4]; + #elif GRUB_CPU_SIZEOF_VOID_P == 8 +@@ -48,11 +60,27 @@ typedef struct grub_mm_header + + #define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2) + ++/* A region from which we can make allocations. */ + typedef struct grub_mm_region + { ++ /* The first free block in this region. */ + struct grub_mm_header *first; ++ ++ /* ++ * The next region in the linked list of regions. Regions are initially ++ * sorted in order of increasing size, but can grow, in which case the ++ * ordering may not be preserved. ++ */ + struct grub_mm_region *next; ++ ++ /* ++ * A grub_mm_region will always be aligned to cell size. The pre-size is ++ * the number of bytes we were given but had to skip in order to get that ++ * alignment. ++ */ + grub_size_t pre_size; ++ ++ /* How many bytes are in this region? (free and allocated) */ + grub_size_t size; + } + *grub_mm_region_t; diff --git a/SOURCES/0298-font-Fix-integer-overflow-in-ensure_comb_space.patch b/SOURCES/0298-font-Fix-integer-overflow-in-ensure_comb_space.patch deleted file mode 100644 index af5eedb..0000000 --- a/SOURCES/0298-font-Fix-integer-overflow-in-ensure_comb_space.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 5 Aug 2022 02:27:05 +0800 -Subject: [PATCH] font: Fix integer overflow in ensure_comb_space() - -In fact it can't overflow at all because glyph_id->ncomb is only 8-bit -wide. But let's keep safe if somebody changes the width of glyph_id->ncomb -in the future. This patch also fixes the inconsistency between -render_max_comb_glyphs and render_combining_glyphs when grub_malloc() -returns NULL. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit b2740b7e4a03bb8331d48b54b119afea76bb9d5f) -(cherry picked from commit f66ea1e60c347408e92b6695d5105c7e0f24d568) ---- - grub-core/font/font.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index a115a63b0c..d0e6340404 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1468,14 +1468,18 @@ ensure_comb_space (const struct grub_unicode_glyph *glyph_id) - if (glyph_id->ncomb <= render_max_comb_glyphs) - return; - -- render_max_comb_glyphs = 2 * glyph_id->ncomb; -- if (render_max_comb_glyphs < 8) -+ if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs)) -+ render_max_comb_glyphs = 0; -+ if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8) - render_max_comb_glyphs = 8; - grub_free (render_combining_glyphs); -- render_combining_glyphs = grub_malloc (render_max_comb_glyphs -- * sizeof (render_combining_glyphs[0])); -+ render_combining_glyphs = (render_max_comb_glyphs > 0) ? -+ grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL; - if (!render_combining_glyphs) -- grub_errno = 0; -+ { -+ render_max_comb_glyphs = 0; -+ grub_errno = GRUB_ERR_NONE; -+ } - } - - int diff --git a/SOURCES/0298-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch b/SOURCES/0298-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch new file mode 100644 index 0000000..2893784 --- /dev/null +++ b/SOURCES/0298-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 21 Apr 2022 15:24:14 +1000 +Subject: [PATCH] mm: Assert that we preserve header vs region alignment + +grub_mm_region_init() does: + + h = (grub_mm_header_t) (r + 1); + +where h is a grub_mm_header_t and r is a grub_mm_region_t. + +Cells are supposed to be GRUB_MM_ALIGN aligned, but while grub_mm_dump +ensures this vs the region header, grub_mm_region_init() does not. + +It's better to be explicit than implicit here: rather than changing +grub_mm_region_init() to ALIGN_UP(), require that the struct is +explicitly a multiple of the header size. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 1df8fe66c57087eb33bd6dc69f786ed124615aa7) +--- + include/grub/mm_private.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h +index 203533cc3d..a688b92a83 100644 +--- a/include/grub/mm_private.h ++++ b/include/grub/mm_private.h +@@ -20,6 +20,7 @@ + #define GRUB_MM_PRIVATE_H 1 + + #include ++#include + + /* For context, see kern/mm.c */ + +@@ -89,4 +90,17 @@ typedef struct grub_mm_region + extern grub_mm_region_t EXPORT_VAR (grub_mm_base); + #endif + ++static inline void ++grub_mm_size_sanity_check (void) { ++ /* Ensure we preserve alignment when doing h = (grub_mm_header_t) (r + 1). */ ++ COMPILE_TIME_ASSERT ((sizeof (struct grub_mm_region) % ++ sizeof (struct grub_mm_header)) == 0); ++ ++ /* ++ * GRUB_MM_ALIGN is supposed to represent cell size, and a mm_header is ++ * supposed to be 1 cell. ++ */ ++ COMPILE_TIME_ASSERT (sizeof (struct grub_mm_header) == GRUB_MM_ALIGN); ++} ++ + #endif diff --git a/SOURCES/0299-font-Fix-integer-overflow-in-BMP-index.patch b/SOURCES/0299-font-Fix-integer-overflow-in-BMP-index.patch deleted file mode 100644 index bb22749..0000000 --- a/SOURCES/0299-font-Fix-integer-overflow-in-BMP-index.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Mon, 15 Aug 2022 02:04:58 +0800 -Subject: [PATCH] font: Fix integer overflow in BMP index - -The BMP index (font->bmp_idx) is designed as a reverse lookup table of -char entries (font->char_index), in order to speed up lookups for BMP -chars (i.e. code < 0x10000). The values in BMP index are the subscripts -of the corresponding char entries, stored in grub_uint16_t, while 0xffff -means not found. - -This patch fixes the problem of large subscript truncated to grub_uint16_t, -leading BMP index to return wrong char entry or report false miss. The -code now checks for bounds and uses BMP index as a hint, and fallbacks -to binary-search if necessary. - -On the occasion add a comment about BMP index is initialized to 0xffff. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit afda8b60ba0712abe01ae1e64c5f7a067a0e6492) -(cherry picked from commit 6d90568929e11739b56f09ebbce9185ca9c23519) ---- - grub-core/font/font.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index d0e6340404..b208a28717 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -300,6 +300,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct - font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); - if (!font->bmp_idx) - return 1; -+ -+ /* Init the BMP index array to 0xffff. */ - grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t)); - - -@@ -328,7 +330,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct - return 1; - } - -- if (entry->code < 0x10000) -+ if (entry->code < 0x10000 && i < 0xffff) - font->bmp_idx[entry->code] = i; - - last_code = entry->code; -@@ -696,9 +698,12 @@ find_glyph (const grub_font_t font, grub_uint32_t code) - /* Use BMP index if possible. */ - if (code < 0x10000 && font->bmp_idx) - { -- if (font->bmp_idx[code] == 0xffff) -- return 0; -- return &table[font->bmp_idx[code]]; -+ if (font->bmp_idx[code] < 0xffff) -+ return &table[font->bmp_idx[code]]; -+ /* -+ * When we are here then lookup in BMP index result in miss, -+ * fallthough to binary-search. -+ */ - } - - /* Do a binary search in `char_index', which is ordered by code point. */ diff --git a/SOURCES/0299-mm-When-adding-a-region-merge-with-region-after-as-w.patch b/SOURCES/0299-mm-When-adding-a-region-merge-with-region-after-as-w.patch new file mode 100644 index 0000000..52cfeee --- /dev/null +++ b/SOURCES/0299-mm-When-adding-a-region-merge-with-region-after-as-w.patch @@ -0,0 +1,203 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 21 Apr 2022 15:24:15 +1000 +Subject: [PATCH] mm: When adding a region, merge with region after as well as + before + +On x86_64-efi (at least) regions seem to be added from top down. The mm +code will merge a new region with an existing region that comes +immediately before the new region. This allows larger allocations to be +satisfied that would otherwise be the case. + +On powerpc-ieee1275, however, regions are added from bottom up. So if +we add 3x 32MB regions, we can still only satisfy a 32MB allocation, +rather than the 96MB allocation we might otherwise be able to satisfy. + + * Define 'post_size' as being bytes lost to the end of an allocation + due to being given weird sizes from firmware that are not multiples + of GRUB_MM_ALIGN. + + * Allow merging of regions immediately _after_ existing regions, not + just before. As with the other approach, we create an allocated + block to represent the new space and the pass it to grub_free() to + get the metadata right. + +Signed-off-by: Daniel Axtens +Tested-by: Stefan Berger +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 052e6068be622ff53f1238b449c300dbd0a8abcd) +--- + grub-core/kern/mm.c | 128 +++++++++++++++++++++++++++++----------------- + include/grub/mm_private.h | 9 ++++ + 2 files changed, 91 insertions(+), 46 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 1cbf98c7ab..7be33e23bf 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -130,53 +130,88 @@ grub_mm_init_region (void *addr, grub_size_t size) + + /* Attempt to merge this region with every existing region */ + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) +- /* +- * Is the new region immediately below an existing region? That +- * is, is the address of the memory we're adding now (addr) + size +- * of the memory we're adding (size) + the bytes we couldn't use +- * at the start of the region we're considering (q->pre_size) +- * equal to the address of q? In other words, does the memory +- * looks like this? +- * +- * addr q +- * |----size-----|-q->pre_size-|| +- */ +- if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) +- { +- /* +- * Yes, we can merge the memory starting at addr into the +- * existing region from below. Align up addr to GRUB_MM_ALIGN +- * so that our new region has proper alignment. +- */ +- r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); +- /* Copy the region data across */ +- *r = *q; +- /* Consider all the new size as pre-size */ +- r->pre_size += size; ++ { ++ /* ++ * Is the new region immediately below an existing region? That ++ * is, is the address of the memory we're adding now (addr) + size ++ * of the memory we're adding (size) + the bytes we couldn't use ++ * at the start of the region we're considering (q->pre_size) ++ * equal to the address of q? In other words, does the memory ++ * looks like this? ++ * ++ * addr q ++ * |----size-----|-q->pre_size-|| ++ */ ++ if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) ++ { ++ /* ++ * Yes, we can merge the memory starting at addr into the ++ * existing region from below. Align up addr to GRUB_MM_ALIGN ++ * so that our new region has proper alignment. ++ */ ++ r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); ++ /* Copy the region data across */ ++ *r = *q; ++ /* Consider all the new size as pre-size */ ++ r->pre_size += size; + +- /* +- * If we have enough pre-size to create a block, create a +- * block with it. Mark it as allocated and pass it to +- * grub_free (), which will sort out getting it into the free +- * list. +- */ +- if (r->pre_size >> GRUB_MM_ALIGN_LOG2) +- { +- h = (grub_mm_header_t) (r + 1); +- /* block size is pre-size converted to cells */ +- h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); +- h->magic = GRUB_MM_ALLOC_MAGIC; +- /* region size grows by block size converted back to bytes */ +- r->size += h->size << GRUB_MM_ALIGN_LOG2; +- /* adjust pre_size to be accurate */ +- r->pre_size &= (GRUB_MM_ALIGN - 1); +- *p = r; +- grub_free (h + 1); +- } +- /* Replace the old region with the new region */ +- *p = r; +- return; +- } ++ /* ++ * If we have enough pre-size to create a block, create a ++ * block with it. Mark it as allocated and pass it to ++ * grub_free (), which will sort out getting it into the free ++ * list. ++ */ ++ if (r->pre_size >> GRUB_MM_ALIGN_LOG2) ++ { ++ h = (grub_mm_header_t) (r + 1); ++ /* block size is pre-size converted to cells */ ++ h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); ++ h->magic = GRUB_MM_ALLOC_MAGIC; ++ /* region size grows by block size converted back to bytes */ ++ r->size += h->size << GRUB_MM_ALIGN_LOG2; ++ /* adjust pre_size to be accurate */ ++ r->pre_size &= (GRUB_MM_ALIGN - 1); ++ *p = r; ++ grub_free (h + 1); ++ } ++ /* Replace the old region with the new region */ ++ *p = r; ++ return; ++ } ++ ++ /* ++ * Is the new region immediately above an existing region? That ++ * is: ++ * q addr ++ * ||-q->post_size-|----size-----| ++ */ ++ if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size == ++ (grub_uint8_t *) addr) ++ { ++ /* ++ * Yes! Follow a similar pattern to above, but simpler. ++ * Our header starts at address - post_size, which should align us ++ * to a cell boundary. ++ * ++ * Cast to (void *) first to avoid the following build error: ++ * kern/mm.c: In function ‘grub_mm_init_region’: ++ * kern/mm.c:211:15: error: cast increases required alignment of target type [-Werror=cast-align] ++ * 211 | h = (grub_mm_header_t) ((grub_uint8_t *) addr - q->post_size); ++ * | ^ ++ * It is safe to do that because proper alignment is enforced in grub_mm_size_sanity_check(). ++ */ ++ h = (grub_mm_header_t)(void *) ((grub_uint8_t *) addr - q->post_size); ++ /* our size is the allocated size plus post_size, in cells */ ++ h->size = (size + q->post_size) >> GRUB_MM_ALIGN_LOG2; ++ h->magic = GRUB_MM_ALLOC_MAGIC; ++ /* region size grows by block size converted back to bytes */ ++ q->size += h->size << GRUB_MM_ALIGN_LOG2; ++ /* adjust new post_size to be accurate */ ++ q->post_size = (q->post_size + size) & (GRUB_MM_ALIGN - 1); ++ grub_free (h + 1); ++ return; ++ } ++ } + + /* Allocate a region from the head. */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); +@@ -195,6 +230,7 @@ grub_mm_init_region (void *addr, grub_size_t size) + r->first = h; + r->pre_size = (grub_addr_t) r - (grub_addr_t) addr; + r->size = (h->size << GRUB_MM_ALIGN_LOG2); ++ r->post_size = size - r->size; + + /* Find where to insert this region. Put a smaller one before bigger ones, + to prevent fragmentation. */ +diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h +index a688b92a83..96c2d816be 100644 +--- a/include/grub/mm_private.h ++++ b/include/grub/mm_private.h +@@ -81,8 +81,17 @@ typedef struct grub_mm_region + */ + grub_size_t pre_size; + ++ /* ++ * Likewise, the post-size is the number of bytes we wasted at the end ++ * of the allocation because it wasn't a multiple of GRUB_MM_ALIGN ++ */ ++ grub_size_t post_size; ++ + /* How many bytes are in this region? (free and allocated) */ + grub_size_t size; ++ ++ /* pad to a multiple of cell size */ ++ char padding[3 * GRUB_CPU_SIZEOF_VOID_P]; + } + *grub_mm_region_t; + diff --git a/SOURCES/0300-font-Fix-integer-underflow-in-binary-search-of-char-.patch b/SOURCES/0300-font-Fix-integer-underflow-in-binary-search-of-char-.patch deleted file mode 100644 index 5c25e09..0000000 --- a/SOURCES/0300-font-Fix-integer-underflow-in-binary-search-of-char-.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Sun, 14 Aug 2022 18:09:38 +0800 -Subject: [PATCH] font: Fix integer underflow in binary search of char index - -If search target is less than all entries in font->index then "hi" -variable is set to -1, which translates to SIZE_MAX and leads to errors. - -This patch fixes the problem by replacing the entire binary search code -with the libstdc++'s std::lower_bound() implementation. - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit c140a086838e7c9af87842036f891b8393a8c4bc) -(cherry picked from commit e110997335b1744464ea232d57a7d86e16ca8dee) ---- - grub-core/font/font.c | 40 ++++++++++++++++++++++------------------ - 1 file changed, 22 insertions(+), 18 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index b208a28717..193dfec045 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -688,12 +688,12 @@ read_be_int16 (grub_file_t file, grub_int16_t * value) - static inline struct char_index_entry * - find_glyph (const grub_font_t font, grub_uint32_t code) - { -- struct char_index_entry *table; -- grub_size_t lo; -- grub_size_t hi; -- grub_size_t mid; -+ struct char_index_entry *table, *first, *end; -+ grub_size_t len; - - table = font->char_index; -+ if (table == NULL) -+ return NULL; - - /* Use BMP index if possible. */ - if (code < 0x10000 && font->bmp_idx) -@@ -706,25 +706,29 @@ find_glyph (const grub_font_t font, grub_uint32_t code) - */ - } - -- /* Do a binary search in `char_index', which is ordered by code point. */ -- lo = 0; -- hi = font->num_chars - 1; -+ /* -+ * Do a binary search in char_index which is ordered by code point. -+ * The code below is the same as libstdc++'s std::lower_bound(). -+ */ -+ first = table; -+ len = font->num_chars; -+ end = first + len; - -- if (!table) -- return 0; -- -- while (lo <= hi) -+ while (len > 0) - { -- mid = lo + (hi - lo) / 2; -- if (code < table[mid].code) -- hi = mid - 1; -- else if (code > table[mid].code) -- lo = mid + 1; -+ grub_size_t half = len >> 1; -+ struct char_index_entry *middle = first + half; -+ -+ if (middle->code < code) -+ { -+ first = middle + 1; -+ len = len - half - 1; -+ } - else -- return &table[mid]; -+ len = half; - } - -- return 0; -+ return (first < end && first->code == code) ? first : NULL; - } - - /* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded diff --git a/SOURCES/0300-mm-Debug-support-for-region-operations.patch b/SOURCES/0300-mm-Debug-support-for-region-operations.patch new file mode 100644 index 0000000..f434260 --- /dev/null +++ b/SOURCES/0300-mm-Debug-support-for-region-operations.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Thu, 21 Apr 2022 15:24:16 +1000 +Subject: [PATCH] mm: Debug support for region operations + +This is handy for debugging. Enable with "set debug=regions". + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 8afa5ef45b797ba5d8147ceee85ac2c59dcc7f09) +--- + grub-core/kern/mm.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 7be33e23bf..38bfb01df9 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -115,9 +115,8 @@ grub_mm_init_region (void *addr, grub_size_t size) + grub_mm_header_t h; + grub_mm_region_t r, *p, q; + +-#if 0 +- grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size); +-#endif ++ grub_dprintf ("regions", "Using memory for heap: start=%p, end=%p\n", ++ addr, (char *) addr + (unsigned int) size); + + /* Exclude last 4K to avoid overflows. */ + /* If addr + 0x1000 overflows then whole region is in excluded zone. */ +@@ -142,8 +141,14 @@ grub_mm_init_region (void *addr, grub_size_t size) + * addr q + * |----size-----|-q->pre_size-|| + */ ++ grub_dprintf ("regions", "Can we extend into region above?" ++ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", ++ (grub_uint8_t *) addr, size, q->pre_size, (grub_uint8_t *) q); + if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) + { ++ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", ++ q, (grub_uint8_t *) q + sizeof (*q) + q->size, ++ addr, (grub_uint8_t *) q + sizeof (*q) + q->size); + /* + * Yes, we can merge the memory starting at addr into the + * existing region from below. Align up addr to GRUB_MM_ALIGN +@@ -185,9 +190,15 @@ grub_mm_init_region (void *addr, grub_size_t size) + * q addr + * ||-q->post_size-|----size-----| + */ ++ grub_dprintf ("regions", "Can we extend into region below?" ++ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", ++ (grub_uint8_t *) q, sizeof(*q), q->size, q->post_size, (grub_uint8_t *) addr); + if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size == + (grub_uint8_t *) addr) + { ++ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", ++ q, (grub_uint8_t *) q + sizeof (*q) + q->size, ++ q, (grub_uint8_t *) addr + size); + /* + * Yes! Follow a similar pattern to above, but simpler. + * Our header starts at address - post_size, which should align us +@@ -213,6 +224,8 @@ grub_mm_init_region (void *addr, grub_size_t size) + } + } + ++ grub_dprintf ("regions", "No: considering a new region at %p of size %" PRIxGRUB_SIZE "\n", ++ addr, size); + /* Allocate a region from the head. */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); + diff --git a/SOURCES/0301-kern-efi-sb-Enforce-verification-of-font-files.patch b/SOURCES/0301-kern-efi-sb-Enforce-verification-of-font-files.patch deleted file mode 100644 index 42fea35..0000000 --- a/SOURCES/0301-kern-efi-sb-Enforce-verification-of-font-files.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Sun, 14 Aug 2022 15:51:54 +0800 -Subject: [PATCH] kern/efi/sb: Enforce verification of font files - -As a mitigation and hardening measure enforce verification of font -files. Then only trusted font files can be load. This will reduce the -attack surface at cost of losing the ability of end-users to customize -fonts if e.g. UEFI Secure Boot is enabled. Vendors can always customize -fonts because they have ability to pack fonts into their GRUB bundles. - -This goal is achieved by: - - * Removing GRUB_FILE_TYPE_FONT from shim lock verifier's - skip-verification list. - - * Adding GRUB_FILE_TYPE_FONT to lockdown verifier's defer-auth list, - so font files must be verified by a verifier before they can be loaded. - -Suggested-by: Daniel Kiper -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 630deb8c0d8b02b670ced4b7030414bcf17aa080) -(cherry picked from commit 37257e0ee45b9029b62f4046c983481d063b821d) ---- - grub-core/kern/efi/sb.c | 1 - - grub-core/kern/lockdown.c | 1 + - 2 files changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c -index 89c4bb3fd1..db42c2539f 100644 ---- a/grub-core/kern/efi/sb.c -+++ b/grub-core/kern/efi/sb.c -@@ -145,7 +145,6 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), - case GRUB_FILE_TYPE_PRINT_BLOCKLIST: - case GRUB_FILE_TYPE_TESTLOAD: - case GRUB_FILE_TYPE_GET_SIZE: -- case GRUB_FILE_TYPE_FONT: - case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: - case GRUB_FILE_TYPE_CAT: - case GRUB_FILE_TYPE_HEXCAT: -diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c -index 0bc70fd42d..af6d493cd3 100644 ---- a/grub-core/kern/lockdown.c -+++ b/grub-core/kern/lockdown.c -@@ -51,6 +51,7 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)), - case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: - case GRUB_FILE_TYPE_ACPI_TABLE: - case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: -+ case GRUB_FILE_TYPE_FONT: - *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; - - /* Fall through. */ diff --git a/SOURCES/0301-mm-Drop-unused-unloading-of-modules-on-OOM.patch b/SOURCES/0301-mm-Drop-unused-unloading-of-modules-on-OOM.patch new file mode 100644 index 0000000..a18d912 --- /dev/null +++ b/SOURCES/0301-mm-Drop-unused-unloading-of-modules-on-OOM.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:17 +1000 +Subject: [PATCH] mm: Drop unused unloading of modules on OOM + +In grub_memalign(), there's a commented section which would allow for +unloading of unneeded modules in case where there is not enough free +memory available to satisfy a request. Given that this code is never +compiled in, let's remove it together with grub_dl_unload_unneeded(). + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 139fd9b134a01e0b5fe0ebefafa7f48d1ffb6d60) +--- + grub-core/kern/dl.c | 20 -------------------- + grub-core/kern/mm.c | 8 -------- + include/grub/dl.h | 1 - + 3 files changed, 29 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index d5de80186f..ab9101a5ad 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -998,23 +998,3 @@ grub_dl_unload (grub_dl_t mod) + grub_free (mod); + return 1; + } +- +-/* Unload unneeded modules. */ +-void +-grub_dl_unload_unneeded (void) +-{ +- /* Because grub_dl_remove modifies the list of modules, this +- implementation is tricky. */ +- grub_dl_t p = grub_dl_head; +- +- while (p) +- { +- if (grub_dl_unload (p)) +- { +- p = grub_dl_head; +- continue; +- } +- +- p = p->next; +- } +-} +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 38bfb01df9..1825dc8289 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -444,14 +444,6 @@ grub_memalign (grub_size_t align, grub_size_t size) + count++; + goto again; + +-#if 0 +- case 1: +- /* Unload unneeded modules. */ +- grub_dl_unload_unneeded (); +- count++; +- goto again; +-#endif +- + default: + break; + } +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 45ac8e339f..6bc2560bf0 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -206,7 +206,6 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name); + grub_dl_t grub_dl_load_core (void *addr, grub_size_t size); + grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size); + int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod); +-extern void grub_dl_unload_unneeded (void); + extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod); + extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); + extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod); diff --git a/SOURCES/0302-fbutil-Fix-integer-overflow.patch b/SOURCES/0302-fbutil-Fix-integer-overflow.patch deleted file mode 100644 index f8e82e5..0000000 --- a/SOURCES/0302-fbutil-Fix-integer-overflow.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Tue, 6 Sep 2022 03:03:21 +0800 -Subject: [PATCH] fbutil: Fix integer overflow - -Expressions like u64 = u32 * u32 are unsafe because their products are -truncated to u32 even if left hand side is u64. This patch fixes all -problems like that one in fbutil. - -To get right result not only left hand side have to be u64 but it's also -necessary to cast at least one of the operands of all leaf operators of -right hand side to u64, e.g. u64 = u32 * u32 + u32 * u32 should be -u64 = (u64)u32 * u32 + (u64)u32 * u32. - -For 1-bit bitmaps grub_uint64_t have to be used. It's safe because any -combination of values in (grub_uint64_t)u32 * u32 + u32 expression will -not overflow grub_uint64_t. - -Other expressions like ptr + u32 * u32 + u32 * u32 are also vulnerable. -They should be ptr + (grub_addr_t)u32 * u32 + (grub_addr_t)u32 * u32. - -This patch also adds a comment to grub_video_fb_get_video_ptr() which -says it's arguments must be valid and no sanity check is performed -(like its siblings in grub-core/video/fb/fbutil.c). - -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 50a11a81bc842c58962244a2dc86bbd31a426e12) -(cherry picked from commit 8fa75d647362c938c4cc302cf5945b31fb92c078) ---- - grub-core/video/fb/fbutil.c | 4 ++-- - include/grub/fbutil.h | 13 +++++++++---- - 2 files changed, 11 insertions(+), 6 deletions(-) - -diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c -index b98bb51fe8..25ef39f47d 100644 ---- a/grub-core/video/fb/fbutil.c -+++ b/grub-core/video/fb/fbutil.c -@@ -67,7 +67,7 @@ get_pixel (struct grub_video_fbblit_info *source, - case 1: - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) - { -- int bit_index = y * source->mode_info->width + x; -+ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; - grub_uint8_t *ptr = source->data + bit_index / 8; - int bit_pos = 7 - bit_index % 8; - color = (*ptr >> bit_pos) & 0x01; -@@ -138,7 +138,7 @@ set_pixel (struct grub_video_fbblit_info *source, - case 1: - if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED) - { -- int bit_index = y * source->mode_info->width + x; -+ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x; - grub_uint8_t *ptr = source->data + bit_index / 8; - int bit_pos = 7 - bit_index % 8; - *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos); -diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h -index 4205eb917f..78a1ab3b45 100644 ---- a/include/grub/fbutil.h -+++ b/include/grub/fbutil.h -@@ -31,14 +31,19 @@ struct grub_video_fbblit_info - grub_uint8_t *data; - }; - --/* Don't use for 1-bit bitmaps, addressing needs to be done at the bit level -- and it doesn't make sense, in general, to ask for a pointer -- to a particular pixel's data. */ -+/* -+ * Don't use for 1-bit bitmaps, addressing needs to be done at the bit level -+ * and it doesn't make sense, in general, to ask for a pointer -+ * to a particular pixel's data. -+ * -+ * This function assumes that bounds checking has been done in previous phase -+ * and they are opted out in here. -+ */ - static inline void * - grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, - unsigned int x, unsigned int y) - { -- return source->data + y * source->mode_info->pitch + x * source->mode_info->bytes_per_pixel; -+ return source->data + (grub_addr_t) y * source->mode_info->pitch + (grub_addr_t) x * source->mode_info->bytes_per_pixel; - } - - /* Advance pointer by VAL bytes. If there is no unaligned access available, diff --git a/SOURCES/0302-mm-Allow-dynamically-requesting-additional-memory-re.patch b/SOURCES/0302-mm-Allow-dynamically-requesting-additional-memory-re.patch new file mode 100644 index 0000000..d225c10 --- /dev/null +++ b/SOURCES/0302-mm-Allow-dynamically-requesting-additional-memory-re.patch @@ -0,0 +1,130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:18 +1000 +Subject: [PATCH] mm: Allow dynamically requesting additional memory regions + +Currently, all platforms will set up their heap on initialization of the +platform code. While this works mostly fine, it poses some limitations +on memory management on us. Most notably, allocating big chunks of +memory in the gigabyte range would require us to pre-request this many +bytes from the firmware and add it to the heap from the beginning on +some platforms like EFI. As this isn't needed for most configurations, +it is inefficient and may even negatively impact some usecases when, +e.g., chainloading. Nonetheless, allocating big chunks of memory is +required sometimes, where one example is the upcoming support for the +Argon2 key derival function in LUKS2. + +In order to avoid pre-allocating big chunks of memory, this commit +implements a runtime mechanism to add more pages to the system. When +a given allocation cannot be currently satisfied, we'll call a given +callback set up by the platform's own memory management subsystem, +asking it to add a memory area with at least "n" bytes. If this +succeeds, we retry searching for a valid memory region, which should +now succeed. + +If this fails, we try asking for "n" bytes, possibly spread across +multiple regions, in hopes that region merging means that we end up +with enough memory for things to work out. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Tested-by: Stefan Berger +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 887f98f0db43e33fba4ec1f85e42fae1185700bc) +--- + grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++ + include/grub/mm.h | 18 ++++++++++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 1825dc8289..f2e27f263b 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -28,6 +28,9 @@ + - multiple regions may be used as free space. They may not be + contiguous. + ++ - if existing regions are insufficient to satisfy an allocation, a new ++ region can be requested from firmware. ++ + Regions are managed by a singly linked list, and the meta information is + stored in the beginning of each region. Space after the meta information + is used to allocate memory. +@@ -81,6 +84,7 @@ + + + grub_mm_region_t grub_mm_base; ++grub_mm_add_region_func_t grub_mm_add_region_fn; + + /* Get a header from the pointer PTR, and set *P and *R to a pointer + to the header and a pointer to its region, respectively. PTR must +@@ -444,6 +448,32 @@ grub_memalign (grub_size_t align, grub_size_t size) + count++; + goto again; + ++ case 1: ++ /* Request additional pages, contiguous */ ++ count++; ++ ++ if (grub_mm_add_region_fn != NULL && ++ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) ++ goto again; ++ ++ /* fallthrough */ ++ ++ case 2: ++ /* Request additional pages, anything at all */ ++ count++; ++ ++ if (grub_mm_add_region_fn != NULL) ++ { ++ /* ++ * Try again even if this fails, in case it was able to partially ++ * satisfy the request ++ */ ++ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE); ++ goto again; ++ } ++ ++ /* fallthrough */ ++ + default: + break; + } +diff --git a/include/grub/mm.h b/include/grub/mm.h +index d81623d226..7c6f925ffd 100644 +--- a/include/grub/mm.h ++++ b/include/grub/mm.h +@@ -20,6 +20,7 @@ + #ifndef GRUB_MM_H + #define GRUB_MM_H 1 + ++#include + #include + #include + #include +@@ -29,6 +30,23 @@ + # define NULL ((void *) 0) + #endif + ++#define GRUB_MM_ADD_REGION_NONE 0 ++#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0) ++ ++/* ++ * Function used to request memory regions of `grub_size_t` bytes. The second ++ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags. ++ */ ++typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int); ++ ++/* ++ * Set this function pointer to enable adding memory-regions at runtime in case ++ * a memory allocation cannot be satisfied with existing regions. ++ */ ++#ifndef GRUB_MACHINE_EMU ++extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn); ++#endif ++ + void grub_mm_init_region (void *addr, grub_size_t size); + void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size); + void *EXPORT_FUNC(grub_malloc) (grub_size_t size); diff --git a/SOURCES/0303-font-Fix-an-integer-underflow-in-blit_comb.patch b/SOURCES/0303-font-Fix-an-integer-underflow-in-blit_comb.patch deleted file mode 100644 index b8a0e9e..0000000 --- a/SOURCES/0303-font-Fix-an-integer-underflow-in-blit_comb.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Mon, 24 Oct 2022 08:05:35 +0800 -Subject: [PATCH] font: Fix an integer underflow in blit_comb() - -The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may -evaluate to a very big invalid value even if both ctx.bounds.height and -combining_glyphs[i]->height are small integers. For example, if -ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this -expression evaluates to 2147483647 (expected -1). This is because -coordinates are allowed to be negative but ctx.bounds.height is an -unsigned int. So, the subtraction operates on unsigned ints and -underflows to a very big value. The division makes things even worse. -The quotient is still an invalid value even if converted back to int. - -This patch fixes the problem by casting ctx.bounds.height to int. As -a result the subtraction will operate on int and grub_uint16_t which -will be promoted to an int. So, the underflow will no longer happen. Other -uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, -to ensure coordinates are always calculated on signed integers. - -Fixes: CVE-2022-3775 - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit 6d2668dea3774ed74c4cd1eadd146f1b846bc3d4) -(cherry picked from commit 05e532fb707bbf79aa4e1efbde4d208d7da89d6b) ---- - grub-core/font/font.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 193dfec045..12a5f0d08c 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - ctx.bounds.height = main_glyph->height; - - above_rightx = main_glyph->offset_x + main_glyph->width; -- above_righty = ctx.bounds.y + ctx.bounds.height; -+ above_righty = ctx.bounds.y + (int) ctx.bounds.height; - - above_leftx = main_glyph->offset_x; -- above_lefty = ctx.bounds.y + ctx.bounds.height; -+ above_lefty = ctx.bounds.y + (int) ctx.bounds.height; - -- below_rightx = ctx.bounds.x + ctx.bounds.width; -+ below_rightx = ctx.bounds.x + (int) ctx.bounds.width; - below_righty = ctx.bounds.y; - - comb = grub_unicode_get_comb (glyph_id); -@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - - if (!combining_glyphs[i]) - continue; -- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; -+ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; - /* CGJ is to avoid diacritics reordering. */ - if (comb[i].code - == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) -@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - case GRUB_UNICODE_COMB_OVERLAY: - do_blit (combining_glyphs[i], - targetx, -- (ctx.bounds.height - combining_glyphs[i]->height) / 2 -- - (ctx.bounds.height + ctx.bounds.y), &ctx); -+ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 -+ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); - if (min_devwidth < combining_glyphs[i]->width) - min_devwidth = combining_glyphs[i]->width; - break; -@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - /* Fallthrough. */ - case GRUB_UNICODE_STACK_ATTACHED_ABOVE: - do_blit (combining_glyphs[i], targetx, -- -(ctx.bounds.height + ctx.bounds.y + space -+ -((int) ctx.bounds.height + ctx.bounds.y + space - + combining_glyphs[i]->height), &ctx); - if (min_devwidth < combining_glyphs[i]->width) - min_devwidth = combining_glyphs[i]->width; -@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - - case GRUB_UNICODE_COMB_HEBREW_DAGESH: - do_blit (combining_glyphs[i], targetx, -- -(ctx.bounds.height / 2 + ctx.bounds.y -+ -((int) ctx.bounds.height / 2 + ctx.bounds.y - + combining_glyphs[i]->height / 2), &ctx); - if (min_devwidth < combining_glyphs[i]->width) - min_devwidth = combining_glyphs[i]->width; diff --git a/SOURCES/0303-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch b/SOURCES/0303-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch new file mode 100644 index 0000000..6fa378c --- /dev/null +++ b/SOURCES/0303-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:19 +1000 +Subject: [PATCH] kern/efi/mm: Always request a fixed number of pages on init + +When initializing the EFI memory subsystem, we will by default request +a quarter of the available memory, bounded by a minimum/maximum value. +Given that we're about to extend the EFI memory system to dynamically +request additional pages from the firmware as required, this scaling of +requested memory based on available memory will not make a lot of sense +anymore. + +Remove this logic as a preparatory patch such that we'll instead defer +to the runtime memory allocator. Note that ideally, we'd want to change +this after dynamic requesting of pages has been implemented for the EFI +platform. But because we'll need to split up initialization of the +memory subsystem and the request of pages from the firmware, we'd have +to duplicate quite some logic at first only to remove it afterwards +again. This seems quite pointless, so we instead have patches slightly +out of order. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 938c3760b8c0fca759140be48307179b50107ff6) +--- + grub-core/kern/efi/mm.c | 35 +++-------------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index e460b072e6..782a1365a1 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -38,9 +38,8 @@ + a multiplier of 4KB. */ + #define MEMORY_MAP_SIZE 0x3000 + +-/* The minimum and maximum heap size for GRUB itself. */ +-#define MIN_HEAP_SIZE 0x100000 +-#define MAX_HEAP_SIZE (1600 * 0x100000) ++/* The default heap size for GRUB itself in bytes. */ ++#define DEFAULT_HEAP_SIZE 0x100000 + + static void *finish_mmap_buf = 0; + static grub_efi_uintn_t finish_mmap_size = 0; +@@ -514,23 +513,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + return filtered_desc; + } + +-/* Return the total number of pages. */ +-static grub_efi_uint64_t +-get_total_pages (grub_efi_memory_descriptor_t *memory_map, +- grub_efi_uintn_t desc_size, +- grub_efi_memory_descriptor_t *memory_map_end) +-{ +- grub_efi_memory_descriptor_t *desc; +- grub_efi_uint64_t total = 0; +- +- for (desc = memory_map; +- desc < memory_map_end; +- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) +- total += desc->num_pages; +- +- return total; +-} +- + /* Add memory regions. */ + static void + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, +@@ -694,8 +676,6 @@ grub_efi_mm_init (void) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; +- grub_efi_uint64_t total_pages; +- grub_efi_uint64_t required_pages; + int mm_status; + + grub_nx_init (); +@@ -737,22 +717,13 @@ grub_efi_mm_init (void) + filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, + desc_size, memory_map_end); + +- /* By default, request a quarter of the available memory. */ +- total_pages = get_total_pages (filtered_memory_map, desc_size, +- filtered_memory_map_end); +- required_pages = (total_pages >> 2); +- if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); +- else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE); +- + /* Sort the filtered descriptors, so that GRUB can allocate pages + from smaller regions. */ + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, required_pages); ++ filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); + + #if 0 + /* For debug. */ diff --git a/SOURCES/0304-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch b/SOURCES/0304-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch deleted file mode 100644 index 307572c..0000000 --- a/SOURCES/0304-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Mon, 24 Oct 2022 07:15:41 +0800 -Subject: [PATCH] font: Harden grub_font_blit_glyph() and - grub_font_blit_glyph_mirror() - -As a mitigation and hardening measure add sanity checks to -grub_font_blit_glyph() and grub_font_blit_glyph_mirror(). This patch -makes these two functions do nothing if target blitting area isn't fully -contained in target bitmap. Therefore, if complex calculations in caller -overflows and malicious coordinates are given, we are still safe because -any coordinates which result in out-of-bound-write are rejected. However, -this patch only checks for invalid coordinates, and doesn't provide any -protection against invalid source glyph or destination glyph, e.g. -mismatch between glyph size and buffer size. - -This hardening measure is designed to mitigate possible overflows in -blit_comb(). If overflow occurs, it may return invalid bounding box -during dry run and call grub_font_blit_glyph() with malicious -coordinates during actual blitting. However, we are still safe because -the scratch glyph itself is valid, although its size makes no sense, and -any invalid coordinates are rejected. - -It would be better to call grub_fatal() if illegal parameter is detected. -However, doing this may end up in a dangerous recursion because grub_fatal() -would print messages to the screen and we are in the progress of drawing -characters on the screen. - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit fcd7aa0c278f7cf3fb9f93f1a3966e1792339eb6) -(cherry picked from commit 1d37ec63a1c76a14fdf70f548eada92667b42ddb) ---- - grub-core/font/font.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 12a5f0d08c..29fbb94294 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -1069,8 +1069,15 @@ static void - grub_font_blit_glyph (struct grub_font_glyph *target, - struct grub_font_glyph *src, unsigned dx, unsigned dy) - { -+ grub_uint16_t max_x, max_y; - unsigned src_bit, tgt_bit, src_byte, tgt_byte; - unsigned i, j; -+ -+ /* Harden against out-of-bound writes. */ -+ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || -+ (grub_add (dy, src->height, &max_y) || max_y > target->height)) -+ return; -+ - for (i = 0; i < src->height; i++) - { - src_bit = (src->width * i) % 8; -@@ -1102,9 +1109,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target, - struct grub_font_glyph *src, - unsigned dx, unsigned dy) - { -+ grub_uint16_t max_x, max_y; - unsigned tgt_bit, src_byte, tgt_byte; - signed src_bit; - unsigned i, j; -+ -+ /* Harden against out-of-bound writes. */ -+ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || -+ (grub_add (dy, src->height, &max_y) || max_y > target->height)) -+ return; -+ - for (i = 0; i < src->height; i++) - { - src_bit = (src->width * i + src->width - 1) % 8; diff --git a/SOURCES/0304-kern-efi-mm-Extract-function-to-add-memory-regions.patch b/SOURCES/0304-kern-efi-mm-Extract-function-to-add-memory-regions.patch new file mode 100644 index 0000000..28cf2e7 --- /dev/null +++ b/SOURCES/0304-kern-efi-mm-Extract-function-to-add-memory-regions.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:20 +1000 +Subject: [PATCH] kern/efi/mm: Extract function to add memory regions + +In preparation of support for runtime-allocating additional memory +region, this patch extracts the function to retrieve the EFI memory +map and add a subset of it to GRUB's own memory regions. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 96a7ea29e3cb61b6c2302e260e8e6a6117e17fa3) +[rharwood: backport around our nx] +--- + grub-core/kern/efi/mm.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 782a1365a1..a1d3b51fe6 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -667,8 +667,8 @@ grub_nx_init (void) + } + } + +-void +-grub_efi_mm_init (void) ++static grub_err_t ++grub_efi_mm_add_regions (grub_size_t required_bytes) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -683,7 +683,7 @@ grub_efi_mm_init (void) + /* Prepare a memory region to store two memory maps. */ + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map"); + + /* Obtain descriptors for available memory. */ + map_size = MEMORY_MAP_SIZE; +@@ -701,14 +701,14 @@ grub_efi_mm_init (void) + + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map"); + + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, + &desc_size, 0); + } + + if (mm_status < 0) +- grub_fatal ("cannot get memory map"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI"); + + memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); + +@@ -723,7 +723,7 @@ grub_efi_mm_init (void) + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); ++ filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); + + #if 0 + /* For debug. */ +@@ -741,6 +741,15 @@ grub_efi_mm_init (void) + /* Release the memory maps. */ + grub_efi_free_pages ((grub_addr_t) memory_map, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); ++ ++ return GRUB_ERR_NONE; ++} ++ ++void ++grub_efi_mm_init (void) ++{ ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ grub_fatal ("%s", grub_errmsg); + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) diff --git a/SOURCES/0305-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch b/SOURCES/0305-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch deleted file mode 100644 index 368b9d0..0000000 --- a/SOURCES/0305-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 28 Oct 2022 17:29:16 +0800 -Subject: [PATCH] font: Assign null_font to glyphs in ascii_font_glyph[] - -The calculations in blit_comb() need information from glyph's font, e.g. -grub_font_get_xheight(main_glyph->font). However, main_glyph->font is -NULL if main_glyph comes from ascii_font_glyph[]. Therefore -grub_font_get_*() crashes because of NULL pointer. - -There is already a solution, the null_font. So, assign it to those glyphs -in ascii_font_glyph[]. - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit dd539d695482069d28b40f2d3821f710cdcf6ee6) -(cherry picked from commit 87526376857eaceae474c9797e3cee5b50597332) ---- - grub-core/font/font.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 29fbb94294..e6616e610c 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -137,7 +137,7 @@ ascii_glyph_lookup (grub_uint32_t code) - ascii_font_glyph[current]->offset_x = 0; - ascii_font_glyph[current]->offset_y = -2; - ascii_font_glyph[current]->device_width = 8; -- ascii_font_glyph[current]->font = NULL; -+ ascii_font_glyph[current]->font = &null_font; - - grub_memcpy (ascii_font_glyph[current]->bitmap, - &ascii_bitmaps[current * ASCII_BITMAP_SIZE], diff --git a/SOURCES/0305-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch b/SOURCES/0305-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch new file mode 100644 index 0000000..b4b7891 --- /dev/null +++ b/SOURCES/0305-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:21 +1000 +Subject: [PATCH] kern/efi/mm: Pass up errors from add_memory_regions() + +The function add_memory_regions() is currently only called on system +initialization to allocate a fixed amount of pages. As such, it didn't +need to return any errors: in case it failed, we cannot proceed anyway. +This will change with the upcoming support for requesting more memory +from the firmware at runtime, where it doesn't make sense anymore to +fail hard. + +Refactor the function to return an error to prepare for this. Note that +this does not change the behaviour when initializing the memory system +because grub_efi_mm_init() knows to call grub_fatal() in case +grub_efi_mm_add_regions() returns an error. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 15a015698921240adc1ac266a3b5bc5fcbd81521) +--- + grub-core/kern/efi/mm.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index a1d3b51fe6..e0ebc65dba 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -514,7 +514,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + + /* Add memory regions. */ +-static void ++static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +@@ -542,9 +542,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_CODE); + if (! addr) +- grub_fatal ("cannot allocate conventional memory %p with %u pages", +- (void *) ((grub_addr_t) start), +- (unsigned) pages); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Memory starting at %p (%u pages) marked as free, but EFI would not allocate", ++ (void *) ((grub_addr_t) start), (unsigned) pages); + + grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); + +@@ -554,7 +554,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + } + + if (required_pages > 0) +- grub_fatal ("too little memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map", ++ required_pages); ++ ++ return GRUB_ERR_NONE; + } + + void +@@ -676,6 +680,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; ++ grub_err_t err; + int mm_status; + + grub_nx_init (); +@@ -722,8 +727,11 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ +- add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); ++ err = add_memory_regions (filtered_memory_map, desc_size, ++ filtered_memory_map_end, ++ BYTES_TO_PAGES (required_bytes)); ++ if (err != GRUB_ERR_NONE) ++ return err; + + #if 0 + /* For debug. */ diff --git a/SOURCES/0306-kern-efi-mm-Implement-runtime-addition-of-pages.patch b/SOURCES/0306-kern-efi-mm-Implement-runtime-addition-of-pages.patch new file mode 100644 index 0000000..1f52581 --- /dev/null +++ b/SOURCES/0306-kern-efi-mm-Implement-runtime-addition-of-pages.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:22 +1000 +Subject: [PATCH] kern/efi/mm: Implement runtime addition of pages + +Adjust the interface of grub_efi_mm_add_regions() to take a set of +GRUB_MM_ADD_REGION_* flags, which most notably is currently only the +GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function +up as callback for the memory subsystem and have it call out to us in +case there's not enough pages available in the current heap. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +(cherry picked from commit 1df2934822df4c1170dde069d97cfbf7a9572bba) +--- + grub-core/kern/efi/mm.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index e0ebc65dba..016ba6cf2f 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -518,7 +518,8 @@ static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +- grub_efi_uint64_t required_pages) ++ grub_efi_uint64_t required_pages, ++ unsigned int flags) + { + grub_efi_memory_descriptor_t *desc; + +@@ -532,6 +533,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + + start = desc->physical_start; + pages = desc->num_pages; ++ ++ if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE)) ++ continue; ++ + if (pages > required_pages) + { + start += PAGES_TO_BYTES (pages - required_pages); +@@ -672,7 +677,7 @@ grub_nx_init (void) + } + + static grub_err_t +-grub_efi_mm_add_regions (grub_size_t required_bytes) ++grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -729,7 +734,8 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + /* Allocate memory regions for GRUB's memory management. */ + err = add_memory_regions (filtered_memory_map, desc_size, + filtered_memory_map_end, +- BYTES_TO_PAGES (required_bytes)); ++ BYTES_TO_PAGES (required_bytes), ++ flags); + if (err != GRUB_ERR_NONE) + return err; + +@@ -756,8 +762,9 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + void + grub_efi_mm_init (void) + { +- if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE) + grub_fatal ("%s", grub_errmsg); ++ grub_mm_add_region_fn = grub_efi_mm_add_regions; + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) diff --git a/SOURCES/0306-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch b/SOURCES/0306-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch deleted file mode 100644 index 96f2f94..0000000 --- a/SOURCES/0306-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zhang Boyang -Date: Fri, 28 Oct 2022 21:31:39 +0800 -Subject: [PATCH] normal/charset: Fix an integer overflow in - grub_unicode_aglomerate_comb() - -The out->ncomb is a bit-field of 8 bits. So, the max possible value is 255. -However, code in grub_unicode_aglomerate_comb() doesn't check for an -overflow when incrementing out->ncomb. If out->ncomb is already 255, -after incrementing it will get 0 instead of 256, and cause illegal -memory access in subsequent processing. - -This patch introduces GRUB_UNICODE_NCOMB_MAX to represent the max -acceptable value of ncomb. The code now checks for this limit and -ignores additional combining characters when limit is reached. - -Reported-by: Daniel Axtens -Signed-off-by: Zhang Boyang -Reviewed-by: Daniel Kiper -(cherry picked from commit da90d62316a3b105d2fbd7334d6521936bd6dcf6) -(cherry picked from commit 26fafec86000b5322837722a115279ef03922ca6) ---- - grub-core/normal/charset.c | 3 +++ - include/grub/unicode.h | 2 ++ - 2 files changed, 5 insertions(+) - -diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c -index 7a5a7c153c..c243ca6dae 100644 ---- a/grub-core/normal/charset.c -+++ b/grub-core/normal/charset.c -@@ -472,6 +472,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, - if (!haveout) - continue; - -+ if (out->ncomb == GRUB_UNICODE_NCOMB_MAX) -+ continue; -+ - if (comb_type == GRUB_UNICODE_COMB_MC - || comb_type == GRUB_UNICODE_COMB_ME - || comb_type == GRUB_UNICODE_COMB_MN) -diff --git a/include/grub/unicode.h b/include/grub/unicode.h -index 4de986a857..c4f6fca043 100644 ---- a/include/grub/unicode.h -+++ b/include/grub/unicode.h -@@ -147,7 +147,9 @@ struct grub_unicode_glyph - grub_uint8_t bidi_level:6; /* minimum: 6 */ - enum grub_bidi_type bidi_type:5; /* minimum: :5 */ - -+#define GRUB_UNICODE_NCOMB_MAX ((1 << 8) - 1) - unsigned ncomb:8; -+ - /* Hint by unicode subsystem how wide this character usually is. - Real width is determined by font. Set only in UTF-8 stream. */ - int estimated_width:8; diff --git a/SOURCES/0307-efi-Increase-default-memory-allocation-to-32-MiB.patch b/SOURCES/0307-efi-Increase-default-memory-allocation-to-32-MiB.patch new file mode 100644 index 0000000..b70c3cc --- /dev/null +++ b/SOURCES/0307-efi-Increase-default-memory-allocation-to-32-MiB.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 20 Sep 2022 00:30:30 +1000 +Subject: [PATCH] efi: Increase default memory allocation to 32 MiB + +We have multiple reports of things being slower with a 1 MiB initial static +allocation, and a report (more difficult to nail down) of a boot failure +as a result of the smaller initial allocation. + +Make the initial memory allocation 32 MiB. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 75e38e86e7d9202f050b093f20500d9ad4c6dad9) +--- + grub-core/kern/efi/mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 016ba6cf2f..b27e966e1f 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -39,7 +39,7 @@ + #define MEMORY_MAP_SIZE 0x3000 + + /* The default heap size for GRUB itself in bytes. */ +-#define DEFAULT_HEAP_SIZE 0x100000 ++#define DEFAULT_HEAP_SIZE 0x2000000 + + static void *finish_mmap_buf = 0; + static grub_efi_uintn_t finish_mmap_size = 0; diff --git a/SOURCES/0308-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch b/SOURCES/0308-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch new file mode 100644 index 0000000..c919891 --- /dev/null +++ b/SOURCES/0308-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sat, 15 Oct 2022 22:15:11 +0800 +Subject: [PATCH] mm: Try invalidate disk caches last when out of memory + +Every heap grow will cause all disk caches invalidated which decreases +performance severely. This patch moves disk cache invalidation code to +the last of memory squeezing measures. So, disk caches are released only +when there are no other ways to get free memory. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +Reviewed-by: Patrick Steinhardt +(cherry picked from commit 17975d10a80e2457e5237f87fa58a7943031983e) +--- + grub-core/kern/mm.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index f2e27f263b..da1ac9427c 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -443,12 +443,6 @@ grub_memalign (grub_size_t align, grub_size_t size) + switch (count) + { + case 0: +- /* Invalidate disk caches. */ +- grub_disk_cache_invalidate_all (); +- count++; +- goto again; +- +- case 1: + /* Request additional pages, contiguous */ + count++; + +@@ -458,7 +452,7 @@ grub_memalign (grub_size_t align, grub_size_t size) + + /* fallthrough */ + +- case 2: ++ case 1: + /* Request additional pages, anything at all */ + count++; + +@@ -474,6 +468,12 @@ grub_memalign (grub_size_t align, grub_size_t size) + + /* fallthrough */ + ++ case 2: ++ /* Invalidate disk caches. */ ++ grub_disk_cache_invalidate_all (); ++ count++; ++ goto again; ++ + default: + break; + } diff --git a/SOURCES/0309-ppc64le-signed-boot-media-changes.patch b/SOURCES/0309-ppc64le-signed-boot-media-changes.patch new file mode 100644 index 0000000..bd71437 --- /dev/null +++ b/SOURCES/0309-ppc64le-signed-boot-media-changes.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 25 Jan 2023 16:10:58 -0500 +Subject: [PATCH] ppc64le: signed boot media changes + +Skip mdraid < 1.1 on isos since mdraid* can't even + +Prior to this change, on ppc64le with part_msdos and the mdraid* modules +enabled, we see: + + disk/diskfilter.c:191: scanning ieee1275/cdrom + kern/disk.c:196: Opening `ieee1275/cdrom'... + disk/ieee1275/ofdisk.c:477: Opening `cdrom'. + disk/ieee1275/ofdisk.c:502: MAX_RETRIES set to 20 + kern/disk.c:288: Opening `ieee1275/cdrom' succeeded. + disk/diskfilter.c:136: Scanning for DISKFILTER devices on disk ieee1275/cdrom + partmap/msdos.c:184: partition 0: flag 0x80, type 0x96, start 0x0, len + 0x6a5d70 + disk/diskfilter.c:136: Scanning for DISKFILTER devices on disk ieee1275/cdrom + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + SCSI-DISK: Access beyond end of device ! + disk/ieee1275/ofdisk.c:578: MAX_RETRIES set to 20 + +These latter two lines repeat many times, eventually ending in: + + kern/disk.c:388: ieee1275/cdrom read failed + error: ../../grub-core/disk/ieee1275/ofdisk.c:608:failure reading sector + 0x1a9720 from `ieee1275/cdrom'. + +and the system drops to a "grub>" prompt. + +Prior to 1.1, mdraid stored the superblock offset from the end of the +disk, and the firmware really doesn't like reads there. Best guess was +that the firmware and the iso image appear to diagree on the blocksize +(512 vs. 2048), and the diskfilter RAID probing is too much for it. +It's tempting to just skip probing for cdroms, but unfortunately isos +can be virtualized elsewhere - such as regular disks. + +Also fix detection of root, and try the chrp path as a fallback if the +built prefix doesn't work. + +Signed-off-by: Robbie Harwood + +wip +--- + grub-core/disk/mdraid1x_linux.c | 8 +++++++- + grub-core/disk/mdraid_linux.c | 5 +++++ + grub-core/kern/ieee1275/openfw.c | 2 +- + grub-core/normal/main.c | 5 +++++ + 4 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c +index 38444b02c7..08c57ae16e 100644 +--- a/grub-core/disk/mdraid1x_linux.c ++++ b/grub-core/disk/mdraid1x_linux.c +@@ -129,7 +129,13 @@ grub_mdraid_detect (grub_disk_t disk, + grub_uint32_t level; + struct grub_diskfilter_vg *array; + char *uuid; +- ++ ++#ifdef __powerpc__ ++ /* Firmware will yell at us for reading too far. */ ++ if (minor_version == 0) ++ continue; ++#endif ++ + if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0) + continue; + +diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c +index e40216f511..98fcfb1be6 100644 +--- a/grub-core/disk/mdraid_linux.c ++++ b/grub-core/disk/mdraid_linux.c +@@ -189,6 +189,11 @@ grub_mdraid_detect (grub_disk_t disk, + grub_uint32_t level; + struct grub_diskfilter_vg *ret; + ++#ifdef __powerpc__ ++ /* Firmware will yell at us for reading too far. */ ++ return NULL; ++#endif ++ + /* The sector where the mdraid 0.90 superblock is stored, if available. */ + size = grub_disk_native_sectors (disk); + if (size == GRUB_DISK_SIZE_UNKNOWN) +diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c +index 3a6689abb1..0278054c61 100644 +--- a/grub-core/kern/ieee1275/openfw.c ++++ b/grub-core/kern/ieee1275/openfw.c +@@ -499,7 +499,7 @@ grub_ieee1275_encode_devname (const char *path) + *optr++ ='\\'; + *optr++ = *iptr++; + } +- if (partition && partition[0]) ++ if (partition && partition[0] >= '0' && partition[0] <= '9') + { + unsigned int partno = grub_strtoul (partition, 0, 0); + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 8f5fd81003..d59145f861 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -372,6 +372,7 @@ grub_try_normal_prefix (const char *prefix) + file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); + if (file) + { ++ grub_env_set ("prefix", prefix); + grub_file_close (file); + err = GRUB_ERR_NONE; + } +@@ -447,6 +448,10 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + err = grub_try_normal ("fw_path"); + if (err == GRUB_ERR_FILE_NOT_FOUND) + err = grub_try_normal ("prefix"); ++#ifdef __powerpc__ ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ err = grub_try_normal_prefix ("/boot/grub"); ++#endif + if (err == GRUB_ERR_FILE_NOT_FOUND) + err = grub_try_normal_discover (); + if (err == GRUB_ERR_FILE_NOT_FOUND) diff --git a/SOURCES/0310-core-Fix-several-implicit-function-declarations.patch b/SOURCES/0310-core-Fix-several-implicit-function-declarations.patch new file mode 100644 index 0000000..48c5bb0 --- /dev/null +++ b/SOURCES/0310-core-Fix-several-implicit-function-declarations.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Arjun Shankar +Date: Sun, 5 Feb 2023 11:13:55 +0100 +Subject: [PATCH] core: Fix several implicit function declarations + +These #include lines ensure that grub2 continues to build with C99 +where implicit function declarations are removed. + +Related to: + + + +--- + grub-core/commands/efi/connectefi.c | 1 + + grub-core/net/http.c | 1 + + grub-core/term/at_keyboard.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/grub-core/commands/efi/connectefi.c b/grub-core/commands/efi/connectefi.c +index 8ab75bd51b..3752ae17ed 100644 +--- a/grub-core/commands/efi/connectefi.c ++++ b/grub-core/commands/efi/connectefi.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 57d2721719..5f956b743e 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c +index dac0f946fe..de3e4abe44 100644 +--- a/grub-core/term/at_keyboard.c ++++ b/grub-core/term/at_keyboard.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + diff --git a/SOURCES/0311-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch b/SOURCES/0311-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch new file mode 100644 index 0000000..65834d8 --- /dev/null +++ b/SOURCES/0311-loader-Add-support-for-grub-emu-to-kexec-Linux-menu-.patch @@ -0,0 +1,431 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Raymund Will +Date: Mon, 24 Oct 2022 14:33:50 -0400 +Subject: [PATCH] loader: Add support for grub-emu to kexec Linux menu entries + +The GRUB emulator is used as a debugging utility but it could also be +used as a user-space bootloader if there is support to boot an operating +system. + +The Linux kernel is already able to (re)boot another kernel via the +kexec boot mechanism. So the grub-emu tool could rely on this feature +and have linux and initrd commands that are used to pass a kernel, +initramfs image and command line parameters to kexec for booting +a selected menu entry. + +By default the systemctl kexec option is used so systemd can shutdown +all of the running services before doing a reboot using kexec. But if +this is not present, it can fall back to executing the kexec user-space +tool directly. The ability to force a kexec-reboot when systemctl kexec +fails must only be used in controlled environments to avoid possible +filesystem corruption and data loss. + +Signed-off-by: Raymund Will +Signed-off-by: John Jolly +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Robbie Harwood +Reviewed-by: Daniel Kiper +(cherry picked from commit e364307f6acc2f631b4c1fefda0791b9ce1f205f) +[rharwood: conflicts around makefile and grub_exit return code] +--- + grub-core/Makefile.core.def | 3 - + grub-core/kern/emu/main.c | 4 + + grub-core/kern/emu/misc.c | 18 ++++- + grub-core/loader/emu/linux.c | 178 +++++++++++++++++++++++++++++++++++++++++++ + include/grub/emu/exec.h | 4 +- + include/grub/emu/hostfile.h | 3 +- + include/grub/emu/misc.h | 3 + + docs/grub.texi | 30 ++++++-- + grub-core/Makefile.am | 1 + + 9 files changed, 230 insertions(+), 14 deletions(-) + create mode 100644 grub-core/loader/emu/linux.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 741a033978..f21da23213 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1864,11 +1864,8 @@ module = { + riscv32 = loader/riscv/linux.c; + riscv64 = loader/riscv/linux.c; + emu = loader/emu/linux.c; +- + common = loader/linux.c; + common = lib/cmdline.c; +- enable = noemu; +- + efi = loader/efi/linux.c; + }; + +diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c +index 12277c34d2..68e2b283bb 100644 +--- a/grub-core/kern/emu/main.c ++++ b/grub-core/kern/emu/main.c +@@ -107,6 +107,7 @@ static struct argp_option options[] = { + N_("use GRUB files in the directory DIR [default=%s]"), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, + {"hold", 'H', N_("SECS"), OPTION_ARG_OPTIONAL, N_("wait until a debugger will attach"), 0}, ++ {"kexec", 'X', 0, 0, N_("use kexec to boot Linux kernels via systemctl (pass twice to enable dangerous fallback to non-systemctl)."), 0}, + { 0, 0, 0, 0, 0, 0 } + }; + +@@ -164,6 +165,9 @@ argp_parser (int key, char *arg, struct argp_state *state) + case 'v': + verbosity++; + break; ++ case 'X': ++ grub_util_set_kexecute (); ++ break; + + case ARGP_KEY_ARG: + { +diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c +index d278c2921f..02d27c3440 100644 +--- a/grub-core/kern/emu/misc.c ++++ b/grub-core/kern/emu/misc.c +@@ -39,6 +39,7 @@ + #include + + int verbosity; ++int kexecute; + + void + grub_util_warn (const char *fmt, ...) +@@ -82,7 +83,7 @@ grub_util_error (const char *fmt, ...) + vfprintf (stderr, fmt, ap); + va_end (ap); + fprintf (stderr, ".\n"); +- exit (1); ++ grub_exit (1); + } + + void * +@@ -154,6 +155,9 @@ void + __attribute__ ((noreturn)) + grub_exit (int rc) + { ++#if defined (GRUB_KERNEL) ++ grub_reboot (); ++#endif + exit (rc < 0 ? 1 : rc); + } + #endif +@@ -215,3 +219,15 @@ grub_util_load_image (const char *path, char *buf) + + fclose (fp); + } ++ ++void ++grub_util_set_kexecute (void) ++{ ++ kexecute++; ++} ++ ++int ++grub_util_get_kexecute (void) ++{ ++ return kexecute; ++} +diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c +new file mode 100644 +index 0000000000..0cf378a376 +--- /dev/null ++++ b/grub-core/loader/emu/linux.c +@@ -0,0 +1,178 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_dl_t my_mod; ++ ++static char *kernel_path; ++static char *initrd_path; ++static char *boot_cmdline; ++ ++static grub_err_t ++grub_linux_boot (void) ++{ ++ grub_err_t rc = GRUB_ERR_NONE; ++ char *initrd_param; ++ const char *kexec[] = {"kexec", "-la", kernel_path, boot_cmdline, NULL, NULL}; ++ const char *systemctl[] = {"systemctl", "kexec", NULL}; ++ int kexecute = grub_util_get_kexecute (); ++ ++ if (initrd_path) ++ { ++ initrd_param = grub_xasprintf ("--initrd=%s", initrd_path); ++ kexec[3] = initrd_param; ++ kexec[4] = boot_cmdline; ++ } ++ else ++ initrd_param = grub_xasprintf ("%s", ""); ++ ++ grub_dprintf ("linux", "%serforming 'kexec -la %s %s %s'\n", ++ (kexecute) ? "P" : "Not p", ++ kernel_path, initrd_param, boot_cmdline); ++ ++ if (kexecute) ++ rc = grub_util_exec (kexec); ++ ++ grub_free (initrd_param); ++ ++ if (rc != GRUB_ERR_NONE) ++ { ++ grub_error (rc, N_("error trying to perform kexec load operation")); ++ grub_sleep (3); ++ return rc; ++ } ++ ++ if (kexecute < 1) ++ grub_fatal (N_("use '"PACKAGE"-emu --kexec' to force a system restart")); ++ ++ grub_dprintf ("linux", "Performing 'systemctl kexec' (%s) ", ++ (kexecute==1) ? "do-or-die" : "just-in-case"); ++ rc = grub_util_exec (systemctl); ++ ++ if (kexecute == 1) ++ grub_fatal (N_("error trying to perform 'systemctl kexec': %d"), rc); ++ ++ /* ++ * WARNING: forcible reset should only be used in read-only environments. ++ * grub-emu cannot check for these - users beware. ++ */ ++ grub_dprintf ("linux", "Performing 'kexec -ex'"); ++ kexec[1] = "-ex"; ++ kexec[2] = NULL; ++ rc = grub_util_exec (kexec); ++ if (rc != GRUB_ERR_NONE) ++ grub_fatal (N_("error trying to directly perform 'kexec -ex': %d"), rc); ++ ++ return rc; ++} ++ ++static grub_err_t ++grub_linux_unload (void) ++{ ++ /* Unloading: we're no longer in use. */ ++ grub_dl_unref (my_mod); ++ grub_free (boot_cmdline); ++ boot_cmdline = NULL; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, ++ char *argv[]) ++{ ++ int i; ++ char *tempstr; ++ ++ /* Mark ourselves as in-use. */ ++ grub_dl_ref (my_mod); ++ ++ if (argc == 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ ++ if (!grub_util_is_regular (argv[0])) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ N_("cannot find kernel file %s"), argv[0]); ++ ++ grub_free (kernel_path); ++ kernel_path = grub_xasprintf ("%s", argv[0]); ++ ++ grub_free (boot_cmdline); ++ boot_cmdline = NULL; ++ ++ if (argc > 1) ++ { ++ boot_cmdline = grub_xasprintf ("--command-line=%s", argv[1]); ++ for (i = 2; i < argc; i++) ++ { ++ tempstr = grub_xasprintf ("%s %s", boot_cmdline, argv[i]); ++ grub_free (boot_cmdline); ++ boot_cmdline = tempstr; ++ } ++ } ++ ++ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, ++ char *argv[]) ++{ ++ if (argc == 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ ++ if (!grub_util_is_regular (argv[0])) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ N_("Cannot find initrd file %s"), argv[0]); ++ ++ grub_free (initrd_path); ++ initrd_path = grub_xasprintf ("%s", argv[0]); ++ ++ /* We are done - mark ourselves as on longer in use. */ ++ grub_dl_unref (my_mod); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_command_t cmd_linux, cmd_initrd; ++ ++GRUB_MOD_INIT (linux) ++{ ++ cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0, ++ N_("Load Linux.")); ++ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0, ++ N_("Load initrd.")); ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI (linux) ++{ ++ grub_unregister_command (cmd_linux); ++ grub_unregister_command (cmd_initrd); ++} +diff --git a/include/grub/emu/exec.h b/include/grub/emu/exec.h +index d1073ef86a..1b61b4a2e5 100644 +--- a/include/grub/emu/exec.h ++++ b/include/grub/emu/exec.h +@@ -23,6 +23,8 @@ + #include + + #include ++#include ++ + pid_t + grub_util_exec_pipe (const char *const *argv, int *fd); + pid_t +@@ -32,7 +34,7 @@ int + grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file, + const char *stdout_file, const char *stderr_file); + int +-grub_util_exec (const char *const *argv); ++EXPORT_FUNC(grub_util_exec) (const char *const *argv); + int + grub_util_exec_redirect (const char *const *argv, const char *stdin_file, + const char *stdout_file); +diff --git a/include/grub/emu/hostfile.h b/include/grub/emu/hostfile.h +index cfb1e2b566..a61568e36e 100644 +--- a/include/grub/emu/hostfile.h ++++ b/include/grub/emu/hostfile.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + + int +@@ -29,7 +30,7 @@ grub_util_is_directory (const char *path); + int + grub_util_is_special_file (const char *path); + int +-grub_util_is_regular (const char *path); ++EXPORT_FUNC(grub_util_is_regular) (const char *path); + + char * + grub_util_path_concat (size_t n, ...); +diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h +index ff9c48a649..01056954b9 100644 +--- a/include/grub/emu/misc.h ++++ b/include/grub/emu/misc.h +@@ -57,6 +57,9 @@ void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format ( + void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); + void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2), noreturn)); + ++void EXPORT_FUNC(grub_util_set_kexecute) (void); ++int EXPORT_FUNC(grub_util_get_kexecute) (void) WARN_UNUSED_RESULT; ++ + grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void); + + #ifdef HAVE_DEVICE_MAPPER +diff --git a/docs/grub.texi b/docs/grub.texi +index a4da9c2a1b..1750b72ee9 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -923,17 +923,17 @@ magic. + @node General boot methods + @section How to boot operating systems + +-GRUB has two distinct boot methods. One of the two is to load an +-operating system directly, and the other is to chain-load another boot +-loader which then will load an operating system actually. Generally +-speaking, the former is more desirable, because you don't need to +-install or maintain other boot loaders and GRUB is flexible enough to +-load an operating system from an arbitrary disk/partition. However, +-the latter is sometimes required, since GRUB doesn't support all the +-existing operating systems natively. ++GRUB has three distinct boot methods: loading an operating system ++directly, using kexec from userspace, and chainloading another ++bootloader. Generally speaking, the first two are more desirable ++because you don't need to install or maintain other boot loaders and ++GRUB is flexible enough to load an operating system from an arbitrary ++disk/partition. However, chainloading is sometimes required, as GRUB ++doesn't support all existing operating systems natively. + + @menu + * Loading an operating system directly:: ++* Kexec:: + * Chain-loading:: + @end menu + +@@ -959,6 +959,20 @@ use more complicated instructions. @xref{DOS/Windows}, for more + information. + + ++@node Kexec ++@subsection Kexec with grub2-emu ++ ++GRUB can be run in userspace by invoking the grub2-emu tool. It will ++read all configuration scripts as if booting directly (see @xref{Loading ++an operating system directly}). With the @code{--kexec} flag, and ++kexec(8) support from the operating system, the @command{linux} command ++will directly boot the target image. For systems that lack working ++systemctl(1) support for kexec, passing the @code{--kexec} flag twice ++will fallback to invoking kexec(8) directly; note however that this ++fallback may be unsafe outside read-only environments, as it does not ++invoke shutdown machinery. ++ ++ + @node Chain-loading + @subsection Chain-loading an OS + +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index c2e8a82bce..dd49939aaa 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -309,6 +309,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/exec.h + if COND_GRUB_EMU_SDL + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h + endif diff --git a/SOURCES/0312-powerpc-Drop-Open-Hack-Ware-remove-GRUB_IEEE1275_FLA.patch b/SOURCES/0312-powerpc-Drop-Open-Hack-Ware-remove-GRUB_IEEE1275_FLA.patch new file mode 100644 index 0000000..735075a --- /dev/null +++ b/SOURCES/0312-powerpc-Drop-Open-Hack-Ware-remove-GRUB_IEEE1275_FLA.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Sep 2021 15:46:12 +1000 +Subject: [PATCH] powerpc: Drop Open Hack'Ware - remove + GRUB_IEEE1275_FLAG_FORCE_CLAIM + +Open Hack'Ware was the only user. It added a lot of complexity. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 333e63b356f1ce833cda1937ed8351618cbdf9d3) +--- + grub-core/kern/ieee1275/init.c | 6 +----- + grub-core/lib/ieee1275/relocator.c | 4 ---- + grub-core/loader/powerpc/ieee1275/linux.c | 14 -------------- + include/grub/ieee1275/ieee1275.h | 11 ----------- + 4 files changed, 1 insertion(+), 34 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 0dcd114ce5..6581c2c996 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -207,11 +207,7 @@ grub_claim_heap (void) + { + unsigned long total = 0; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, +- 1, &total); +- else +- grub_machine_mmap_iterate (heap_init, &total); ++ grub_machine_mmap_iterate (heap_init, &total); + } + #endif + +diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c +index c6dd8facb0..d1bb45c75e 100644 +--- a/grub-core/lib/ieee1275/relocator.c ++++ b/grub-core/lib/ieee1275/relocator.c +@@ -38,8 +38,6 @@ grub_relocator_firmware_get_max_events (void) + { + int counter = 0; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- return 0; + grub_machine_mmap_iterate (count, &counter); + return 2 * counter; + } +@@ -92,8 +90,6 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) + .counter = 0 + }; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- return 0; + grub_machine_mmap_iterate (grub_relocator_firmware_fill_events_iter, &ctx); + return ctx.counter; + } +diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c +index 818b2a86d1..6fdd863130 100644 +--- a/grub-core/loader/powerpc/ieee1275/linux.c ++++ b/grub-core/loader/powerpc/ieee1275/linux.c +@@ -111,20 +111,6 @@ grub_linux_claimmap_iterate (grub_addr_t target, grub_size_t size, + .found_addr = (grub_addr_t) -1 + }; + +- if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) +- { +- grub_uint64_t addr = target; +- if (addr < GRUB_IEEE1275_STATIC_HEAP_START +- + GRUB_IEEE1275_STATIC_HEAP_LEN) +- addr = GRUB_IEEE1275_STATIC_HEAP_START +- + GRUB_IEEE1275_STATIC_HEAP_LEN; +- addr = ALIGN_UP (addr, align); +- if (grub_claimmap (addr, size) == GRUB_ERR_NONE) +- return addr; +- return (grub_addr_t) -1; +- } +- +- + grub_machine_mmap_iterate (alloc_mem, &ctx); + + return ctx.found_addr; +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index b5a1d49bbc..6a1d3e5d70 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -85,14 +85,6 @@ extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu); + + extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *) GRUB_IEEE1275_ENTRY_FN_ATTRIBUTE; + +-/* Static heap, used only if FORCE_CLAIM is set, +- happens on Open Hack'Ware. Should be in platform-specific +- header but is used only on PPC anyway. +-*/ +-#define GRUB_IEEE1275_STATIC_HEAP_START 0x1000000 +-#define GRUB_IEEE1275_STATIC_HEAP_LEN 0x1000000 +- +- + enum grub_ieee1275_flag + { + /* Old World Macintosh firmware fails seek when "dev:0" is opened. */ +@@ -119,9 +111,6 @@ enum grub_ieee1275_flag + /* Open Hack'Ware stops when grub_ieee1275_interpret is used. */ + GRUB_IEEE1275_FLAG_CANNOT_INTERPRET, + +- /* Open Hack'Ware has no memory map, just claim what we need. */ +- GRUB_IEEE1275_FLAG_FORCE_CLAIM, +- + /* Open Hack'Ware don't support the ANSI sequence. */ + GRUB_IEEE1275_FLAG_NO_ANSI, + diff --git a/SOURCES/0313-ieee1275-request-memory-with-ibm-client-architecture.patch b/SOURCES/0313-ieee1275-request-memory-with-ibm-client-architecture.patch new file mode 100644 index 0000000..4e95630 --- /dev/null +++ b/SOURCES/0313-ieee1275-request-memory-with-ibm-client-architecture.patch @@ -0,0 +1,308 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Feb 2023 10:03:20 -0500 +Subject: [PATCH] ieee1275: request memory with ibm, + client-architecture-support + +On PowerVM, the first time we boot a Linux partition, we may only get +256MB of real memory area, even if the partition has more memory. + +This isn't enough to reliably verify a kernel. Fortunately, the Power +Architecture Platform Reference (PAPR) defines a method we can call to ask +for more memory: the broad and powerful ibm,client-architecture-support +(CAS) method. + +CAS can do an enormous amount of things on a PAPR platform: as well as +asking for memory, you can set the supported processor level, the interrupt +controller, hash vs radix mmu, and so on. + +If: + + - we are running under what we think is PowerVM (compatible property of / + begins with "IBM"), and + + - the full amount of RMA is less than 512MB (as determined by the reg + property of /memory) + +then call CAS as follows: (refer to the Linux on Power Architecture +Reference, LoPAR, which is public, at B.5.2.3): + + - Use the "any" PVR value and supply 2 option vectors. + + - Set option vector 1 (PowerPC Server Processor Architecture Level) + to "ignore". + + - Set option vector 2 with default or Linux-like options, including a + min-rma-size of 512MB. + + - Set option vector 3 to request Floating Point, VMX and Decimal Floating + point, but don't abort the boot if we can't get them. + + - Set option vector 4 to request a minimum VP percentage to 1%, which is + what Linux requests, and is below the default of 10%. Without this, + some systems with very large or very small configurations fail to boot. + +This will cause a CAS reboot and the partition will restart with 512MB +of RMA. Importantly, grub will notice the 512MB and not call CAS again. + +Notes about the choices of parameters: + + - A partition can be configured with only 256MB of memory, which would + mean this request couldn't be satisfied, but PFW refuses to load with + only 256MB of memory, so it's a bit moot. SLOF will run fine with 256MB, + but we will never call CAS under qemu/SLOF because /compatible won't + begin with "IBM".) + + - unspecified CAS vectors take on default values. Some of these values + might restrict the ability of certain hardware configurations to boot. + This is why we need to specify the VP percentage in vector 4, which is + in turn why we need to specify vector 3. + +Finally, we should have enough memory to verify a kernel, and we will +reach Linux. One of the first things Linux does while still running under +OpenFirmware is to call CAS with a much fuller set of options (including +asking for 512MB of memory). Linux includes a much more restrictive set of +PVR values and processor support levels, and this CAS invocation will likely +induce another reboot. On this reboot grub will again notice the higher RMA, +and not call CAS. We will get to Linux again, Linux will call CAS again, but +because the values are now set for Linux this will not induce another CAS +reboot and we will finally boot all the way to userspace. + +On all subsequent boots, everything will be configured with 512MB of RMA, +so there will be no further CAS reboots from grub. (phyp is super sticky +with the RMA size - it persists even on cold boots. So if you've ever booted +Linux in a partition, you'll probably never have grub call CAS. It'll only +ever fire the first time a partition loads grub, or if you deliberately lower +the amount of memory your partition has below 512MB.) + +Signed-off-by: Daniel Axtens +Signed-off-by: Stefan Berger +Reviewed-by: Daniel Kiper +(cherry picked from commit d5571590b7de61887efac1c298901455697ba307) +--- + grub-core/kern/ieee1275/cmain.c | 5 ++ + grub-core/kern/ieee1275/init.c | 167 ++++++++++++++++++++++++++++++++++++++- + include/grub/ieee1275/ieee1275.h | 12 ++- + 3 files changed, 182 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c +index 04df9d2c66..dce7b84922 100644 +--- a/grub-core/kern/ieee1275/cmain.c ++++ b/grub-core/kern/ieee1275/cmain.c +@@ -127,6 +127,11 @@ grub_ieee1275_find_options (void) + break; + } + } ++ ++#if defined(__powerpc__) ++ if (grub_strncmp (tmp, "IBM,", 4) == 0) ++ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY); ++#endif + } + + if (is_smartfirmware) +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 6581c2c996..8ae405bc79 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -202,11 +202,176 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + return 0; + } + +-static void ++/* ++ * How much memory does OF believe it has? (regardless of whether ++ * it's accessible or not) ++ */ ++static grub_err_t ++grub_ieee1275_total_mem (grub_uint64_t *total) ++{ ++ grub_ieee1275_phandle_t root; ++ grub_ieee1275_phandle_t memory; ++ grub_uint32_t reg[4]; ++ grub_ssize_t reg_size; ++ grub_uint32_t address_cells = 1; ++ grub_uint32_t size_cells = 1; ++ grub_uint64_t size; ++ ++ /* If we fail to get to the end, report 0. */ ++ *total = 0; ++ ++ /* Determine the format of each entry in `reg'. */ ++ if (grub_ieee1275_finddevice ("/", &root)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node"); ++ if (grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells, ++ sizeof (address_cells), 0)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #address-cells"); ++ if (grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells, ++ sizeof (size_cells), 0)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #size-cells"); ++ ++ if (size_cells > address_cells) ++ address_cells = size_cells; ++ ++ /* Load `/memory/reg'. */ ++ if (grub_ieee1275_finddevice ("/memory", &memory)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find /memory node"); ++ if (grub_ieee1275_get_integer_property (memory, "reg", reg, ++ sizeof (reg), ®_size)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /memory/reg property"); ++ if (reg_size < 0 || (grub_size_t) reg_size > sizeof (reg)) ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "/memory response buffer exceeded"); ++ ++ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS)) ++ { ++ address_cells = 1; ++ size_cells = 1; ++ } ++ ++ /* Decode only the size */ ++ size = reg[address_cells]; ++ if (size_cells == 2) ++ size = (size << 32) | reg[address_cells + 1]; ++ ++ *total = size; ++ ++ return grub_errno; ++} ++ ++#if defined(__powerpc__) ++ ++/* See PAPR or arch/powerpc/kernel/prom_init.c */ ++struct option_vector2 ++{ ++ grub_uint8_t byte1; ++ grub_uint16_t reserved; ++ grub_uint32_t real_base; ++ grub_uint32_t real_size; ++ grub_uint32_t virt_base; ++ grub_uint32_t virt_size; ++ grub_uint32_t load_base; ++ grub_uint32_t min_rma; ++ grub_uint32_t min_load; ++ grub_uint8_t min_rma_percent; ++ grub_uint8_t max_pft_size; ++} GRUB_PACKED; ++ ++struct pvr_entry ++{ ++ grub_uint32_t mask; ++ grub_uint32_t entry; ++}; ++ ++struct cas_vector ++{ ++ struct ++ { ++ struct pvr_entry terminal; ++ } pvr_list; ++ grub_uint8_t num_vecs; ++ grub_uint8_t vec1_size; ++ grub_uint8_t vec1; ++ grub_uint8_t vec2_size; ++ struct option_vector2 vec2; ++ grub_uint8_t vec3_size; ++ grub_uint16_t vec3; ++ grub_uint8_t vec4_size; ++ grub_uint16_t vec4; ++} GRUB_PACKED; ++ ++/* ++ * Call ibm,client-architecture-support to try to get more RMA. ++ * We ask for 512MB which should be enough to verify a distro kernel. ++ * We ignore most errors: if we don't succeed we'll proceed with whatever ++ * memory we have. ++ */ ++static void ++grub_ieee1275_ibm_cas (void) ++{ ++ int rc; ++ grub_ieee1275_ihandle_t root; ++ struct cas_args ++ { ++ struct grub_ieee1275_common_hdr common; ++ grub_ieee1275_cell_t method; ++ grub_ieee1275_ihandle_t ihandle; ++ grub_ieee1275_cell_t cas_addr; ++ grub_ieee1275_cell_t result; ++ } args; ++ struct cas_vector vector = ++ { ++ .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ ++ .num_vecs = 4 - 1, ++ .vec1_size = 0, ++ .vec1 = 0x80, /* ignore */ ++ .vec2_size = 1 + sizeof (struct option_vector2) - 2, ++ .vec2 = { ++ 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48 ++ }, ++ .vec3_size = 2 - 1, ++ .vec3 = 0x00e0, /* ask for FP + VMX + DFP but don't halt if unsatisfied */ ++ .vec4_size = 2 - 1, ++ .vec4 = 0x0001, /* set required minimum capacity % to the lowest value */ ++ }; ++ ++ INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); ++ args.method = (grub_ieee1275_cell_t) "ibm,client-architecture-support"; ++ rc = grub_ieee1275_open ("/", &root); ++ if (rc) ++ { ++ grub_error (GRUB_ERR_IO, "could not open root when trying to call CAS"); ++ return; ++ } ++ args.ihandle = root; ++ args.cas_addr = (grub_ieee1275_cell_t) &vector; ++ ++ grub_printf ("Calling ibm,client-architecture-support from grub..."); ++ IEEE1275_CALL_ENTRY_FN (&args); ++ grub_printf ("done\n"); ++ ++ grub_ieee1275_close (root); ++} ++ ++#endif /* __powerpc__ */ ++ ++static void + grub_claim_heap (void) + { + unsigned long total = 0; + ++#if defined(__powerpc__) ++ if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY)) ++ { ++ grub_uint64_t rma_size; ++ grub_err_t err; ++ ++ err = grub_ieee1275_total_mem (&rma_size); ++ /* if we have an error, don't call CAS, just hope for the best */ ++ if (err == GRUB_ERR_NONE && rma_size < (512 * 1024 * 1024)) ++ grub_ieee1275_ibm_cas (); ++ } ++#endif ++ + grub_machine_mmap_iterate (heap_init, &total); + } + #endif +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index 6a1d3e5d70..560c968460 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -138,7 +138,17 @@ enum grub_ieee1275_flag + + GRUB_IEEE1275_FLAG_RAW_DEVNAMES, + +- GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT ++ GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT, ++ ++#if defined(__powerpc__) ++ /* ++ * On PFW, the first time we boot a Linux partition, we may only get 256MB of ++ * real memory area, even if the partition has more memory. Set this flag if ++ * we think we're running under PFW. Then, if this flag is set, and the RMA is ++ * only 256MB in size, try asking for more with CAS. ++ */ ++ GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY, ++#endif + }; + + extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); diff --git a/SOURCES/0314-ieee1275-drop-len-1-quirk-in-heap_init.patch b/SOURCES/0314-ieee1275-drop-len-1-quirk-in-heap_init.patch new file mode 100644 index 0000000..4ce064b --- /dev/null +++ b/SOURCES/0314-ieee1275-drop-len-1-quirk-in-heap_init.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Feb 2023 10:03:21 -0500 +Subject: [PATCH] ieee1275: drop len -= 1 quirk in heap_init + +This was apparently 'required by some firmware': commit dc9468500919 +("2007-02-12 Hollis Blanchard "). + +It's not clear what firmware that was, and what platform from 14 years ago +which exhibited the bug then is still both in use and buggy now. + +It doesn't cause issues on qemu (mac99 or pseries) or under PFW for Power8. + +I don't have access to old Mac hardware, but if anyone feels especially +strongly we can put it under some feature flag. I really want to disable +it under pseries because it will mess with region merging. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit fc639d430297321ee4f77c5d2d698f698cec0dc7) +--- + grub-core/kern/ieee1275/init.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 8ae405bc79..c8d551759d 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -168,7 +168,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + addr = 0x180000; + } + } +- len -= 1; /* Required for some firmware. */ + + /* Never exceed HEAP_MAX_SIZE */ + if (*total + len > HEAP_MAX_SIZE) diff --git a/SOURCES/0315-ieee1275-support-runtime-memory-claiming.patch b/SOURCES/0315-ieee1275-support-runtime-memory-claiming.patch new file mode 100644 index 0000000..17ad61d --- /dev/null +++ b/SOURCES/0315-ieee1275-support-runtime-memory-claiming.patch @@ -0,0 +1,435 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Feb 2023 10:03:22 -0500 +Subject: [PATCH] ieee1275: support runtime memory claiming + +On powerpc-ieee1275, we are running out of memory trying to verify +anything. This is because: + + - we have to load an entire file into memory to verify it. This is + difficult to change with appended signatures. + - We only have 32MB of heap. + - Distro kernels are now often around 30MB. + +So we want to be able to claim more memory from OpenFirmware for our heap +at runtime. + +There are some complications: + + - The grub mm code isn't the only thing that will make claims on + memory from OpenFirmware: + + * PFW/SLOF will have claimed some for their own use. + + * The ieee1275 loader will try to find other bits of memory that we + haven't claimed to place the kernel and initrd when we go to boot. + + * Once we load Linux, it will also try to claim memory. It claims + memory without any reference to /memory/available, it just starts + at min(top of RMO, 768MB) and works down. So we need to avoid this + area. See arch/powerpc/kernel/prom_init.c as of v5.11. + + - The smallest amount of memory a ppc64 KVM guest can have is 256MB. + It doesn't work with distro kernels but can work with custom kernels. + We should maintain support for that. (ppc32 can boot with even less, + and we shouldn't break that either.) + + - Even if a VM has more memory, the memory OpenFirmware makes available + as Real Memory Area can be restricted. Even with our CAS work, an LPAR + on a PowerVM box is likely to have only 512MB available to OpenFirmware + even if it has many gigabytes of memory allocated. + +What should we do? + +We don't know in advance how big the kernel and initrd are going to be, +which makes figuring out how much memory we can take a bit tricky. + +To figure out how much memory we should leave unused, I looked at: + + - an Ubuntu 20.04.1 ppc64le pseries KVM guest: + vmlinux: ~30MB + initrd: ~50MB + + - a RHEL8.2 ppc64le pseries KVM guest: + vmlinux: ~30MB + initrd: ~30MB + +So to give us a little wriggle room, I think we want to leave at least +128MB for the loader to put vmlinux and initrd in memory and leave Linux +with space to satisfy its early allocations. + +Allow other space to be allocated at runtime. + +Tested-by: Stefan Berger +Signed-off-by: Daniel Axtens +(cherry picked from commit a5c710789ccdd27a84ae4a34c7d453bd585e2b66) +[rharwood: _start?] +--- + grub-core/kern/ieee1275/init.c | 270 ++++++++++++++++++++++++++++++++++++++--- + docs/grub-dev.texi | 7 +- + 2 files changed, 257 insertions(+), 20 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index c8d551759d..85af8fa97b 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -46,13 +46,26 @@ + #endif + #include + +-/* The maximum heap size we're going to claim */ ++/* The maximum heap size we're going to claim at boot. Not used by sparc. */ + #ifdef __i386__ + #define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) +-#else ++#else /* __powerpc__ */ + #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) + #endif + ++/* RMO max. address at 768 MB */ ++#define RMO_ADDR_MAX (grub_uint64_t) (768 * 1024 * 1024) ++ ++/* ++ * The amount of OF space we will not claim here so as to leave space for ++ * the loader and linux to service early allocations. ++ * ++ * In 2021, Daniel Axtens claims that we should leave at least 128MB to ++ * ensure we can load a stock kernel and initrd on a pseries guest with ++ * a 512MB real memory area under PowerVM. ++ */ ++#define RUNTIME_MIN_SPACE (128UL * 1024 * 1024) ++ + extern char _end[]; + + #ifdef __sparc__ +@@ -147,16 +160,52 @@ grub_claim_heap (void) + + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); + } + #else +-/* Helper for grub_claim_heap. */ ++/* Helpers for mm on powerpc. */ ++ ++/* ++ * How much memory does OF believe exists in total? ++ * ++ * This isn't necessarily the true total. It can be the total memory ++ * accessible in real mode for a pseries guest, for example. ++ */ ++static grub_uint64_t rmo_top; ++ + static int +-heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, +- void *data) ++count_free (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ void *data) + { +- unsigned long *total = data; ++ if (type != GRUB_MEMORY_AVAILABLE) ++ return 0; ++ ++ /* Do not consider memory beyond 4GB */ ++ if (addr > 0xffffffffULL) ++ return 0; ++ ++ if (addr + len > 0xffffffffULL) ++ len = 0xffffffffULL - addr; ++ ++ *(grub_uint32_t *) data += len; ++ ++ return 0; ++} ++ ++static int ++regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ unsigned int flags, void *data) ++{ ++ grub_uint32_t total = *(grub_uint32_t *) data; ++ grub_uint64_t linux_rmo_save; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + ++ /* Do not consider memory beyond 4GB */ ++ if (addr > 0xffffffffULL) ++ return 0; ++ ++ if (addr + len > 0xffffffffULL) ++ len = 0xffffffffULL - addr; ++ + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) +@@ -169,10 +218,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + } + } + +- /* Never exceed HEAP_MAX_SIZE */ +- if (*total + len > HEAP_MAX_SIZE) +- len = HEAP_MAX_SIZE - *total; +- + /* In theory, firmware should already prevent this from happening by not + listing our own image in /memory/available. The check below is intended + as a safeguard in case that doesn't happen. However, it doesn't protect +@@ -184,6 +229,108 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + len = 0; + } + ++ /* ++ * Linux likes to claim memory at min(RMO top, 768MB) and works down ++ * without reference to /memory/available. (See prom_init.c::alloc_down) ++ * ++ * If this block contains min(RMO top, 768MB), do not claim below that for ++ * at least a few MB (this is where RTAS, SML and potentially TCEs live). ++ * ++ * We also need to leave enough space for the DT in the RMA. (See ++ * prom_init.c::alloc_up) ++ * ++ * Finally, we also want to make sure that when grub loads the kernel, ++ * it isn't going to use up all the memory we're trying to reserve! So ++ * enforce our entire RUNTIME_MIN_SPACE here: ++ * ++ * |---------- Top of memory ----------| ++ * | | ++ * | available | ++ * | | ++ * |---------- 768 MB ----------| ++ * | | ++ * | reserved | ++ * | | ++ * |--- 768 MB - runtime min space ---| ++ * | | ++ * | available | ++ * | | ++ * |---------- 0 MB ----------| ++ * ++ * Edge cases: ++ * ++ * - Total memory less than RUNTIME_MIN_SPACE: only claim up to HEAP_MAX_SIZE. ++ * (enforced elsewhere) ++ * ++ * - Total memory between RUNTIME_MIN_SPACE and 768MB: ++ * ++ * |---------- Top of memory ----------| ++ * | | ++ * | reserved | ++ * | | ++ * |---- top - runtime min space ----| ++ * | | ++ * | available | ++ * | | ++ * |---------- 0 MB ----------| ++ * ++ * This by itself would not leave us with RUNTIME_MIN_SPACE of free bytes: if ++ * rmo_top < 768MB, we will almost certainly have FW claims in the reserved ++ * region. We try to address that elsewhere: grub_ieee1275_mm_add_region will ++ * not call us if the resulting free space would be less than RUNTIME_MIN_SPACE. ++ */ ++ linux_rmo_save = grub_min (RMO_ADDR_MAX, rmo_top) - RUNTIME_MIN_SPACE; ++ if (rmo_top > RUNTIME_MIN_SPACE) ++ { ++ if (rmo_top <= RMO_ADDR_MAX) ++ { ++ if (addr > linux_rmo_save) ++ { ++ grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n", ++ addr); ++ return 0; ++ } ++ else if (addr + len > linux_rmo_save) ++ { ++ grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n", ++ addr, addr + len, addr, rmo_top - RUNTIME_MIN_SPACE); ++ len = linux_rmo_save - addr; ++ } ++ } ++ else ++ { ++ /* ++ * we order these cases to prefer higher addresses and avoid some ++ * splitting issues ++ */ ++ if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX) ++ { ++ grub_dprintf ("ieee1275", ++ "adjusting region for RUNTIME_MIN_SPACE: (%llx -> %llx) -> (%llx -> %llx)\n", ++ addr, addr + len, RMO_ADDR_MAX, addr + len); ++ len = (addr + len) - RMO_ADDR_MAX; ++ addr = RMO_ADDR_MAX; ++ } ++ else if ((addr < linux_rmo_save) && ((addr + len) > linux_rmo_save)) ++ { ++ grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n", ++ addr, addr + len, addr, linux_rmo_save); ++ len = linux_rmo_save - addr; ++ } ++ else if (addr >= linux_rmo_save && (addr + len) <= RMO_ADDR_MAX) ++ { ++ grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n", ++ addr); ++ return 0; ++ } ++ } ++ } ++ if (flags & GRUB_MM_ADD_REGION_CONSECUTIVE && len < total) ++ return 0; ++ ++ if (len > total) ++ len = total; ++ + if (len) + { + grub_err_t err; +@@ -192,15 +339,95 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + if (err) + return err; + grub_mm_init_region ((void *) (grub_addr_t) addr, len); ++ total -= len; + } + +- *total += len; +- if (*total >= HEAP_MAX_SIZE) ++ *(grub_uint32_t *) data = total; ++ ++ if (total == 0) + return 1; + + return 0; + } + ++static int ++heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ void *data) ++{ ++ return regions_claim (addr, len, type, GRUB_MM_ADD_REGION_NONE, data); ++} ++ ++static int ++region_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, ++ void *data) ++{ ++ return regions_claim (addr, len, type, GRUB_MM_ADD_REGION_CONSECUTIVE, data); ++} ++ ++static grub_err_t ++grub_ieee1275_mm_add_region (grub_size_t size, unsigned int flags) ++{ ++ grub_uint32_t free_memory = 0; ++ grub_uint32_t avail = 0; ++ grub_uint32_t total; ++ ++ grub_dprintf ("ieee1275", "mm requested region of size %x, flags %x\n", ++ size, flags); ++ ++ /* ++ * Update free memory each time, which is a bit inefficient but guards us ++ * against a situation where some OF driver goes out to firmware for ++ * memory and we don't realise. ++ */ ++ grub_machine_mmap_iterate (count_free, &free_memory); ++ ++ /* Ensure we leave enough space to boot. */ ++ if (free_memory <= RUNTIME_MIN_SPACE + size) ++ { ++ grub_dprintf ("ieee1275", "Cannot satisfy allocation and retain minimum runtime space\n"); ++ return GRUB_ERR_OUT_OF_MEMORY; ++ } ++ ++ if (free_memory > RUNTIME_MIN_SPACE) ++ avail = free_memory - RUNTIME_MIN_SPACE; ++ ++ grub_dprintf ("ieee1275", "free = 0x%x available = 0x%x\n", free_memory, avail); ++ ++ if (flags & GRUB_MM_ADD_REGION_CONSECUTIVE) ++ { ++ /* first try rounding up hard for the sake of speed */ ++ total = grub_max (ALIGN_UP (size, 1024 * 1024) + 1024 * 1024, 32 * 1024 * 1024); ++ total = grub_min (avail, total); ++ ++ grub_dprintf ("ieee1275", "looking for %x bytes of memory (%x requested)\n", total, size); ++ ++ grub_machine_mmap_iterate (region_claim, &total); ++ grub_dprintf ("ieee1275", "get memory from fw %s\n", total == 0 ? "succeeded" : "failed"); ++ ++ if (total != 0) ++ { ++ total = grub_min (avail, size); ++ ++ grub_dprintf ("ieee1275", "fallback for %x bytes of memory (%x requested)\n", total, size); ++ ++ grub_machine_mmap_iterate (region_claim, &total); ++ grub_dprintf ("ieee1275", "fallback from fw %s\n", total == 0 ? "succeeded" : "failed"); ++ } ++ } ++ else ++ { ++ /* provide padding for a grub_mm_header_t and region */ ++ total = grub_min (avail, size); ++ grub_machine_mmap_iterate (heap_init, &total); ++ grub_dprintf ("ieee1275", "get noncontig memory from fw %s\n", total == 0 ? "succeeded" : "failed"); ++ } ++ ++ if (total == 0) ++ return GRUB_ERR_NONE; ++ else ++ return GRUB_ERR_OUT_OF_MEMORY; ++} ++ + /* + * How much memory does OF believe it has? (regardless of whether + * it's accessible or not) +@@ -356,17 +583,24 @@ grub_ieee1275_ibm_cas (void) + static void + grub_claim_heap (void) + { +- unsigned long total = 0; ++ grub_err_t err; ++ grub_uint32_t total = HEAP_MAX_SIZE; ++ ++ err = grub_ieee1275_total_mem (&rmo_top); ++ ++ /* ++ * If we cannot size the available memory, we can't be sure we're leaving ++ * space for the kernel, initrd and things Linux loads early in boot. So only ++ * allow further allocations from firmware on success ++ */ ++ if (err == GRUB_ERR_NONE) ++ grub_mm_add_region_fn = grub_ieee1275_mm_add_region; + + #if defined(__powerpc__) + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY)) + { +- grub_uint64_t rma_size; +- grub_err_t err; +- +- err = grub_ieee1275_total_mem (&rma_size); + /* if we have an error, don't call CAS, just hope for the best */ +- if (err == GRUB_ERR_NONE && rma_size < (512 * 1024 * 1024)) ++ if (err == GRUB_ERR_NONE && rmo_top < (512 * 1024 * 1024)) + grub_ieee1275_ibm_cas (); + } + #endif +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi +index 7b2455a8fe..7edc5b7e2b 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -1047,7 +1047,10 @@ space is limited to 4GiB. GRUB allocates pages from EFI for its heap, at most + 1.6 GiB. + + On i386-ieee1275 and powerpc-ieee1275 GRUB uses same stack as IEEE1275. +-It allocates at most 32MiB for its heap. ++ ++On i386-ieee1275 and powerpc-ieee1275, GRUB will allocate 32MiB for its heap on ++startup. It may allocate more at runtime, as long as at least 128MiB remain free ++in OpenFirmware. + + On sparc64-ieee1275 stack is 256KiB and heap is 2MiB. + +@@ -1075,7 +1078,7 @@ In short: + @item i386-qemu @tab 60 KiB @tab < 4 GiB + @item *-efi @tab ? @tab < 1.6 GiB + @item i386-ieee1275 @tab ? @tab < 32 MiB +-@item powerpc-ieee1275 @tab ? @tab < 32 MiB ++@item powerpc-ieee1275 @tab ? @tab available memory - 128MiB + @item sparc64-ieee1275 @tab 256KiB @tab 2 MiB + @item arm-uboot @tab 256KiB @tab 2 MiB + @item mips(el)-qemu_mips @tab 2MiB @tab 253 MiB diff --git a/SOURCES/0316-ieee1275-implement-vec5-for-cas-negotiation.patch b/SOURCES/0316-ieee1275-implement-vec5-for-cas-negotiation.patch new file mode 100644 index 0000000..fad39db --- /dev/null +++ b/SOURCES/0316-ieee1275-implement-vec5-for-cas-negotiation.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Diego Domingos +Date: Mon, 6 Feb 2023 10:03:23 -0500 +Subject: [PATCH] ieee1275: implement vec5 for cas negotiation + +As a legacy support, if the vector 5 is not implemented, Power Hypervisor will +consider the max CPUs as 64 instead 256 currently supported during +client-architecture-support negotiation. + +This patch implements the vector 5 and set the MAX CPUs to 256 while setting the +others values to 0 (default). + +Signed-off-by: Diego Domingos +Acked-by: Daniel Axtens +Signed-off-by: Stefan Berger +Signed-off-by: Avnish Chouhan +(cherry picked from commit 942f19959fe7465fb52a1da39ff271a7ab704892) +--- + grub-core/kern/ieee1275/init.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 85af8fa97b..72d4fed312 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -502,6 +502,19 @@ struct option_vector2 + grub_uint8_t max_pft_size; + } GRUB_PACKED; + ++struct option_vector5 ++{ ++ grub_uint8_t byte1; ++ grub_uint8_t byte2; ++ grub_uint8_t byte3; ++ grub_uint8_t cmo; ++ grub_uint8_t associativity; ++ grub_uint8_t bin_opts; ++ grub_uint8_t micro_checkpoint; ++ grub_uint8_t reserved0; ++ grub_uint32_t max_cpus; ++} GRUB_PACKED; ++ + struct pvr_entry + { + grub_uint32_t mask; +@@ -523,6 +536,8 @@ struct cas_vector + grub_uint16_t vec3; + grub_uint8_t vec4_size; + grub_uint16_t vec4; ++ grub_uint8_t vec5_size; ++ struct option_vector5 vec5; + } GRUB_PACKED; + + /* +@@ -547,7 +562,7 @@ grub_ieee1275_ibm_cas (void) + struct cas_vector vector = + { + .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ +- .num_vecs = 4 - 1, ++ .num_vecs = 5 - 1, + .vec1_size = 0, + .vec1 = 0x80, /* ignore */ + .vec2_size = 1 + sizeof (struct option_vector2) - 2, +@@ -558,6 +573,10 @@ grub_ieee1275_ibm_cas (void) + .vec3 = 0x00e0, /* ask for FP + VMX + DFP but don't halt if unsatisfied */ + .vec4_size = 2 - 1, + .vec4 = 0x0001, /* set required minimum capacity % to the lowest value */ ++ .vec5_size = 1 + sizeof (struct option_vector5) - 2, ++ .vec5 = { ++ 0, 192, 0, 128, 0, 0, 0, 0, 256 ++ } + }; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); diff --git a/SOURCES/0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch b/SOURCES/0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch new file mode 100644 index 0000000..02c0282 --- /dev/null +++ b/SOURCES/0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch @@ -0,0 +1,246 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Mon, 6 Feb 2023 10:03:25 -0500 +Subject: [PATCH] ibmvtpm: Add support for trusted boot using a vTPM 2.0 + +Add support for trusted boot using a vTPM 2.0 on the IBM IEEE1275 +PowerPC platform. With this patch grub now measures text and binary data +into the TPM's PCRs 8 and 9 in the same way as the x86_64 platform +does. + +This patch requires Daniel Axtens's patches for claiming more memory. + +Note: The tpm_init() function cannot be called from GRUB_MOD_INIT() since +it does not find the device nodes upon module initialization and +therefore the call to tpm_init() must be deferred to grub_tpm_measure(). + +For vTPM support to work on PowerVM, system driver levels 1010.30 +or 1020.00 are required. + +Note: Previous versions of firmware levels with the 2hash-ext-log +API call have a bug that, once this API call is invoked, has the +effect of disabling the vTPM driver under Linux causing an error +message to be displayed in the Linux kernel log. Those users will +have to update their machines to the firmware levels mentioned +above. + +Cc: Eric Snowberg +Signed-off-by: Stefan Berger +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit 2aa5ef83743dfea79377309ff4f5e9c9a55de355) +--- + grub-core/Makefile.core.def | 7 ++ + grub-core/commands/ieee1275/ibmvtpm.c | 155 ++++++++++++++++++++++++++++++++++ + include/grub/ieee1275/ieee1275.h | 3 + + docs/grub.texi | 3 +- + 4 files changed, 167 insertions(+), 1 deletion(-) + create mode 100644 grub-core/commands/ieee1275/ibmvtpm.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index f21da23213..02ea718652 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1175,6 +1175,13 @@ module = { + enable = powerpc_ieee1275; + }; + ++module = { ++ name = tpm; ++ common = commands/tpm.c; ++ ieee1275 = commands/ieee1275/ibmvtpm.c; ++ enable = powerpc_ieee1275; ++}; ++ + module = { + name = terminal; + common = commands/terminal.c; +diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c +new file mode 100644 +index 0000000000..239942d27e +--- /dev/null ++++ b/grub-core/commands/ieee1275/ibmvtpm.c +@@ -0,0 +1,155 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Free Software Foundation, Inc. ++ * Copyright (C) 2022 IBM Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ * ++ * IBM vTPM support code. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static grub_ieee1275_ihandle_t tpm_ihandle; ++static grub_uint8_t tpm_version; ++ ++#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0) ++ ++static void ++tpm_get_tpm_version (void) ++{ ++ grub_ieee1275_phandle_t vtpm; ++ char buffer[20]; ++ ++ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) && ++ !grub_ieee1275_get_property (vtpm, "compatible", buffer, ++ sizeof (buffer), NULL) && ++ !grub_strcmp (buffer, "IBM,vtpm20")) ++ tpm_version = 2; ++} ++ ++static grub_err_t ++tpm_init (void) ++{ ++ static int init_success = 0; ++ ++ if (!init_success) ++ { ++ if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0) ++ { ++ tpm_ihandle = IEEE1275_IHANDLE_INVALID; ++ return GRUB_ERR_UNKNOWN_DEVICE; ++ } ++ ++ init_success = 1; ++ ++ tpm_get_tpm_version (); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static int ++ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex, ++ grub_uint32_t eventtype, ++ const char *description, ++ grub_size_t description_size, ++ void *buf, grub_size_t size) ++{ ++ struct tpm_2hash_ext_log ++ { ++ struct grub_ieee1275_common_hdr common; ++ grub_ieee1275_cell_t method; ++ grub_ieee1275_cell_t ihandle; ++ grub_ieee1275_cell_t size; ++ grub_ieee1275_cell_t buf; ++ grub_ieee1275_cell_t description_size; ++ grub_ieee1275_cell_t description; ++ grub_ieee1275_cell_t eventtype; ++ grub_ieee1275_cell_t pcrindex; ++ grub_ieee1275_cell_t catch_result; ++ grub_ieee1275_cell_t rc; ++ }; ++ struct tpm_2hash_ext_log args; ++ ++ INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2); ++ args.method = (grub_ieee1275_cell_t) "2hash-ext-log"; ++ args.ihandle = tpm_ihandle; ++ args.pcrindex = pcrindex; ++ args.eventtype = eventtype; ++ args.description = (grub_ieee1275_cell_t) description; ++ args.description_size = description_size; ++ args.buf = (grub_ieee1275_cell_t) buf; ++ args.size = (grub_ieee1275_cell_t) size; ++ ++ if (IEEE1275_CALL_ENTRY_FN (&args) == -1) ++ return -1; ++ ++ /* ++ * catch_result is set if firmware does not support 2hash-ext-log ++ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure ++ */ ++ if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE) ++ return -1; ++ ++ return 0; ++} ++ ++static grub_err_t ++tpm2_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ static int error_displayed = 0; ++ int rc; ++ ++ rc = ibmvtpm_2hash_ext_log (pcr, EV_IPL, ++ description, grub_strlen(description) + 1, ++ buf, size); ++ if (rc && !error_displayed) ++ { ++ error_displayed++; ++ return grub_error (GRUB_ERR_BAD_DEVICE, ++ "2HASH-EXT-LOG failed: Firmware is likely too old.\n"); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ /* ++ * Call tpm_init() 'late' rather than from GRUB_MOD_INIT() so that device nodes ++ * can be found. ++ */ ++ grub_err_t err = tpm_init (); ++ ++ /* Absence of a TPM isn't a failure. */ ++ if (err != GRUB_ERR_NONE) ++ return GRUB_ERR_NONE; ++ ++ grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n", ++ pcr, size, description); ++ ++ if (tpm_version == 2) ++ return tpm2_log_event (buf, size, pcr, description); ++ ++ return GRUB_ERR_NONE; ++} +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index 560c968460..27b9cf259b 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -24,6 +24,9 @@ + #include + #include + ++#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0) ++#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1) ++ + struct grub_ieee1275_mem_region + { + unsigned int start; +diff --git a/docs/grub.texi b/docs/grub.texi +index 1750b72ee9..825278a7f3 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -6235,7 +6235,8 @@ tpm module is loaded. As such it is recommended that the tpm module be built + into @file{core.img} in order to avoid a potential gap in measurement between + @file{core.img} being loaded and the tpm module being loaded. + +-Measured boot is currently only supported on EFI platforms. ++Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC ++platforms. + + @node Lockdown + @section Lockdown when booting on a secure setup diff --git a/SOURCES/0318-powerpc-Drop-Open-Hack-Ware.patch b/SOURCES/0318-powerpc-Drop-Open-Hack-Ware.patch new file mode 100644 index 0000000..1d201d3 --- /dev/null +++ b/SOURCES/0318-powerpc-Drop-Open-Hack-Ware.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Mon, 6 Sep 2021 15:46:11 +1000 +Subject: [PATCH] powerpc: Drop Open Hack'Ware + +Open Hack'Ware was an alternative firmware of powerpc under QEMU. + +The last commit to any Open Hack'Ware repo I can find is from 2014 [1]. + +Open Hack'Ware was used for the QEMU "prep" machine type, which was +deprecated in QEMU in commit 54c86f5a4844 (hw/ppc: deprecate the +machine type 'prep', replaced by '40p') in QEMU v3.1, and had reportedly +been broken for years before without anyone noticing. Support was removed +in February 2020 by commit b2ce76a0730e (hw/ppc/prep: Remove the +deprecated "prep" machine and the OpenHackware BIOS). + +Open Hack'Ware's limitations require some messy code in GRUB. This +complexity is not worth carrying any more. + +Remove detection of Open Hack'Ware. We will clean up the feature flags +in following commits. + +[1]: https://github.com/qemu/openhackware and + https://repo.or.cz/w/openhackware.git are QEMU submodules. They have + only small changes on top of OHW v0.4.1, which was imported into + QEMU SCM in 2010. I can't find anything resembling an official repo + any more. + +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +(cherry picked from commit f9ce538eec88c5cffbfde021c4e8a95a5e9d0e8f) +--- + grub-core/kern/ieee1275/cmain.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c +index dce7b84922..cb42f60ebe 100644 +--- a/grub-core/kern/ieee1275/cmain.c ++++ b/grub-core/kern/ieee1275/cmain.c +@@ -49,7 +49,6 @@ grub_ieee1275_find_options (void) + grub_ieee1275_phandle_t root; + grub_ieee1275_phandle_t options; + grub_ieee1275_phandle_t openprom; +- grub_ieee1275_phandle_t bootrom; + int rc; + grub_uint32_t realmode = 0; + char tmp[256]; +@@ -198,21 +197,6 @@ grub_ieee1275_find_options (void) + + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); + } +- +- if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom) +- || ! grub_ieee1275_finddevice ("/boot-rom", &bootrom)) +- { +- rc = grub_ieee1275_get_property (bootrom, "model", tmp, sizeof (tmp), 0); +- if (rc >= 0 && !grub_strncmp (tmp, "PPC Open Hack'Ware", +- sizeof ("PPC Open Hack'Ware") - 1)) +- { +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM); +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_ANSI); +- } +- } + } + + void diff --git a/SOURCES/0319-osdep-linux-hostdisk-Modify-sector-by-sysfs-as-disk-.patch b/SOURCES/0319-osdep-linux-hostdisk-Modify-sector-by-sysfs-as-disk-.patch new file mode 100644 index 0000000..6e7b17f --- /dev/null +++ b/SOURCES/0319-osdep-linux-hostdisk-Modify-sector-by-sysfs-as-disk-.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mukesh Kumar Chaurasiya +Date: Thu, 9 Feb 2023 13:09:16 +0530 +Subject: [PATCH] osdep/linux/hostdisk: Modify sector by sysfs as disk sector + +The disk sector size provided by sysfs file system considers the sector +size of 512 irrespective of disk sector size, thus causing the read by +the GRUB to an incorrect offset from what was originally intended. + +Considering the 512 sector size of sysfs data the actual sector needs to +be modified corresponding to disk sector size. + +Signed-off-by: Mukesh Kumar Chaurasiya +Reviewed-by: Daniel Kiper +(cherry picked from commit f7564844f82b57078d601befadc438b5bc1fa01b) +--- + grub-core/osdep/linux/hostdisk.c | 7 ++++--- + include/grub/disk.h | 7 +++++++ + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/grub-core/osdep/linux/hostdisk.c b/grub-core/osdep/linux/hostdisk.c +index 7bc99ac1c1..a9ea0bb465 100644 +--- a/grub-core/osdep/linux/hostdisk.c ++++ b/grub-core/osdep/linux/hostdisk.c +@@ -240,7 +240,8 @@ have_devfs (void) + #pragma GCC diagnostic ignored "-Wformat-nonliteral" + + static int +-grub_hostdisk_linux_find_partition (char *dev, grub_disk_addr_t sector) ++grub_hostdisk_linux_find_partition (const grub_disk_t disk, char *dev, ++ grub_disk_addr_t sector) + { + size_t len = strlen (dev); + const char *format; +@@ -305,7 +306,7 @@ grub_hostdisk_linux_find_partition (char *dev, grub_disk_addr_t sector) + if (fstat (fd, &st) < 0 + || !grub_util_device_is_mapped_stat (&st) + || !grub_util_get_dm_node_linear_info (st.st_rdev, 0, 0, &start)) +- start = grub_util_find_partition_start_os (real_dev); ++ start = grub_disk_to_native_sector (disk, grub_util_find_partition_start_os (real_dev)); + /* We don't care about errors here. */ + grub_errno = GRUB_ERR_NONE; + +@@ -386,7 +387,7 @@ grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int f + && strncmp (dev, "/dev/", 5) == 0) + { + if (sector >= part_start) +- is_partition = grub_hostdisk_linux_find_partition (dev, part_start); ++ is_partition = grub_hostdisk_linux_find_partition (disk, dev, part_start); + else + *max = part_start - sector; + } +diff --git a/include/grub/disk.h b/include/grub/disk.h +index 06210a7049..881addcc77 100644 +--- a/include/grub/disk.h ++++ b/include/grub/disk.h +@@ -208,6 +208,13 @@ grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector) + return sector << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); + } + ++/* Convert from GRUB native disk sized sector to disk sized sector. */ ++static inline grub_disk_addr_t ++grub_disk_to_native_sector (grub_disk_t disk, grub_disk_addr_t sector) ++{ ++ return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); ++} ++ + /* This is called from the memory manager. */ + void grub_disk_cache_invalidate_all (void); + diff --git a/SOURCES/0320-mm-Adjust-new-region-size-to-take-management-overhea.patch b/SOURCES/0320-mm-Adjust-new-region-size-to-take-management-overhea.patch new file mode 100644 index 0000000..456f8f7 --- /dev/null +++ b/SOURCES/0320-mm-Adjust-new-region-size-to-take-management-overhea.patch @@ -0,0 +1,145 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sun, 29 Jan 2023 19:49:31 +0800 +Subject: [PATCH] mm: Adjust new region size to take management overhead into + account + +When grub_memalign() encounters out-of-memory, it will try +grub_mm_add_region_fn() to request more memory from system firmware. +However, the size passed to it doesn't take region management overhead +into account. Adding a memory area of "size" bytes may result in a heap +region of less than "size" bytes really available. Thus, the new region +may not be adequate for current allocation request, confusing +out-of-memory handling code. + +This patch introduces GRUB_MM_MGMT_OVERHEAD to address the region +management overhead (e.g. metadata, padding). The value of this new +constant must be large enough to make sure grub_memalign(align, size) +always succeeds after a successful call to + grub_mm_init_region(addr, size + align + GRUB_MM_MGMT_OVERHEAD), +for any given addr and size (assuming no integer overflow). + +The size passed to grub_mm_add_region_fn() is now correctly adjusted, +thus if grub_mm_add_region_fn() succeeded, current allocation request +can always succeed. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 2282cbfe5aa1ff6c1bbcbdcd2003089ad7c03ba3) +--- + grub-core/kern/mm.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 61 insertions(+), 3 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index da1ac9427c..f29a3e5cbd 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -83,6 +83,46 @@ + + + ++/* ++ * GRUB_MM_MGMT_OVERHEAD is an upper bound of management overhead of ++ * each region, with any possible padding taken into account. ++ * ++ * The value must be large enough to make sure grub_memalign(align, size) ++ * always succeeds after a successful call to ++ * grub_mm_init_region(addr, size + align + GRUB_MM_MGMT_OVERHEAD), ++ * for any given addr, align and size (assuming no interger overflow). ++ * ++ * The worst case which has maximum overhead is shown in the figure below: ++ * ++ * +-- addr ++ * v |<- size + align ->| ++ * +---------+----------------+----------------+------------------+---------+ ++ * | padding | grub_mm_region | grub_mm_header | usable bytes | padding | ++ * +---------+----------------+----------------+------------------+---------+ ++ * |<- a ->|<- b ->|<- c ->|<- d ->|<- e ->| ++ * ^ ++ * b == sizeof (struct grub_mm_region) | / Assuming no other suitable ++ * c == sizeof (struct grub_mm_header) | | block is available, then: ++ * d == size + align +-| If align == 0, this will be ++ * | the pointer returned by next ++ * Assuming addr % GRUB_MM_ALIGN == 1, then: | grub_memalign(align, size). ++ * a == GRUB_MM_ALIGN - 1 | If align > 0, this chunk may ++ * | need to be split to fulfill ++ * Assuming d % GRUB_MM_ALIGN == 1, then: | alignment requirements, and ++ * e == GRUB_MM_ALIGN - 1 | the returned pointer may be ++ * \ inside these usable bytes. ++ * Therefore, the maximum overhead is: ++ * a + b + c + e == (GRUB_MM_ALIGN - 1) + sizeof (struct grub_mm_region) ++ * + sizeof (struct grub_mm_header) + (GRUB_MM_ALIGN - 1) ++ */ ++#define GRUB_MM_MGMT_OVERHEAD ((GRUB_MM_ALIGN - 1) \ ++ + sizeof (struct grub_mm_region) \ ++ + sizeof (struct grub_mm_header) \ ++ + (GRUB_MM_ALIGN - 1)) ++ ++/* The size passed to grub_mm_add_region_fn() is aligned up by this value. */ ++#define GRUB_MM_HEAP_GROW_ALIGN 4096 ++ + grub_mm_region_t grub_mm_base; + grub_mm_add_region_func_t grub_mm_add_region_fn; + +@@ -230,6 +270,11 @@ grub_mm_init_region (void *addr, grub_size_t size) + + grub_dprintf ("regions", "No: considering a new region at %p of size %" PRIxGRUB_SIZE "\n", + addr, size); ++ /* ++ * If you want to modify the code below, please also take a look at ++ * GRUB_MM_MGMT_OVERHEAD and make sure it is synchronized with the code. ++ */ ++ + /* Allocate a region from the head. */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); + +@@ -410,6 +455,7 @@ grub_memalign (grub_size_t align, grub_size_t size) + { + grub_mm_region_t r; + grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1; ++ grub_size_t grow; + int count = 0; + + if (!grub_mm_base) +@@ -418,10 +464,22 @@ grub_memalign (grub_size_t align, grub_size_t size) + if (size > ~(grub_size_t) align) + goto fail; + ++ /* ++ * Pre-calculate the necessary size of heap growth (if applicable), ++ * with region management overhead taken into account. ++ */ ++ if (grub_add (size + align, GRUB_MM_MGMT_OVERHEAD, &grow)) ++ goto fail; ++ ++ /* Align up heap growth to make it friendly to CPU/MMU. */ ++ if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1)) ++ goto fail; ++ grow = ALIGN_UP (grow, GRUB_MM_HEAP_GROW_ALIGN); ++ + /* We currently assume at least a 32-bit grub_size_t, + so limiting allocations to - 1MiB + in name of sanity is beneficial. */ +- if ((size + align) > ~(grub_size_t) 0x100000) ++ if (grow > ~(grub_size_t) 0x100000) + goto fail; + + align = (align >> GRUB_MM_ALIGN_LOG2); +@@ -447,7 +505,7 @@ grub_memalign (grub_size_t align, grub_size_t size) + count++; + + if (grub_mm_add_region_fn != NULL && +- grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) ++ grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) + goto again; + + /* fallthrough */ +@@ -462,7 +520,7 @@ grub_memalign (grub_size_t align, grub_size_t size) + * Try again even if this fails, in case it was able to partially + * satisfy the request + */ +- grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE); ++ grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_NONE); + goto again; + } + diff --git a/SOURCES/0321-mm-Preallocate-some-space-when-adding-new-regions.patch b/SOURCES/0321-mm-Preallocate-some-space-when-adding-new-regions.patch new file mode 100644 index 0000000..291092d --- /dev/null +++ b/SOURCES/0321-mm-Preallocate-some-space-when-adding-new-regions.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sun, 29 Jan 2023 19:49:32 +0800 +Subject: [PATCH] mm: Preallocate some space when adding new regions + +When grub_memalign() encounters out-of-memory, it will try +grub_mm_add_region_fn() to request more memory from system firmware. +However, it doesn't preallocate memory space for future allocation +requests. In extreme cases, it requires one call to +grub_mm_add_region_fn() for each memory allocation request. This can +be very slow. + +This patch introduces GRUB_MM_HEAP_GROW_EXTRA, the minimal heap growth +granularity. The new region size is now set to the bigger one of its +original value and GRUB_MM_HEAP_GROW_EXTRA. Thus, it will result in some +memory space preallocated if current allocations request is small. + +The value of GRUB_MM_HEAP_GROW_EXTRA is set to 1MB. If this value is +smaller, the cost of small memory allocations will be higher. If this +value is larger, more memory will be wasted and it might cause +out-of-memory on machines with small amount of RAM. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 21869baec15239b6d99122b32b14a778af4c754f) +--- + grub-core/kern/mm.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index f29a3e5cbd..cc8a4703bc 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -123,6 +123,9 @@ + /* The size passed to grub_mm_add_region_fn() is aligned up by this value. */ + #define GRUB_MM_HEAP_GROW_ALIGN 4096 + ++/* Minimal heap growth granularity when existing heap space is exhausted. */ ++#define GRUB_MM_HEAP_GROW_EXTRA 0x100000 ++ + grub_mm_region_t grub_mm_base; + grub_mm_add_region_func_t grub_mm_add_region_fn; + +@@ -471,6 +474,9 @@ grub_memalign (grub_size_t align, grub_size_t size) + if (grub_add (size + align, GRUB_MM_MGMT_OVERHEAD, &grow)) + goto fail; + ++ /* Preallocate some extra space if heap growth is small. */ ++ grow = grub_max (grow, GRUB_MM_HEAP_GROW_EXTRA); ++ + /* Align up heap growth to make it friendly to CPU/MMU. */ + if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1)) + goto fail; diff --git a/SOURCES/0322-mm-Avoid-complex-heap-growth-math-in-hot-path.patch b/SOURCES/0322-mm-Avoid-complex-heap-growth-math-in-hot-path.patch new file mode 100644 index 0000000..fe6b3e1 --- /dev/null +++ b/SOURCES/0322-mm-Avoid-complex-heap-growth-math-in-hot-path.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zhang Boyang +Date: Sun, 29 Jan 2023 19:49:33 +0800 +Subject: [PATCH] mm: Avoid complex heap growth math in hot path + +We do a lot of math about heap growth in hot path of grub_memalign(). +However, the result is only used if out of memory is encountered, which +is seldom. + +This patch moves these calculations away from hot path. These +calculations are now only done if out of memory is encountered. This +change can also help compiler to optimize integer overflow checks away. + +Signed-off-by: Zhang Boyang +Reviewed-by: Daniel Kiper +(cherry picked from commit 65bc45963014773e2062ccc63ff34a089d2e352e) +--- + grub-core/kern/mm.c | 34 ++++++++++++++++++++-------------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index cc8a4703bc..630d7be0e2 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -467,20 +467,7 @@ grub_memalign (grub_size_t align, grub_size_t size) + if (size > ~(grub_size_t) align) + goto fail; + +- /* +- * Pre-calculate the necessary size of heap growth (if applicable), +- * with region management overhead taken into account. +- */ +- if (grub_add (size + align, GRUB_MM_MGMT_OVERHEAD, &grow)) +- goto fail; +- +- /* Preallocate some extra space if heap growth is small. */ +- grow = grub_max (grow, GRUB_MM_HEAP_GROW_EXTRA); +- +- /* Align up heap growth to make it friendly to CPU/MMU. */ +- if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1)) +- goto fail; +- grow = ALIGN_UP (grow, GRUB_MM_HEAP_GROW_ALIGN); ++ grow = size + align; + + /* We currently assume at least a 32-bit grub_size_t, + so limiting allocations to - 1MiB +@@ -510,6 +497,25 @@ grub_memalign (grub_size_t align, grub_size_t size) + /* Request additional pages, contiguous */ + count++; + ++ /* ++ * Calculate the necessary size of heap growth (if applicable), ++ * with region management overhead taken into account. ++ */ ++ if (grub_add (grow, GRUB_MM_MGMT_OVERHEAD, &grow)) ++ goto fail; ++ ++ /* Preallocate some extra space if heap growth is small. */ ++ grow = grub_max (grow, GRUB_MM_HEAP_GROW_EXTRA); ++ ++ /* Align up heap growth to make it friendly to CPU/MMU. */ ++ if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1)) ++ goto fail; ++ grow = ALIGN_UP (grow, GRUB_MM_HEAP_GROW_ALIGN); ++ ++ /* Do the same sanity check again. */ ++ if (grow > ~(grub_size_t) 0x100000) ++ goto fail; ++ + if (grub_mm_add_region_fn != NULL && + grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) + goto again; diff --git a/SOURCES/701-ca.cer b/SOURCES/701-ca.cer deleted file mode 100644 index 0e6e79b..0000000 Binary files a/SOURCES/701-ca.cer and /dev/null differ diff --git a/SOURCES/701-cer.cer b/SOURCES/701-cer.cer deleted file mode 100644 index 25e3743..0000000 Binary files a/SOURCES/701-cer.cer and /dev/null differ diff --git a/SOURCES/grub.macros b/SOURCES/grub.macros index 62ed7b6..4a2883d 100755 --- a/SOURCES/grub.macros +++ b/SOURCES/grub.macros @@ -9,11 +9,14 @@ %global _configure ../configure %if %{?_with_ccache: 1}%{?!_with_ccache: 0} -%global cc_equals CC=/usr/%{_lib}/ccache/gcc +%global ccpath /usr/%{_lib}/ccache/gcc %else -%global cc_equals %{nil} +%global ccpath %{__cc} %endif +# gnulib actively ignores CFLAGS because it's terrible +%global cc_equals "CC=%{ccpath} -fPIE -Wl,-z,noexecstack" + %global cflags_sed \\\ sed \\\ -e 's/-O. //g' \\\ @@ -122,7 +125,7 @@ %endif %ifarch ppc64le -%global platform_modules " appendedsig tpm " +%global platform_modules " appendedsig ofnet tpm " %endif %ifarch aarch64 %{arm} riscv64 @@ -322,6 +325,7 @@ git commit -a -q -m "%{tarversion} baseline." \ #git apply --index --whitespace=nowarn %{SOURCE3} \ #git commit -a -q -m "%{tarversion} master." \ git am --whitespace=nowarn %%{patches} - 2.06-46.el9.centos.3 -- Apply debranding changes +* Mon Mar 27 2023 Robbie Harwood - 2.06-46.el9_1.5 +- Sync (actually 2.06-61) +- Resolves: #2181506 + +* Tue Feb 07 2023 Robbie Harwood - 2.06-46.el9_1.4 +- Sync with 9.2 (actually 2.06-58) +- Resolves: #2156419 * Fri Nov 11 2022 Robbie Harwood - 2.06-46.el9_1.3 - Give up on redhat-sb-certs