From 820919e0251a13cb7c5cc23b43b183ee97cdeb85 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 24 Jun 2025 14:25:41 +1200 Subject: [PATCH 01/15] kernel: Add upstream patch to handle empty object files With newer versions of binutils we can end up with completely empty object files. This upsets objtool which expects to find a valid symbol table resulting in the following error arch/x86/entry/thunk_64.o: warning: objtool: missing symbol table Bring in an upstream change that allows these and continues. Signed-off-by: Chris Packham --- ...l-Don-t-fail-on-missing-symbol-table.patch | 49 +++++++++++++++++++ patches/kernel/5.4.86/series | 1 + 2 files changed, 50 insertions(+) create mode 100644 patches/kernel/5.4.86/objtool-Don-t-fail-on-missing-symbol-table.patch diff --git a/patches/kernel/5.4.86/objtool-Don-t-fail-on-missing-symbol-table.patch b/patches/kernel/5.4.86/objtool-Don-t-fail-on-missing-symbol-table.patch new file mode 100644 index 000000000..445f4ccd8 --- /dev/null +++ b/patches/kernel/5.4.86/objtool-Don-t-fail-on-missing-symbol-table.patch @@ -0,0 +1,49 @@ +From 2d7ca4a84b589210b633b3c2f2c0b8fc627c97c7 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Thu, 14 Jan 2021 16:14:01 -0600 +Subject: [PATCH] objtool: Don't fail on missing symbol table + +[ Upstream commit 1d489151e9f9d1647110277ff77282fe4d96d09b ] + +Thanks to a recent binutils change which doesn't generate unused +symbols, it's now possible for thunk_64.o be completely empty without +CONFIG_PREEMPTION: no text, no data, no symbols. + +We could edit the Makefile to only build that file when +CONFIG_PREEMPTION is enabled, but that will likely create confusion +if/when the thunks end up getting used by some other code again. + +Just ignore it and move on. + +Reported-by: Nathan Chancellor +Reviewed-by: Nathan Chancellor +Reviewed-by: Miroslav Benes +Tested-by: Nathan Chancellor +Link: https://github.com/ClangBuiltLinux/linux/issues/1254 +Signed-off-by: Josh Poimboeuf +Signed-off-by: Sasha Levin +--- + tools/objtool/elf.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c +index edba4745f25a..693d740107a8 100644 +--- a/tools/objtool/elf.c ++++ b/tools/objtool/elf.c +@@ -214,8 +214,11 @@ static int read_symbols(struct elf *elf) + + symtab = find_section_by_name(elf, ".symtab"); + if (!symtab) { +- WARN("missing symbol table"); +- return -1; ++ /* ++ * A missing symbol table is actually possible if it's an empty ++ * .o file. This can happen for thunk_64.o. ++ */ ++ return 0; + } + + symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize; +-- +2.49.0 + diff --git a/patches/kernel/5.4.86/series b/patches/kernel/5.4.86/series index e69de29bb..6ed1737c2 100644 --- a/patches/kernel/5.4.86/series +++ b/patches/kernel/5.4.86/series @@ -0,0 +1 @@ +objtool-Don-t-fail-on-missing-symbol-table.patch From 3c968fa36163390160fb0b9fb1449cb6ef089c36 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 28 Oct 2025 17:30:27 +1300 Subject: [PATCH 02/15] busybox: Update sys_eeprom cmd_usage() GCC 15 will switch to C23 by default which causes some old style function definitions to generate errors because they are interpreted differently. Add the missing return type and arguments to cmd_usage() in sys_eeprom.c to comply with C23. Signed-off-by: Chris Packham --- patches/busybox/feature-onie-syseeprom-command.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/busybox/feature-onie-syseeprom-command.patch b/patches/busybox/feature-onie-syseeprom-command.patch index 88bbcf3ae..56bba844f 100644 --- a/patches/busybox/feature-onie-syseeprom-command.patch +++ b/patches/busybox/feature-onie-syseeprom-command.patch @@ -1687,7 +1687,7 @@ index 0000000..26b6ec5 +} diff --git a/miscutils/sys_eeprom.c b/miscutils/sys_eeprom.c new file mode 100644 -index 0000000..a24d6bb +index 0000000..ed3fb38 --- /dev/null +++ b/miscutils/sys_eeprom.c @@ -0,0 +1,188 @@ @@ -1711,7 +1711,7 @@ index 0000000..a24d6bb +//usage: "\n If no value, TLV is deleted." +//usage: "\n" + -+cmd_usage() ++void cmd_usage(void) +{ + static const char *usage = + "Display and program the system EEPROM data block.\n" From 0d57fcc9f2de2c622659cdbcfb089f28c5e27d99 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 29 Oct 2025 08:53:55 +1300 Subject: [PATCH 03/15] kexec-tools: Remove unused patches These patches have been unused since commit f1d5ec18 ("kexec-tools - upgrade from 2.0.9 to 2.0.22"). Drop them from the repository. Signed-off-by: Chris Packham --- ...mprove-device-tree-directory-sorting.patch | 84 -- ...5-25-kexec-tools-add-aarch64-support.patch | 828 ------------------ patches/kexec-tools/series | 6 - 3 files changed, 918 deletions(-) delete mode 100644 patches/kexec-tools/0001-Improve-device-tree-directory-sorting.patch delete mode 100644 patches/kexec-tools/15-25-kexec-tools-add-aarch64-support.patch diff --git a/patches/kexec-tools/0001-Improve-device-tree-directory-sorting.patch b/patches/kexec-tools/0001-Improve-device-tree-directory-sorting.patch deleted file mode 100644 index 243ef57c3..000000000 --- a/patches/kexec-tools/0001-Improve-device-tree-directory-sorting.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0e1030b345b9e7c1c64b85dde32a282a19b825f0 Mon Sep 17 00:00:00 2001 -From: Curt Brune -Date: Tue, 24 Nov 2015 18:17:10 -0800 -Subject: [PATCH 1/1] Improve device tree directory sorting - -Previously when sorting the device tree directory entries, if both -device tree entries contained the '@' character then comparison was -made based on the length of the strings. - -This did not work in all cases and could result in odd orderings. - -This patch modifies the comparison function for the case when both -strings contain the '@' character. - -First a lexical comparison is made between the prefix portions of the -strings *before* the '@' character. - -Next, if the prefixes are equal, the lengths of the suffixes *after* -the '@' character are compared. This preserves the intent of the -original code. - -Next, if the suffix lengths are equal, a lexical comparison of the -suffixes is made. - -This is still not strictly correct, as ideally the portion after the -'@' should be compared numerically. However, determining what base to -use for all case is difficult. - -Signed-off-by: Curt Brune -Signed-off-by: Simon Horman ---- - kexec/arch/ppc/fs2dt.c | 21 +++++++++++++++++---- - 1 file changed, 17 insertions(+), 4 deletions(-) - -diff --git a/kexec/arch/ppc/fs2dt.c b/kexec/arch/ppc/fs2dt.c -index 4121c7d..6e77379 100644 ---- a/kexec/arch/ppc/fs2dt.c -+++ b/kexec/arch/ppc/fs2dt.c -@@ -30,6 +30,7 @@ - #include - #include "../../kexec.h" - #include "kexec-ppc.h" -+#include "types.h" - - #define MAXPATH 1024 /* max path name length */ - #define NAMESPACE 16384 /* max bytes for property names */ -@@ -296,6 +297,8 @@ static int comparefunc(const void *dentry1, const void *dentry2) - { - char *str1 = (*(struct dirent **)dentry1)->d_name; - char *str2 = (*(struct dirent **)dentry2)->d_name; -+ char *p1, *p2; -+ int res = 0, max_len; - - /* - * strcmp scans from left to right and fails to idetify for some -@@ -303,11 +306,21 @@ static int comparefunc(const void *dentry1, const void *dentry2) - * Therefore, we get the wrong sorted order like memory@10000000 and - * memory@f000000. - */ -- if (strchr(str1, '@') && strchr(str2, '@') && -- (strlen(str1) > strlen(str2))) -- return 1; -+ if ((p1 = strchr(str1, '@')) && (p2 = strchr(str2, '@'))) { -+ max_len = max(p1 - str1, p2 - str2); -+ if ((res = strncmp(str1, str2, max_len)) == 0) { -+ /* prefix is equal - compare part after '@' by length */ -+ p1++; p2++; -+ res = strlen(p1) - strlen(p2); -+ if (res == 0) -+ /* equal length, compare by strcmp() */ -+ res = strcmp(p1,p2); -+ } -+ } else { -+ res = strcmp(str1, str2); -+ } - -- return strcmp(str1, str2); -+ return res; - } - - /* --- -1.9.1 - diff --git a/patches/kexec-tools/15-25-kexec-tools-add-aarch64-support.patch b/patches/kexec-tools/15-25-kexec-tools-add-aarch64-support.patch deleted file mode 100644 index 1a7c2a9ad..000000000 --- a/patches/kexec-tools/15-25-kexec-tools-add-aarch64-support.patch +++ /dev/null @@ -1,828 +0,0 @@ -Subject: [PATCH 1/1] From: Geoff Levand Date: Mon, 15 - Jul 2013 23:32:36 +0000 (-0700) Subject: Add arm64 support X-Git-Url: - https://git.linaro.org/gitweb?p=people%2Fgeoff%2Fkexec-tools.git;a=commitdiff_plain;h=fbf5ac6c2c70ec0f6da2b9ff563e573999752c01 - -Add arm64 support - -Signed-off-by: Geoff Levand - -Get patch from: -https://fedorapeople.org/~hrw/aarch64/for-fedora/kexec-aarch64.patch - -Signed-off-by: Kai Kang ---- - configure | 3 + - configure.ac | 3 + - kexec/Makefile | 1 + - kexec/arch/arm64/Makefile | 13 ++ - kexec/arch/arm64/crashdump-arm64.c | 305 ++++++++++++++++++++++++++++++++ - kexec/arch/arm64/include/arch/options.h | 26 +++ - kexec/arch/arm64/kexec-arm64.c | 177 ++++++++++++++++++ - kexec/arch/arm64/kexec-arm64.h | 20 +++ - kexec/arch/arm64/kexec-elf-arm64.c | 114 ++++++++++++ - kexec/kexec-syscall.h | 7 +- - kexec/kexec.c | 4 +- - purgatory/arch/arm64/Makefile | 7 + - 12 files changed, 678 insertions(+), 2 deletions(-) - create mode 100644 kexec/arch/arm64/Makefile - create mode 100644 kexec/arch/arm64/crashdump-arm64.c - create mode 100644 kexec/arch/arm64/include/arch/options.h - create mode 100644 kexec/arch/arm64/kexec-arm64.c - create mode 100644 kexec/arch/arm64/kexec-arm64.h - create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c - create mode 100644 purgatory/arch/arm64/Makefile - -diff --git a/configure b/configure -index 94a429c..1b59cdf 100755 ---- a/configure -+++ b/configure -@@ -2195,6 +2195,9 @@ case $target_cpu in - ARCH="ppc64" - SUBARCH="LE" - ;; -+ aarch64 ) -+ ARCH="arm64" -+ ;; - arm* ) - ARCH="arm" - ;; -diff --git a/configure.ac b/configure.ac -index 94f3018..c815f34 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -35,6 +35,9 @@ case $target_cpu in - ARCH="ppc64" - SUBARCH="LE" - ;; -+ aarch64 ) -+ ARCH="arm64" -+ ;; - arm* ) - ARCH="arm" - ;; -diff --git a/kexec/Makefile b/kexec/Makefile -index a758b4a..8bc6d08 100644 ---- a/kexec/Makefile -+++ b/kexec/Makefile -@@ -71,6 +71,7 @@ KEXEC_SRCS += $($(ARCH)_FS2DT) - - include $(srcdir)/kexec/arch/alpha/Makefile - include $(srcdir)/kexec/arch/arm/Makefile -+include $(srcdir)/kexec/arch/arm64/Makefile - include $(srcdir)/kexec/arch/i386/Makefile - include $(srcdir)/kexec/arch/ia64/Makefile - include $(srcdir)/kexec/arch/m68k/Makefile -diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile -new file mode 100644 -index 0000000..639805a ---- /dev/null -+++ b/kexec/arch/arm64/Makefile -@@ -0,0 +1,13 @@ -+arm64_KEXEC_SRCS += \ -+ kexec/arch/arm64/kexec-arm64.c \ -+ kexec/arch/arm64/kexec-elf-arm64.c \ -+ kexec/arch/arm64/crashdump-arm64.c -+ -+arm64_ARCH_REUSE_INITRD = -+arm64_ADD_SEGMENT = -+arm64_VIRT_TO_PHYS = -+ -+dist += $(arm64_KEXEC_SRCS) \ -+ kexec/arch/arm64/Makefile \ -+ kexec/arch/arm64/kexec-arm64.h -+ -diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c -new file mode 100644 -index 0000000..bb1b8bd ---- /dev/null -+++ b/kexec/arch/arm64/crashdump-arm64.c -@@ -0,0 +1,305 @@ -+/* -+ * 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 (version 2 of the License). -+ */ -+ -+#include "../../kexec.h" -+#include "../../kexec-elf.h" -+#include "../../crashdump.h" -+ -+int is_crashkernel_mem_reserved(void) -+{ -+ return 0; -+} -+ -+#if 0 -+/* -+ * Used to save various memory ranges/regions needed for the captured -+ * kernel to boot. (lime memmap= option in other archs) -+ */ -+static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES]; -+struct memory_ranges usablemem_rgns = { -+ .size = 0, -+ .ranges = crash_memory_ranges, -+}; -+ -+/* memory range reserved for crashkernel */ -+static struct memory_range crash_reserved_mem; -+ -+static struct crash_elf_info elf_info = { -+ .class = ELFCLASS32, -+ .data = ELFDATA2LSB, -+ .machine = EM_ARM, -+ .page_offset = PAGE_OFFSET, -+}; -+ -+unsigned long phys_offset; -+ -+/** -+ * crash_range_callback() - callback called for each iomem region -+ * @data: not used -+ * @nr: not used -+ * @str: name of the memory region -+ * @base: start address of the memory region -+ * @length: size of the memory region -+ * -+ * This function is called once for each memory region found in /proc/iomem. It -+ * locates system RAM and crashkernel reserved memory and places these to -+ * variables: @crash_memory_ranges and @crash_reserved_mem. Number of memory -+ * regions is placed in @crash_memory_nr_ranges. -+ */ -+static int crash_range_callback(void *UNUSED(data), int UNUSED(nr), -+ char *str, unsigned long base, -+ unsigned long length) -+{ -+ struct memory_range *range; -+ -+ if (usablemem_rgns.size >= CRASH_MAX_MEMORY_RANGES) -+ return 1; -+ -+ range = usablemem_rgns.ranges + usablemem_rgns.size; -+ -+ if (strncmp(str, "System RAM\n", 11) == 0) { -+ range->start = base; -+ range->end = base + length - 1; -+ range->type = RANGE_RAM; -+ usablemem_rgns.size++; -+ } else if (strncmp(str, "Crash kernel\n", 13) == 0) { -+ crash_reserved_mem.start = base; -+ crash_reserved_mem.end = base + length - 1; -+ crash_reserved_mem.type = RANGE_RAM; -+ } -+ -+ return 0; -+} -+ -+/** -+ * crash_exclude_range() - excludes memory region reserved for crashkernel -+ * -+ * Function locates where crashkernel reserved memory is and removes that region -+ * from the available memory regions. -+ */ -+static void crash_exclude_range(void) -+{ -+ const struct memory_range *range = &crash_reserved_mem; -+ int i; -+ -+ for (i = 0; i < usablemem_rgns.size; i++) { -+ struct memory_range *r = usablemem_rgns.ranges + i; -+ -+ /* -+ * We assume that crash area is fully contained in -+ * some larger memory area. -+ */ -+ if (r->start <= range->start && r->end >= range->end) { -+ struct memory_range *new; -+ /* -+ * Let's split this area into 2 smaller ones and -+ * remove excluded range from between. First create -+ * new entry for the remaining area. -+ */ -+ new = usablemem_rgns.ranges + usablemem_rgns.size; -+ new->start = range->end + 1; -+ new->end = r->end; -+ usablemem_rgns.size++; -+ /* -+ * Next update this area to end before excluded range. -+ */ -+ r->end = range->start - 1; -+ break; -+ } -+ } -+} -+ -+static int range_cmp(const void *a1, const void *a2) -+{ -+ const struct memory_range *r1 = a1; -+ const struct memory_range *r2 = a2; -+ -+ if (r1->start > r2->start) -+ return 1; -+ if (r1->start < r2->start) -+ return -1; -+ -+ return 0; -+} -+ -+/** -+ * crash_get_memory_ranges() - read system physical memory -+ * -+ * Function reads through system physical memory and stores found memory regions -+ * in @crash_memory_ranges. Number of memory regions found is placed in -+ * @crash_memory_nr_ranges. Regions are sorted in ascending order. -+ * -+ * Returns %0 in case of success and %-1 otherwise (errno is set). -+ */ -+static int crash_get_memory_ranges(void) -+{ -+ /* -+ * First read all memory regions that can be considered as -+ * system memory including the crash area. -+ */ -+ kexec_iomem_for_each_line(NULL, crash_range_callback, NULL); -+ -+ if (usablemem_rgns.size < 1) { -+ errno = EINVAL; -+ return -1; -+ } -+ -+ /* -+ * Exclude memory reserved for crashkernel (this may result a split memory -+ * region). -+ */ -+ crash_exclude_range(); -+ -+ /* -+ * Make sure that the memory regions are sorted. -+ */ -+ qsort(usablemem_rgns.ranges, usablemem_rgns.size, -+ sizeof(*usablemem_rgns.ranges), range_cmp); -+ -+ return 0; -+} -+ -+/** -+ * cmdline_add_elfcorehdr() - adds elfcorehdr= to @cmdline -+ * @cmdline: buffer where parameter is placed -+ * @elfcorehdr: physical address of elfcorehdr -+ * -+ * Function appends 'elfcorehdr=start' at the end of the command line given in -+ * @cmdline. Note that @cmdline must be at least %COMMAND_LINE_SIZE bytes long -+ * (inclunding %NUL). -+ */ -+static void cmdline_add_elfcorehdr(char *cmdline, unsigned long elfcorehdr) -+{ -+ char buf[COMMAND_LINE_SIZE]; -+ int buflen; -+ -+ buflen = snprintf(buf, sizeof(buf), "%s elfcorehdr=%#lx", -+ cmdline, elfcorehdr); -+ if (buflen < 0) -+ die("Failed to construct elfcorehdr= command line parameter\n"); -+ if (buflen >= sizeof(buf)) -+ die("Command line overflow\n"); -+ -+ (void) strncpy(cmdline, buf, COMMAND_LINE_SIZE); -+ cmdline[COMMAND_LINE_SIZE - 1] = '\0'; -+} -+ -+/** -+ * cmdline_add_mem() - adds mem= parameter to kernel command line -+ * @cmdline: buffer where parameter is placed -+ * @size: size of the kernel reserved memory (in bytes) -+ * -+ * This function appends 'mem=size' at the end of the command line given in -+ * @cmdline. Note that @cmdline must be at least %COMMAND_LINE_SIZE bytes long -+ * (including %NUL). -+ */ -+static void cmdline_add_mem(char *cmdline, unsigned long size) -+{ -+ char buf[COMMAND_LINE_SIZE]; -+ int buflen; -+ -+ buflen = snprintf(buf, sizeof(buf), "%s mem=%ldK", cmdline, size >> 10); -+ if (buflen < 0) -+ die("Failed to construct mem= command line parameter\n"); -+ if (buflen >= sizeof(buf)) -+ die("Command line overflow\n"); -+ -+ (void) strncpy(cmdline, buf, COMMAND_LINE_SIZE); -+ cmdline[COMMAND_LINE_SIZE - 1] = '\0'; -+} -+ -+static unsigned long long range_size(const struct memory_range *r) -+{ -+ return r->end - r->start + 1; -+} -+ -+static void dump_memory_ranges(void) -+{ -+ int i; -+ -+ if (!kexec_debug) -+ return; -+ -+ dbgprintf("crashkernel: [%#llx - %#llx] (%ldM)\n", -+ crash_reserved_mem.start, crash_reserved_mem.end, -+ (unsigned long)range_size(&crash_reserved_mem) >> 20); -+ -+ for (i = 0; i < usablemem_rgns.size; i++) { -+ struct memory_range *r = usablemem_rgns.ranges + i; -+ dbgprintf("memory range: [%#llx - %#llx] (%ldM)\n", -+ r->start, r->end, (unsigned long)range_size(r) >> 20); -+ } -+} -+ -+/** -+ * load_crashdump_segments() - loads additional segments needed for kdump -+ * @info: kexec info structure -+ * @mod_cmdline: kernel command line -+ * -+ * This function loads additional segments which are needed for the dump capture -+ * kernel. It also updates kernel command line passed in @mod_cmdline to have -+ * right parameters for the dump capture kernel. -+ * -+ * Return %0 in case of success and %-1 in case of error. -+ */ -+int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline) -+{ -+ unsigned long elfcorehdr; -+ unsigned long bufsz; -+ void *buf; -+ int err; -+ -+ /* -+ * First fetch all the memory (RAM) ranges that we are going to pass to -+ * the crashdump kernel during panic. -+ */ -+ err = crash_get_memory_ranges(); -+ if (err) -+ return err; -+ -+ /* -+ * Now that we have memory regions sorted, we can use first memory -+ * region as PHYS_OFFSET. -+ */ -+ phys_offset = usablemem_rgns.ranges->start; -+ dbgprintf("phys_offset: %#lx\n", phys_offset); -+ -+ err = crash_create_elf32_headers(info, &elf_info, -+ usablemem_rgns.ranges, -+ usablemem_rgns.size, &buf, &bufsz, -+ ELF_CORE_HEADER_ALIGN); -+ if (err) -+ return err; -+ -+ /* -+ * We allocate ELF core header from the end of the memory area reserved -+ * for the crashkernel. We align the header to SECTION_SIZE (which is -+ * 1MB) so that available memory passed in kernel command line will be -+ * aligned to 1MB. This is because kernel create_mapping() wants memory -+ * regions to be aligned to SECTION_SIZE. -+ */ -+ elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 1 << 20, -+ crash_reserved_mem.start, -+ crash_reserved_mem.end, -1, 0); -+ -+ dbgprintf("elfcorehdr: %#lx\n", elfcorehdr); -+ cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr); -+ -+ /* -+ * Add 'mem=size' parameter to dump capture kernel command line. This -+ * prevents the dump capture kernel from using any other memory regions -+ * which belong to the primary kernel. -+ */ -+ cmdline_add_mem(mod_cmdline, elfcorehdr - crash_reserved_mem.start); -+ -+ dump_memory_ranges(); -+ dbgprintf("kernel command line: \"%s\"\n", mod_cmdline); -+ -+ return 0; -+} -+ -+#endif -+ -diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h -new file mode 100644 -index 0000000..04f6451 ---- /dev/null -+++ b/kexec/arch/arm64/include/arch/options.h -@@ -0,0 +1,26 @@ -+#ifndef KEXEC_ARCH_ARM64_OPTIONS_H -+#define KEXEC_ARCH_ARM64_OPTIONS_H -+ -+//#define OPT_ARCH_MAX ((OPT_MAX)+0) -+ -+#define OPT_APPEND ((OPT_MAX)+0) -+#define OPT_RAMDISK ((OPT_MAX)+1) -+#define OPT_DTB ((OPT_MAX)+2) -+ -+#define OPT_ARCH_MAX ((OPT_MAX)+3) -+ -+ -+#define KEXEC_ARCH_OPTIONS \ -+ KEXEC_OPTIONS \ -+ { "append", 1, NULL, OPT_APPEND }, \ -+ { "command-line", 1, NULL, OPT_APPEND }, \ -+ { "dtb", 1, NULL, OPT_DTB }, \ -+ { "initrd", 1, NULL, OPT_RAMDISK }, \ -+ { "ramdisk", 1, NULL, OPT_RAMDISK }, \ -+ -+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */ -+ -+#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS -+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR -+ -+#endif /* KEXEC_ARCH_ARM64_OPTIONS_H */ -diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c -new file mode 100644 -index 0000000..fdb59d8 ---- /dev/null -+++ b/kexec/arch/arm64/kexec-arm64.c -@@ -0,0 +1,177 @@ -+/* -+ *ARM64 kexec support. -+ */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+ -+//#include -+ -+#include "../../kexec.h" -+#include "../../kexec-syscall.h" -+#include "kexec-arm64.h" -+ -+ -+void arch_usage(void) -+{ -+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); -+ -+ printf( -+" --append=STRING Set the kernel command line to STRING.\n" -+" --command-line=STRING Set the kernel command line to STRING.\n" -+" --dtb=FILE Use FILE as the device tree blob.\n" -+" --initrd=FILE Use FILE as the kernel initial ramdisk.\n" -+" --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n"); -+ -+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); -+} -+ -+int arch_process_options(int UNUSED(argc), char **UNUSED(argv)) -+{ -+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); -+ return 0; -+} -+ -+const struct arch_map_entry arches[] = { -+ { "aarch64", KEXEC_ARCH_ARM64 }, -+ { NULL, 0 }, -+}; -+ -+void arch_update_purgatory(struct kexec_info *UNUSED(info)) -+{ -+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); -+} -+ -+unsigned long virt_to_phys(unsigned long addr) -+{ -+ fprintf(stderr, "%s:%d: %016lx -> %016lx\n", __func__, __LINE__, addr, -+ addr + 0x080000000UL); -+ return addr + 0x080000000UL; -+} -+ -+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz, -+ unsigned long base, size_t memsz) -+{ -+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); -+ add_segment_phys_virt(info, buf, bufsz, base, memsz, 1); -+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); -+} -+ -+static int get_memory_ranges_1(struct memory_range **range, int *ranges, -+ unsigned long kexec_flags) -+{ -+ static struct memory_range memory_range[KEXEC_SEGMENT_MAX]; -+ const char *iomem; -+ int range_count = 0; -+ char line[MAX_LINE]; -+ FILE *fp; -+ -+ iomem = proc_iomem(); -+ fp = fopen(iomem, "r"); -+ -+ if (!fp) { -+ fprintf(stderr, "Cannot open %s: %s\n", -+ iomem, strerror(errno)); -+ return -1; -+ } -+ -+ dbgprintf("memory ranges:\n"); -+ -+ while(fgets(line, sizeof(line), fp) != 0) { -+ struct memory_range r; -+ char *str; -+ int consumed; -+ -+ if (range_count >= KEXEC_SEGMENT_MAX) -+ break; -+ -+ if (sscanf(line, "%Lx-%Lx : %n", &r.start, &r.end, &consumed) -+ != 2) -+ continue; -+ -+ str = line + consumed; -+ r.end++; -+ -+ if (memcmp(str, "System RAM\n", 11)) { -+ dbgprintf(" Skip: %016Lx - %016Lx : %s", r.start, r.end, -+ str); -+ continue; -+ } -+ -+ r.type = RANGE_RAM; -+ memory_range[range_count] = r; -+ range_count++; -+ -+ dbgprintf(" Add: %016Lx - %016Lx : %s", r.start, r.end, str); -+ } -+ -+ fclose(fp); -+ *range = memory_range; -+ *ranges = range_count; -+ -+ return 0; -+} -+ -+static int get_memory_ranges_2(struct memory_range **range, int *ranges, -+ unsigned long UNUSED(kexec_flags)) -+{ -+ static struct memory_range memory_range[2]; -+ -+ memory_range[0].start = 0x080000000; -+ memory_range[0].end = 0x100000000; -+ memory_range[0].type = RANGE_RAM; -+ -+ memory_range[1].start = 0x900000000; -+ memory_range[1].end = 0x880000000; -+ memory_range[1].type = RANGE_RAM; -+ -+ *range = memory_range; -+ *ranges = sizeof(memory_range) / sizeof(memory_range[0]); -+ -+ return 0; -+} -+ -+int get_memory_ranges(struct memory_range **range, int *ranges, -+ unsigned long kexec_flags) -+{ -+ /* FIXME: Should get this info from device tree. */ -+ -+ return get_memory_ranges_1(range, ranges, kexec_flags); -+} -+ -+struct file_type file_type[] = { -+ { "elf-arm64", elf_arm64_probe, elf_arm64_load, elf_arm64_usage }, -+}; -+ -+int file_types = sizeof(file_type) / sizeof(file_type[0]); -+ -+int arch_compat_trampoline(struct kexec_info *info) -+{ -+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); -+ return 0; -+} -+ -+void arch_reuse_initrd(void) -+{ -+} -+ -+int machine_verify_elf_rel(struct mem_ehdr *ehdr) -+{ -+ (void)ehdr; -+ -+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); -+ return 0; -+} -+ -+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, -+ void *location, unsigned long address, unsigned long value) -+{ -+ (void)ehdr; -+ (void)r_type; -+ (void)location; -+ (void)address; -+ (void)value; -+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); -+} -diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h -new file mode 100644 -index 0000000..e5bf383 ---- /dev/null -+++ b/kexec/arch/arm64/kexec-arm64.h -@@ -0,0 +1,20 @@ -+/* -+ *ARM64 kexec support. -+ */ -+ -+#if !defined(KEXEC_ARM64_H) -+#define KEXEC_ARM64_H -+ -+/* #include FIXME: this is broken */ -+#include -+ -+#include "../../kexec.h" -+ -+#define KEXEC_SEGMENT_MAX 16 /* FIXME: this should come from */ -+ -+int elf_arm64_probe(const char *buf, off_t len); -+int elf_arm64_load(int argc, char **argv, const char *buf, off_t len, -+ struct kexec_info *info); -+void elf_arm64_usage(void); -+ -+#endif -diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c -new file mode 100644 -index 0000000..72c8687 ---- /dev/null -+++ b/kexec/arch/arm64/kexec-elf-arm64.c -@@ -0,0 +1,114 @@ -+/* -+ *ARM64 kexec support. -+ */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+ -+#include "../../kexec-syscall.h" -+ -+#include "kexec-arm64.h" -+#include "arch/options.h" -+ -+#if !defined(EM_AARCH64) -+# define EM_AARCH64 183 -+#endif -+ -+int elf_arm64_probe(const char *buf, off_t len) -+{ -+ int result; -+ struct mem_ehdr ehdr; -+ -+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); -+ -+ result = build_elf_exec_info(buf, len, &ehdr, 0); -+ -+ if (result < 0) { -+ dbgprintf("Not an ELF executable\n"); -+ goto out; -+ } -+ -+ if (ehdr.e_machine != EM_AARCH64) { -+ dbgprintf("Not an AARCH64 executable\n"); -+ result = -1; -+ goto out; -+ } -+ -+ result = 0; -+ -+out: -+ free_elf_info(&ehdr); -+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); -+ return result; -+} -+ -+int elf_arm64_load(int argc, char **argv, const char *buf, off_t len, -+ struct kexec_info *info) -+{ -+ static const struct option options[] = { -+ KEXEC_ARCH_OPTIONS -+ { 0 } -+ }; -+ static const char short_options[] = KEXEC_OPT_STR ""; -+ const char *command_line = NULL; -+ unsigned int command_line_len = 0; -+ const char *ramdisk = NULL; -+ const char *dtb = NULL; -+ int opt; -+ struct mem_ehdr ehdr; -+ int result; -+ -+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); -+ -+ while ((opt = getopt_long(argc, argv, short_options, options, 0)) -+ != -1) { -+ switch (opt) { -+ default: -+ if (opt < OPT_MAX) /* Ignore core options */ -+ break; -+ case OPT_APPEND: -+ command_line = optarg; -+ command_line_len = strlen(command_line) + 1; -+ break; -+ case OPT_RAMDISK: -+ ramdisk = optarg; -+ break; -+ case OPT_DTB: -+ dtb = optarg; -+ break; -+ } -+ } -+ -+ fprintf(stderr, "%s:%d: command_line: %s\n", __func__, __LINE__, command_line); -+ fprintf(stderr, "%s:%d: ramdisk: %s\n", __func__, __LINE__, ramdisk); -+ fprintf(stderr, "%s:%d: dtb: %s\n", __func__, __LINE__, dtb); -+ -+ if (info->kexec_flags & KEXEC_ON_CRASH) { -+ fprintf(stderr, "kexec: kdump not yet supported on arm64\n"); -+ return -1; -+ } -+ -+ result = build_elf_exec_info(buf, len, &ehdr, 0); -+ -+ if (result < 0) { -+ free_elf_info(&ehdr); -+ fprintf(stderr, "%s:%d: free_elf_info failed\n", __func__, -+ __LINE__); -+ return result; -+ } -+ -+ elf_exec_build_load(info, &ehdr, buf, len, 0); -+ -+ info->entry = (void*)0x80080000UL; // FIXME -+ -+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); -+ return 0; -+} -+ -+void elf_arm64_usage(void) -+{ -+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); -+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); -+} -diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h -index ce2e20b..b66db6c 100644 ---- a/kexec/kexec-syscall.h -+++ b/kexec/kexec-syscall.h -@@ -39,7 +39,7 @@ - #ifdef __s390__ - #define __NR_kexec_load 277 - #endif --#ifdef __arm__ -+#if defined(__arm__) || defined(__arm64__) - #define __NR_kexec_load __NR_SYSCALL_BASE + 347 - #endif - #if defined(__mips__) -@@ -108,6 +108,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd, - #define KEXEC_ARCH_PPC64 (21 << 16) - #define KEXEC_ARCH_IA_64 (50 << 16) - #define KEXEC_ARCH_ARM (40 << 16) -+#define KEXEC_ARCH_ARM64 (183 << 16) -+/* #define KEXEC_ARCH_AARCH64 (183 << 16) */ - #define KEXEC_ARCH_S390 (22 << 16) - #define KEXEC_ARCH_SH (42 << 16) - #define KEXEC_ARCH_MIPS_LE (10 << 16) -@@ -150,6 +152,9 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd, - #if defined(__mips__) - #define KEXEC_ARCH_NATIVE KEXEC_ARCH_MIPS - #endif -+#if defined(__arm64__) -+#define KEXEC_ARCH_NATIVE KEXEC_ARCH_ARM64 -+#endif - #ifdef __m68k__ - #define KEXEC_ARCH_NATIVE KEXEC_ARCH_68K - #endif -diff --git a/kexec/kexec.c b/kexec/kexec.c -index b088916..4ef7c64 100644 ---- a/kexec/kexec.c -+++ b/kexec/kexec.c -@@ -663,7 +663,9 @@ static int my_load(const char *type, int fileind, int argc, char **argv, - - memset(&info, 0, sizeof(info)); - info.kexec_flags = kexec_flags; -- -+ -+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); -+ - result = 0; - if (argc - fileind <= 0) { - fprintf(stderr, "No kernel specified\n"); -diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile -new file mode 100644 -index 0000000..d88e037 ---- /dev/null -+++ b/purgatory/arch/arm64/Makefile -@@ -0,0 +1,7 @@ -+# -+# Purgatory arm64 -+# -+ -+arm64_PURGATORY_SRCS = -+ -+dist += purgatory/arch/arm64/Makefile $(arm64_PURGATORY_SRCS) --- -1.9.1 - diff --git a/patches/kexec-tools/series b/patches/kexec-tools/series index 73a74ea10..e69de29bb 100644 --- a/patches/kexec-tools/series +++ b/patches/kexec-tools/series @@ -1,6 +0,0 @@ -# Disabled this series for the post 2021.08 ONIE release, as the upgraded -# kexec-tools has arm64 support, and seems to work fine without the patch. -# PowerPC support remains to be tested - Alex Doyle -# This series applies on GIT commit db8668ed563d446839f25150fb1ba24721d7c4be -#0001-Improve-device-tree-directory-sorting.patch -#15-25-kexec-tools-add-aarch64-support.patch From 73bbd345c883bf3ac0ea3ec166c0d13ed6117635 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 29 Oct 2025 08:45:14 +1300 Subject: [PATCH 04/15] kexec-tools: Bring in upstream patch for binutils 2.41 Bring in an upstream patch that fixes a build issue when using binutils 2.41 or newer. Signed-off-by: Chris Packham --- ...uilding-on-x86_64-with-binutils-2.41.patch | 90 +++++++++++++++++++ patches/kexec-tools/series | 1 + 2 files changed, 91 insertions(+) create mode 100644 patches/kexec-tools/0001-Fix-building-on-x86_64-with-binutils-2.41.patch diff --git a/patches/kexec-tools/0001-Fix-building-on-x86_64-with-binutils-2.41.patch b/patches/kexec-tools/0001-Fix-building-on-x86_64-with-binutils-2.41.patch new file mode 100644 index 000000000..7736fb5c4 --- /dev/null +++ b/patches/kexec-tools/0001-Fix-building-on-x86_64-with-binutils-2.41.patch @@ -0,0 +1,90 @@ +From 328de8e00e298f00d7ba6b25dc3950147e9642e6 Mon Sep 17 00:00:00 2001 +From: Michel Lind +Date: Tue, 30 Jan 2024 04:14:31 -0600 +Subject: [PATCH] Fix building on x86_64 with binutils 2.41 + +Newer versions of the GNU assembler (observed with binutils 2.41) will +complain about the ".arch i386" in files assembled with "as --64", +with the message "Error: 64bit mode not supported on 'i386'". + +Fix by moving ".arch i386" below the relevant ".code32" directive, so +that the assembler is no longer expecting 64-bit instructions to be used +by the time that the ".arch i386" directive is encountered. + +Based on similar iPXE fix: +https://github.com/ipxe/ipxe/commit/6ca597eee + +Signed-off-by: Michel Lind +Signed-off-by: Simon Horman +--- + purgatory/arch/i386/entry32-16-debug.S | 2 +- + purgatory/arch/i386/entry32-16.S | 2 +- + purgatory/arch/i386/entry32.S | 2 +- + purgatory/arch/i386/setup-x86.S | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/purgatory/arch/i386/entry32-16-debug.S b/purgatory/arch/i386/entry32-16-debug.S +index 5167944..12e1164 100644 +--- a/purgatory/arch/i386/entry32-16-debug.S ++++ b/purgatory/arch/i386/entry32-16-debug.S +@@ -25,10 +25,10 @@ + .globl entry16_debug_pre32 + .globl entry16_debug_first32 + .globl entry16_debug_old_first32 +- .arch i386 + .balign 16 + entry16_debug: + .code32 ++ .arch i386 + /* Compute where I am running at (assumes esp valid) */ + call 1f + 1: popl %ebx +diff --git a/purgatory/arch/i386/entry32-16.S b/purgatory/arch/i386/entry32-16.S +index c051aab..eace095 100644 +--- a/purgatory/arch/i386/entry32-16.S ++++ b/purgatory/arch/i386/entry32-16.S +@@ -20,10 +20,10 @@ + #undef i386 + .text + .globl entry16, entry16_regs +- .arch i386 + .balign 16 + entry16: + .code32 ++ .arch i386 + /* Compute where I am running at (assumes esp valid) */ + call 1f + 1: popl %ebx +diff --git a/purgatory/arch/i386/entry32.S b/purgatory/arch/i386/entry32.S +index f7a494f..8ce9e31 100644 +--- a/purgatory/arch/i386/entry32.S ++++ b/purgatory/arch/i386/entry32.S +@@ -20,10 +20,10 @@ + #undef i386 + + .text +- .arch i386 + .globl entry32, entry32_regs + entry32: + .code32 ++ .arch i386 + + /* Setup a gdt that should that is generally usefully */ + lgdt %cs:gdt +diff --git a/purgatory/arch/i386/setup-x86.S b/purgatory/arch/i386/setup-x86.S +index 201bb2c..a212eed 100644 +--- a/purgatory/arch/i386/setup-x86.S ++++ b/purgatory/arch/i386/setup-x86.S +@@ -21,10 +21,10 @@ + #undef i386 + + .text +- .arch i386 + .globl purgatory_start + purgatory_start: + .code32 ++ .arch i386 + + /* Load a gdt so I know what the segment registers are */ + lgdt %cs:gdt + diff --git a/patches/kexec-tools/series b/patches/kexec-tools/series index e69de29bb..1875dd76c 100644 --- a/patches/kexec-tools/series +++ b/patches/kexec-tools/series @@ -0,0 +1 @@ +0001-Fix-building-on-x86_64-with-binutils-2.41.patch From 1b04bc6f8372be2c72638f8e30067d036ac871f4 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 29 Oct 2025 09:05:51 +1300 Subject: [PATCH 05/15] grub-2.04: Bring in upstream patches for build failures Newer versions of GCC produce new sections that need to be stripped from the grub decompressor. There are also some new errors issues by GCC 15 for some existing code. Bring in some upstream patches that resolve these issues. uild-Fix-Werror-array-bounds-array-subscript-0-is-o.patch had some merge conflicts when applying to 2.04 which were resolved. use-stdbool.patch is a simplified version of the upstream patch. Signed-off-by: Chris Packham --- ...x-GRUB-i386-pc-build-with-Ubuntu-gcc.patch | 43 ++ ...-array-bounds-array-subscript-0-is-o.patch | 556 ++++++++++++++++++ ...move-.interp-section-from-.img-files.patch | 30 + patches/grub/2.04/series | 5 + .../types-Make-bool-generally-available.patch | 80 +++ patches/grub/2.04/use-stdbool.patch | 47 ++ 6 files changed, 761 insertions(+) create mode 100644 patches/grub/2.04/build-Fix-GRUB-i386-pc-build-with-Ubuntu-gcc.patch create mode 100644 patches/grub/2.04/build-Fix-Werror-array-bounds-array-subscript-0-is-o.patch create mode 100644 patches/grub/2.04/gentpl.py-Remove-.interp-section-from-.img-files.patch create mode 100644 patches/grub/2.04/types-Make-bool-generally-available.patch create mode 100644 patches/grub/2.04/use-stdbool.patch diff --git a/patches/grub/2.04/build-Fix-GRUB-i386-pc-build-with-Ubuntu-gcc.patch b/patches/grub/2.04/build-Fix-GRUB-i386-pc-build-with-Ubuntu-gcc.patch new file mode 100644 index 000000000..8788f6c99 --- /dev/null +++ b/patches/grub/2.04/build-Fix-GRUB-i386-pc-build-with-Ubuntu-gcc.patch @@ -0,0 +1,43 @@ +From aa7681fc6388f50ad8af08c3f8b9f8f0a66803e0 Mon Sep 17 00:00:00 2001 +From: Simon Hardy +Date: Tue, 24 Mar 2020 13:29:12 +0000 +Subject: [PATCH] build: Fix GRUB i386-pc build with Ubuntu gcc + +With recent versions of gcc on Ubuntu a very large lzma_decompress.img file is +output. (e.g. 134479600 bytes instead of 2864.) This causes grub-mkimage to +fail with: "error: Decompressor is too big." + +This seems to be caused by a section .note.gnu.property that is placed at an +offset such that objcopy needs to pad the img file with zeros. + +This issue is present on: +Ubuntu 19.10 with gcc (Ubuntu 8.3.0-26ubuntu1~19.10) 8.3.0 +Ubuntu 19.10 with gcc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008 + +This issue is not present on: +Ubuntu 19.10 with gcc (Ubuntu 7.5.0-3ubuntu1~19.10) 7.5.0 +RHEL 8.0 with gcc 8.3.1 20190507 (Red Hat 8.3.1-4) + +The issue can be fixed by removing the section using objcopy as shown in +this patch. + +Signed-off-by: Simon Hardy +Reviewed-by: Daniel Kiper +[upstream commit 6643507ce30f775008e093580f0c9499dfb2c485] +--- + gentpl.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gentpl.py b/gentpl.py +index 387588c05..c86550d4f 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -766,7 +766,7 @@ def image(defn, platform): + if test x$(TARGET_APPLE_LINKER) = x1; then \ + $(MACHO2IMG) $< $@; \ + else \ +- $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .ARM.exidx $< $@; \ ++ $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .note.gnu.property -R .ARM.exidx $< $@; \ + fi + """) + diff --git a/patches/grub/2.04/build-Fix-Werror-array-bounds-array-subscript-0-is-o.patch b/patches/grub/2.04/build-Fix-Werror-array-bounds-array-subscript-0-is-o.patch new file mode 100644 index 000000000..dda376077 --- /dev/null +++ b/patches/grub/2.04/build-Fix-Werror-array-bounds-array-subscript-0-is-o.patch @@ -0,0 +1,556 @@ +From 1bd64999d704ea21f00ec0a9c741186b08d6449a Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 28 Mar 2022 15:00:53 +0800 +Subject: [PATCH] build: Fix -Werror=array-bounds array subscript 0 is + outside array bounds + +The GRUB is failing to build with GCC-12 in many places like this: + + In function 'init_cbfsdisk', + inlined from 'grub_mod_init' at ../../grub-core/fs/cbfs.c:391:3: + ../../grub-core/fs/cbfs.c:345:7: error: array subscript 0 is outside array bounds of 'grub_uint32_t[0]' {aka 'unsigned int[]'} [-Werror=array-bounds] + 345 | ptr = *(grub_uint32_t *) 0xfffffffc; + | ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is caused by GCC regression in 11/12 [1]. In a nut shell, the +warning is about detected invalid accesses at non-zero offsets to NULL +pointers. Since hardwired constant address is treated as NULL plus an +offset in the same underlying code, the warning is therefore triggered. + +Instead of inserting #pragma all over the places where literal pointers +are accessed to avoid diagnosing array-bounds, we can try to borrow the +idea from Linux kernel that the absolute_pointer() macro [2][3] is used +to disconnect a pointer using literal address from it's original object, +hence GCC won't be able to make assumptions on the boundary while doing +pointer arithmetic. With that we can greatly reduce the code we have to +cover up by making initial literal pointer assignment to use the new +wrapper but not having to track everywhere literal pointers are +accessed. This also makes code looks cleaner. + +Please note the grub_absolute_pointer() macro requires to be invoked in +a function as long as it is compound expression. Some global variables +with literal pointers has been changed to local ones in order to use +grub_absolute_pointer() to initialize it. The shuffling is basically done +in a selective and careful way that the variable's scope doesn't matter +being local or global, for example, the global variable must not get +modified at run time throughout. For the record, here's the list of +global variables got shuffled in this patch: + + grub-core/commands/i386/pc/drivemap.c:int13slot + grub-core/term/i386/pc/console.c:bios_data_area + grub-core/term/ns8250.c:serial_hw_io_addr + +[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 +[2] https://elixir.bootlin.com/linux/v5.16.14/source/include/linux/compiler.h#L180 +[3] https://elixir.bootlin.com/linux/v5.16.14/source/include/linux/compiler-gcc.h#L31 + +Signed-off-by: Michael Chang +Reviewed-by: Daniel Kiper +[upstream commit acffb81485e35e1f28152949a1c6e1d4dbf5172e] +--- + grub-core/bus/cs5536.c | 5 +++-- + grub-core/commands/acpi.c | 4 ++-- + grub-core/commands/efi/loadbios.c | 9 +++++---- + grub-core/commands/i386/pc/drivemap.c | 8 +++++--- + grub-core/commands/i386/pc/sendkey.c | 14 +++++++------- + grub-core/disk/i386/pc/biosdisk.c | 4 ++-- + grub-core/fs/cbfs.c | 2 +- + grub-core/kern/i386/pc/acpi.c | 4 ++-- + grub-core/kern/i386/pc/mmap.c | 2 +- + grub-core/loader/i386/multiboot_mbi.c | 2 +- + grub-core/loader/multiboot_mbi2.c | 4 ++-- + grub-core/mmap/i386/pc/mmap.c | 26 +++++++++++++------------- + grub-core/net/drivers/i386/pc/pxe.c | 12 ++++++------ + grub-core/term/i386/pc/console.c | 5 ++--- + grub-core/term/i386/pc/vga_text.c | 6 +++--- + grub-core/term/ns8250.c | 7 ++++++- + grub-core/video/i386/pc/vbe.c | 6 +++--- + include/grub/types.h | 24 ++++++++++++++++++++++++ + 18 files changed, 88 insertions(+), 56 deletions(-) + +diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c +index bb9aa27e5..ee4342850 100644 +--- a/grub-core/bus/cs5536.c ++++ b/grub-core/bus/cs5536.c +@@ -331,8 +331,9 @@ grub_cs5536_init_geode (grub_pci_device_t dev) + + { + volatile grub_uint32_t *oc; +- oc = grub_pci_device_map_range (dev, 0x05022000, +- GRUB_CS5536_USB_OPTION_REGS_SIZE); ++ ++ oc = grub_absolute_pointer (grub_pci_device_map_range (dev, 0x05022000, ++ GRUB_CS5536_USB_OPTION_REGS_SIZE)); + + oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] = + (oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] +diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c +index 5a1499aa0..dbd801b55 100644 +--- a/grub-core/commands/acpi.c ++++ b/grub-core/commands/acpi.c +@@ -167,7 +167,7 @@ grub_acpi_create_ebda (void) + struct grub_acpi_rsdp_v10 *v1; + struct grub_acpi_rsdp_v20 *v2; + +- ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4); ++ ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4); + grub_dprintf ("acpi", "EBDA @%p\n", ebda); + if (ebda) + ebda_kb_len = *(grub_uint16_t *) ebda; +@@ -297,7 +297,7 @@ grub_acpi_create_ebda (void) + *target = 0; + + grub_dprintf ("acpi", "Switching EBDA\n"); +- (*((grub_uint16_t *) 0x40e)) = ((grub_addr_t) targetebda) >> 4; ++ (*((grub_uint16_t *) grub_absolute_pointer (0x40e))) = ((grub_addr_t) targetebda) >> 4; + grub_dprintf ("acpi", "EBDA switched\n"); + + return GRUB_ERR_NONE; +diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c +index d41d521a4..2b4d73189 100644 +--- a/grub-core/commands/efi/loadbios.c ++++ b/grub-core/commands/efi/loadbios.c +@@ -46,7 +46,7 @@ enable_rom_area (void) + grub_uint32_t *rom_ptr; + grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0}; + +- rom_ptr = (grub_uint32_t *) VBIOS_ADDR; ++ rom_ptr = grub_absolute_pointer (VBIOS_ADDR); + if (*rom_ptr != BLANK_MEM) + { + grub_puts_ (N_("ROM image is present.")); +@@ -96,8 +96,8 @@ fake_bios_data (int use_rom) + void *acpi, *smbios; + grub_uint16_t *ebda_seg_ptr, *low_mem_ptr; + +- ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR; +- low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR; ++ ebda_seg_ptr = grub_absolute_pointer (EBDA_SEG_ADDR); ++ low_mem_ptr = grub_absolute_pointer (LOW_MEM_ADDR); + if ((*ebda_seg_ptr) || (*low_mem_ptr)) + return; + +@@ -132,7 +132,8 @@ fake_bios_data (int use_rom) + *ebda_seg_ptr = FAKE_EBDA_SEG; + *low_mem_ptr = (FAKE_EBDA_SEG >> 6); + +- *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr; ++ /* *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr; */ ++ *((grub_uint16_t *) (grub_absolute_pointer (FAKE_EBDA_SEG << 4))) = 640 - *low_mem_ptr; + + if (acpi) + grub_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16); +diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c +index 7f7f2d41c..a4b8cd913 100644 +--- a/grub-core/commands/i386/pc/drivemap.c ++++ b/grub-core/commands/i386/pc/drivemap.c +@@ -31,9 +31,6 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + +-/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ +-static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13); +- + /* Remember to update enum opt_idxs accordingly. */ + static const struct grub_arg_option options[] = { + /* TRANSLATORS: In this file "mapping" refers to a change GRUB makes so if +@@ -280,6 +277,8 @@ install_int13_handler (int noret __attribute__ ((unused))) + grub_uint8_t *handler_base = 0; + /* Address of the map within the deployed bundle. */ + int13map_node_t *handler_map; ++ /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ ++ grub_uint32_t *int13slot = (grub_uint32_t *) grub_absolute_pointer (4 * 0x13); + + int i; + int entries = 0; +@@ -354,6 +353,9 @@ install_int13_handler (int noret __attribute__ ((unused))) + static grub_err_t + uninstall_int13_handler (void) + { ++ /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ ++ grub_uint32_t *int13slot = (grub_uint32_t *) grub_absolute_pointer (4 * 0x13); ++ + if (! grub_drivemap_oldhandler) + return GRUB_ERR_NONE; + +diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c +index 26d9acd3d..dace1880c 100644 +--- a/grub-core/commands/i386/pc/sendkey.c ++++ b/grub-core/commands/i386/pc/sendkey.c +@@ -216,12 +216,12 @@ static grub_err_t + grub_sendkey_postboot (void) + { + /* For convention: pointer to flags. */ +- grub_uint32_t *flags = (grub_uint32_t *) 0x417; ++ grub_uint32_t *flags = grub_absolute_pointer (0x417); + + *flags = oldflags; + +- *((char *) 0x41a) = 0x1e; +- *((char *) 0x41c) = 0x1e; ++ *((volatile char *) grub_absolute_pointer (0x41a)) = 0x1e; ++ *((volatile char *) grub_absolute_pointer (0x41c)) = 0x1e; + + return GRUB_ERR_NONE; + } +@@ -231,13 +231,13 @@ static grub_err_t + grub_sendkey_preboot (int noret __attribute__ ((unused))) + { + /* For convention: pointer to flags. */ +- grub_uint32_t *flags = (grub_uint32_t *) 0x417; ++ grub_uint32_t *flags = grub_absolute_pointer (0x417); + + oldflags = *flags; +- ++ + /* Set the sendkey. */ +- *((char *) 0x41a) = 0x1e; +- *((char *) 0x41c) = keylen + 0x1e; ++ *((volatile char *) grub_absolute_pointer (0x41a)) = 0x1e; ++ *((volatile char *) grub_absolute_pointer (0x41c)) = keylen + 0x1e; + grub_memcpy ((char *) 0x41e, sendkey, 0x20); + + /* Transform "any ctrl" to "right ctrl" flag. */ +diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c +index 8ca250c77..89746ed94 100644 +--- a/grub-core/disk/i386/pc/biosdisk.c ++++ b/grub-core/disk/i386/pc/biosdisk.c +@@ -367,7 +367,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) + if (version) + { + struct grub_biosdisk_drp *drp +- = (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ = (struct grub_biosdisk_drp *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + + /* Clear out the DRP. */ + grub_memset (drp, 0, sizeof (*drp)); +@@ -654,7 +654,7 @@ grub_disk_biosdisk_fini (void) + GRUB_MOD_INIT(biosdisk) + { + struct grub_biosdisk_cdrp *cdrp +- = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ = (struct grub_biosdisk_cdrp *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + grub_uint8_t boot_drive; + + if (grub_disk_firmware_is_tainted) +diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c +index 857bea991..917cd00a4 100644 +--- a/grub-core/fs/cbfs.c ++++ b/grub-core/fs/cbfs.c +@@ -342,7 +342,7 @@ init_cbfsdisk (void) + grub_uint32_t ptr; + struct cbfs_header *head; + +- ptr = *(grub_uint32_t *) 0xfffffffc; ++ ptr = *((grub_uint32_t *) grub_absolute_pointer (0xfffffffc)); + head = (struct cbfs_header *) (grub_addr_t) ptr; + grub_dprintf ("cbfs", "head=%p\n", head); + +diff --git a/grub-core/kern/i386/pc/acpi.c b/grub-core/kern/i386/pc/acpi.c +index 297f5d05f..0a69eba7b 100644 +--- a/grub-core/kern/i386/pc/acpi.c ++++ b/grub-core/kern/i386/pc/acpi.c +@@ -27,7 +27,7 @@ grub_machine_acpi_get_rsdpv1 (void) + grub_uint8_t *ebda, *ptr; + + grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); +- ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ++ ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4); + ebda_len = * (grub_uint16_t *) ebda; + if (! ebda_len) /* FIXME do we really need this check? */ + goto scan_bios; +@@ -55,7 +55,7 @@ grub_machine_acpi_get_rsdpv2 (void) + grub_uint8_t *ebda, *ptr; + + grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); +- ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ++ ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4); + ebda_len = * (grub_uint16_t *) ebda; + if (! ebda_len) /* FIXME do we really need this check? */ + goto scan_bios; +diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c +index c0c3c3585..a4a1a75af 100644 +--- a/grub-core/kern/i386/pc/mmap.c ++++ b/grub-core/kern/i386/pc/mmap.c +@@ -143,7 +143,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) + { + grub_uint32_t cont = 0; + struct grub_machine_mmap_entry *entry +- = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ = (struct grub_machine_mmap_entry *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + int e820_works = 0; + + while (1) +diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c +index a67d9d0a8..434e694ff 100644 +--- a/grub-core/loader/i386/multiboot_mbi.c ++++ b/grub-core/loader/i386/multiboot_mbi.c +@@ -293,7 +293,7 @@ fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig, + struct grub_vbe_mode_info_block *mode_info; + #if GRUB_MACHINE_HAS_VBE + grub_vbe_status_t status; +- void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + + status = grub_vbe_bios_get_controller_info (scratch); + if (status != GRUB_VBE_STATUS_OK) +diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c +index 03967839c..b4b561ae3 100644 +--- a/grub-core/loader/multiboot_mbi2.c ++++ b/grub-core/loader/multiboot_mbi2.c +@@ -498,7 +498,7 @@ static void + fill_vbe_tag (struct multiboot_tag_vbe *tag) + { + grub_vbe_status_t status; +- void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + + tag->type = MULTIBOOT_TAG_TYPE_VBE; + tag->size = 0; +@@ -571,7 +571,7 @@ retrieve_video_parameters (grub_properly_aligned_t **ptrorig) + #if defined (GRUB_MACHINE_PCBIOS) + { + grub_vbe_status_t status; +- void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + status = grub_vbe_bios_get_mode (scratch); + vbe_mode = *(grub_uint32_t *) scratch; + if (status != GRUB_VBE_STATUS_OK) +diff --git a/grub-core/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c +index 6ab4f6730..b9c5b0a00 100644 +--- a/grub-core/mmap/i386/pc/mmap.c ++++ b/grub-core/mmap/i386/pc/mmap.c +@@ -80,13 +80,13 @@ preboot (int noreturn __attribute__ ((unused))) + = min (grub_mmap_get_post64 (), 0xfc000000ULL) >> 16; + + /* Correct BDA. */ +- *((grub_uint16_t *) 0x413) = grub_mmap_get_lower () >> 10; ++ *((grub_uint16_t *) grub_absolute_pointer (0x413)) = grub_mmap_get_lower () >> 10; + + /* Save old interrupt handlers. */ +- grub_machine_mmaphook_int12offset = *((grub_uint16_t *) 0x48); +- grub_machine_mmaphook_int12segment = *((grub_uint16_t *) 0x4a); +- grub_machine_mmaphook_int15offset = *((grub_uint16_t *) 0x54); +- grub_machine_mmaphook_int15segment = *((grub_uint16_t *) 0x56); ++ grub_machine_mmaphook_int12offset = *((grub_uint16_t *) grub_absolute_pointer (0x48)); ++ grub_machine_mmaphook_int12segment = *((grub_uint16_t *) grub_absolute_pointer (0x4a)); ++ grub_machine_mmaphook_int15offset = *((grub_uint16_t *) grub_absolute_pointer (0x54)); ++ grub_machine_mmaphook_int15segment = *((grub_uint16_t *) grub_absolute_pointer (0x56)); + + grub_dprintf ("mmap", "hooktarget = %p\n", hooktarget); + +@@ -94,11 +94,11 @@ preboot (int noreturn __attribute__ ((unused))) + grub_memcpy (hooktarget, &grub_machine_mmaphook_start, + &grub_machine_mmaphook_end - &grub_machine_mmaphook_start); + +- *((grub_uint16_t *) 0x4a) = ((grub_addr_t) hooktarget) >> 4; +- *((grub_uint16_t *) 0x56) = ((grub_addr_t) hooktarget) >> 4; +- *((grub_uint16_t *) 0x48) = &grub_machine_mmaphook_int12 ++ *((grub_uint16_t *) grub_absolute_pointer (0x4a)) = ((grub_addr_t) hooktarget) >> 4; ++ *((grub_uint16_t *) grub_absolute_pointer (0x56)) = ((grub_addr_t) hooktarget) >> 4; ++ *((grub_uint16_t *) grub_absolute_pointer (0x48)) = &grub_machine_mmaphook_int12 + - &grub_machine_mmaphook_start; +- *((grub_uint16_t *) 0x54) = &grub_machine_mmaphook_int15 ++ *((grub_uint16_t *) grub_absolute_pointer (0x54)) = &grub_machine_mmaphook_int15 + - &grub_machine_mmaphook_start; + + return GRUB_ERR_NONE; +@@ -108,10 +108,10 @@ static grub_err_t + preboot_rest (void) + { + /* Restore old interrupt handlers. */ +- *((grub_uint16_t *) 0x48) = grub_machine_mmaphook_int12offset; +- *((grub_uint16_t *) 0x4a) = grub_machine_mmaphook_int12segment; +- *((grub_uint16_t *) 0x54) = grub_machine_mmaphook_int15offset; +- *((grub_uint16_t *) 0x56) = grub_machine_mmaphook_int15segment; ++ *((grub_uint16_t *) grub_absolute_pointer (0x48)) = grub_machine_mmaphook_int12offset; ++ *((grub_uint16_t *) grub_absolute_pointer (0x4a)) = grub_machine_mmaphook_int12segment; ++ *((grub_uint16_t *) grub_absolute_pointer (0x54)) = grub_machine_mmaphook_int15offset; ++ *((grub_uint16_t *) grub_absolute_pointer (0x56)) = grub_machine_mmaphook_int15segment; + + return GRUB_ERR_NONE; + } +diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c +index 3f4152d03..313ed250e 100644 +--- a/grub-core/net/drivers/i386/pc/pxe.c ++++ b/grub-core/net/drivers/i386/pc/pxe.c +@@ -174,7 +174,7 @@ grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused))) + grub_uint8_t *ptr, *end; + struct grub_net_buff *buf; + +- isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ isr = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + + if (!in_progress) + { +@@ -256,11 +256,11 @@ grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), + struct grub_pxe_undi_tbd *tbd; + char *buf; + +- trans = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ trans = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + grub_memset (trans, 0, sizeof (*trans)); +- tbd = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128); ++ tbd = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128); + grub_memset (tbd, 0, sizeof (*tbd)); +- buf = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256); ++ buf = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256); + grub_memcpy (buf, pack->data, pack->tail - pack->data); + + trans->tbd = SEGOFS ((grub_addr_t) tbd); +@@ -287,7 +287,7 @@ static grub_err_t + grub_pxe_open (struct grub_net_card *dev __attribute__ ((unused))) + { + struct grub_pxe_undi_open *ou; +- ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ ou = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + grub_memset (ou, 0, sizeof (*ou)); + ou->pkt_filter = 4; + grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); +@@ -382,7 +382,7 @@ GRUB_MOD_INIT(pxe) + if (! pxenv) + return; + +- ui = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ ui = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + grub_memset (ui, 0, sizeof (*ui)); + grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry); + +diff --git a/grub-core/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c +index f6142a2de..d70ee4af0 100644 +--- a/grub-core/term/i386/pc/console.c ++++ b/grub-core/term/i386/pc/console.c +@@ -238,12 +238,11 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) + return (regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL); + } + +-static const struct grub_machine_bios_data_area *bios_data_area = +- (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; +- + static int + grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused))) + { ++ const struct grub_machine_bios_data_area *bios_data_area = ++ (struct grub_machine_bios_data_area *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR); + /* conveniently GRUB keystatus is modelled after BIOS one. */ + return bios_data_area->keyboard_flag_lower & ~0x80; + } +diff --git a/grub-core/term/i386/pc/vga_text.c b/grub-core/term/i386/pc/vga_text.c +index 88fecc5ea..669d06fad 100644 +--- a/grub-core/term/i386/pc/vga_text.c ++++ b/grub-core/term/i386/pc/vga_text.c +@@ -45,15 +45,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_term_coordinate grub_curr_pos; + + #ifdef __mips__ +-#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb00b8000) ++#define VGA_TEXT_SCREEN ((grub_uint16_t *) grub_absolute_pointer (0xb00b8000)) + #define cr_read grub_vga_cr_read + #define cr_write grub_vga_cr_write + #elif defined (MODE_MDA) +-#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb0000) ++#define VGA_TEXT_SCREEN ((grub_uint16_t *) grub_absolute_pointer (0xb0000)) + #define cr_read grub_vga_cr_bw_read + #define cr_write grub_vga_cr_bw_write + #else +-#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb8000) ++#define VGA_TEXT_SCREEN ((grub_uint16_t *) grub_absolute_pointer (0xb8000)) + #define cr_read grub_vga_cr_read + #define cr_write grub_vga_cr_write + #endif +diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c +index 39809d042..622670d17 100644 +--- a/grub-core/term/ns8250.c ++++ b/grub-core/term/ns8250.c +@@ -28,7 +28,6 @@ + + #ifdef GRUB_MACHINE_PCBIOS + #include +-static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; + #define GRUB_SERIAL_PORT_NUM 4 + #else + #include +@@ -237,6 +236,9 @@ static struct grub_serial_port com_ports[GRUB_SERIAL_PORT_NUM]; + void + grub_ns8250_init (void) + { ++#ifdef GRUB_MACHINE_PCBIOS ++ const unsigned short *serial_hw_io_addr = (const unsigned short *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR); ++#endif + unsigned i; + for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++) + if (serial_hw_io_addr[i]) +@@ -272,6 +274,9 @@ grub_ns8250_init (void) + grub_port_t + grub_ns8250_hw_get_port (const unsigned int unit) + { ++#ifdef GRUB_MACHINE_PCBIOS ++ const unsigned short *serial_hw_io_addr = (const unsigned short *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR); ++#endif + if (unit < GRUB_SERIAL_PORT_NUM + && !(dead_ports & (1 << unit))) + return serial_hw_io_addr[unit]; +diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c +index 4b1bd7d5e..3c17f9247 100644 +--- a/grub-core/video/i386/pc/vbe.c ++++ b/grub-core/video/i386/pc/vbe.c +@@ -514,7 +514,7 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) + + /* Use low memory scratch area as temporary storage + for VESA BIOS call. */ +- vbe_ib = (struct grub_vbe_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ vbe_ib = (struct grub_vbe_info_block *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + + /* Prepare info block. */ + grub_memset (vbe_ib, 0, sizeof (*vbe_ib)); +@@ -574,7 +574,7 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) + + /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ + flat_panel_info = (struct grub_vbe_flat_panel_info *) +- (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + sizeof (struct grub_video_edid_info)); ++ grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + sizeof (struct grub_video_edid_info)); + + if (controller_info.version >= 0x200 + && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) +@@ -676,7 +676,7 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, + == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL) + { + struct grub_vbe_palette_data *palette +- = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ = (struct grub_vbe_palette_data *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + unsigned i; + + /* Make sure that the BIOS can reach the palette. */ +diff --git a/include/grub/types.h b/include/grub/types.h +index 035a4b528..dbbe672b4 100644 +--- a/include/grub/types.h ++++ b/include/grub/types.h +@@ -319,4 +319,28 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val) + + #define GRUB_CHAR_BIT 8 + ++/* ++ * The grub_absolute_pointer() macro borrows the idea from Linux kernel of using ++ * RELOC_HIDE() macro to stop GCC from checking the result of pointer arithmetic ++ * and also it's conversion to be inside the symbol's boundary [1]. The check ++ * is sometimes false positive, especially it is controversial to emit the array ++ * bounds [-Warray-bounds] warning on all hardwired literal pointers since GCC ++ * 11/12 [2]. Unless a good solution can be settled, for the time being we ++ * would be in favor of the macro instead of GCC pragmas which cannot match the ++ * places the warning needs to be ignored in an exact way. ++ * ++ * [1] https://lists.linuxcoding.com/kernel/2006-q3/msg17979.html ++ * [2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 ++ */ ++#if defined(__GNUC__) ++# define grub_absolute_pointer(val) \ ++({ \ ++ grub_addr_t __ptr; \ ++ asm ("" : "=r" (__ptr) : "0" ((void *) (val))); \ ++ (void *) (__ptr); \ ++}) ++#else ++# define grub_absolute_pointer(val) ((void *) (val)) ++#endif ++ + #endif /* ! GRUB_TYPES_HEADER */ diff --git a/patches/grub/2.04/gentpl.py-Remove-.interp-section-from-.img-files.patch b/patches/grub/2.04/gentpl.py-Remove-.interp-section-from-.img-files.patch new file mode 100644 index 000000000..89f722f2c --- /dev/null +++ b/patches/grub/2.04/gentpl.py-Remove-.interp-section-from-.img-files.patch @@ -0,0 +1,30 @@ +From 7d2649f94200ebce1b95f2255ec87d0c4f49001e Mon Sep 17 00:00:00 2001 +From: Nicholas Vinson +Date: Fri, 13 Jan 2023 02:56:35 -0500 +Subject: [PATCH] gentpl.py: Remove .interp section from .img files + +When building .img files, a .interp section from the .image files will +sometimes be copied into the .img file. This additional section pushes +the .img file beyond the 512-byte limit and causes grub-install to fail +to run for i386-pc platforms. + +Signed-off-by: Nicholas Vinson +Reviewed-by: Daniel Kiper +[upstream commit b58aa4e2095943303126fff706d73f18f7caab35] +--- + gentpl.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gentpl.py b/gentpl.py +index c86550d4f..823a8b5f8 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -766,7 +766,7 @@ def image(defn, platform): + if test x$(TARGET_APPLE_LINKER) = x1; then \ + $(MACHO2IMG) $< $@; \ + else \ +- $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .note.gnu.property -R .ARM.exidx $< $@; \ ++ $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .note.gnu.property -R .ARM.exidx -R .interp $< $@; \ + fi + """) + diff --git a/patches/grub/2.04/series b/patches/grub/2.04/series index 725c3d945..b4d512fee 100644 --- a/patches/grub/2.04/series +++ b/patches/grub/2.04/series @@ -97,3 +97,8 @@ deviceiter-overflow.patch is_sb_enabled_command.patch mdraid1x-linux-gcc-10.patch zfs-gcc-10.patch +build-Fix-GRUB-i386-pc-build-with-Ubuntu-gcc.patch +use-stdbool.patch +build-Fix-Werror-array-bounds-array-subscript-0-is-o.patch +types-Make-bool-generally-available.patch +gentpl.py-Remove-.interp-section-from-.img-files.patch diff --git a/patches/grub/2.04/types-Make-bool-generally-available.patch b/patches/grub/2.04/types-Make-bool-generally-available.patch new file mode 100644 index 000000000..2f1b4602d --- /dev/null +++ b/patches/grub/2.04/types-Make-bool-generally-available.patch @@ -0,0 +1,80 @@ +From ec1f2ae6e8e12095ede19b596ee58b332b955bff Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 4 Nov 2022 12:13:34 -0400 +Subject: [PATCH] types: Make bool generally available + +Add an include on stdbool.h, making the bool type generally available +within the GRUB without needing to add a file-specific include every +time it would be used. + +Signed-off-by: Robbie Harwood +Reviewed-by: Daniel Kiper +[upstream commit 229b23a017f2faae632730b7f240ee57cfdff0f9] +--- + grub-core/commands/parttool.c | 2 +- + grub-core/parttool/msdospart.c | 4 ++-- + include/grub/parttool.h | 2 +- + include/grub/types.h | 1 + + 4 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c +index 051e31320..ff45c65e6 100644 +--- a/grub-core/commands/parttool.c ++++ b/grub-core/commands/parttool.c +@@ -315,7 +315,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), + switch (curarg->type) + { + case GRUB_PARTTOOL_ARG_BOOL: +- pargs[curarg - ptool->args].bool ++ pargs[curarg - ptool->args].b + = (args[j][grub_strlen (curarg->name)] != '-'); + break; + +diff --git a/grub-core/parttool/msdospart.c b/grub-core/parttool/msdospart.c +index dcbf74e3b..a92669e5a 100644 +--- a/grub-core/parttool/msdospart.c ++++ b/grub-core/parttool/msdospart.c +@@ -61,7 +61,7 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev, + return grub_errno; + } + +- if (args[0].set && args[0].bool) ++ if (args[0].set && args[0].b) + { + for (i = 0; i < 4; i++) + mbr.entries[i].flag = 0x0; +@@ -116,7 +116,7 @@ static grub_err_t grub_pcpart_type (const grub_device_t dev, + + if (args[1].set) + { +- if (args[1].bool) ++ if (args[1].b) + type |= GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG; + else + type &= ~GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG; +diff --git a/include/grub/parttool.h b/include/grub/parttool.h +index 4e8f8d5e5..4799a22c5 100644 +--- a/include/grub/parttool.h ++++ b/include/grub/parttool.h +@@ -32,7 +32,7 @@ struct grub_parttool_args + int set; + union + { +- int bool; ++ int b; + char *str; + }; + }; +diff --git a/include/grub/types.h b/include/grub/types.h +index dbbe672b4..24b041b4a 100644 +--- a/include/grub/types.h ++++ b/include/grub/types.h +@@ -20,6 +20,7 @@ + #define GRUB_TYPES_HEADER 1 + + #include ++#include + #ifndef GRUB_UTIL + #include + #endif + diff --git a/patches/grub/2.04/use-stdbool.patch b/patches/grub/2.04/use-stdbool.patch new file mode 100644 index 000000000..fc744cdc1 --- /dev/null +++ b/patches/grub/2.04/use-stdbool.patch @@ -0,0 +1,47 @@ +From eafa3b5617bcefeb19e6112ee869d912667d26bb Mon Sep 17 00:00:00 2001 +From: Chris Packham +Date: Thu, 30 Oct 2025 17:12:03 +1300 +Subject: [PATCH] use stdbool + +Use stdbool to provide a bool type. A similar change was done are in commit +ea780522e ("gnulib: Drop fix-base64.patch") but this won't apply cleanly to +2.04 so this change brings in only the stdbool related changes. +--- + grub-core/lib/posix_wrap/sys/types.h | 6 ++---- + grub-core/lib/xzembed/xz.h | 5 +---- + 2 files changed, 3 insertions(+), 8 deletions(-) + +diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h +index 854eb0122..a13f5edb5 100644 +--- a/grub-core/lib/posix_wrap/sys/types.h ++++ b/grub-core/lib/posix_wrap/sys/types.h +@@ -23,11 +23,9 @@ + + #include + ++#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 f7b32d800..d1417039a 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 From 34ca436219329205034e576e1b59ae7d47a85c38 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 29 Oct 2025 14:12:47 +1300 Subject: [PATCH 06/15] parted: Add patch to fix build issue Add a patch to fix a build issue with newer versions of GCC. This is based on upstream commit 16343bd ("bug#74444: [PATCH] parted: fix do_version declaration") but is not identical because there are other changes that stop the upstream patch from applying cleanly to parted-3.1. Signed-off-by: Chris Packham --- build-config/make/parted.make | 14 ++++++-- .../parted/fix-do_version-declaration.patch | 35 +++++++++++++++++++ patches/parted/series | 1 + 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 patches/parted/fix-do_version-declaration.patch create mode 100644 patches/parted/series diff --git a/build-config/make/parted.make b/build-config/make/parted.make index 9e6f498cb..5b87d9b7a 100644 --- a/build-config/make/parted.make +++ b/build-config/make/parted.make @@ -24,11 +24,13 @@ PARTED_DIR = $(PARTED_BUILD_DIR)/parted-$(PARTED_VERSION) PARTED_SRCPATCHDIR = $(PATCHDIR)/parted PARTED_DOWNLOAD_STAMP = $(DOWNLOADDIR)/parted-download PARTED_SOURCE_STAMP = $(USER_STAMPDIR)/parted-source +PARTED_PATCH_STAMP = $(USER_STAMPDIR)/parted-patch PARTED_CONFIGURE_STAMP = $(USER_STAMPDIR)/parted-configure PARTED_BUILD_STAMP = $(USER_STAMPDIR)/parted-build PARTED_INSTALL_STAMP = $(STAMPDIR)/parted-install PARTED_STAMP = $(PARTED_SOURCE_STAMP) \ + $(PARTED_PATCH_STAMP) \ $(PARTED_CONFIGURE_STAMP) \ $(PARTED_BUILD_STAMP) \ $(PARTED_INSTALL_STAMP) @@ -58,8 +60,16 @@ $(PARTED_SOURCE_STAMP): $(USER_TREE_STAMP) | $(PARTED_DOWNLOAD_STAMP) $(Q) $(SCRIPTDIR)/extract-package $(PARTED_BUILD_DIR) $(DOWNLOADDIR)/$(PARTED_TARBALL) $(Q) touch $@ +parted-patch: $(PARTED_PATCH_STAMP) +$(PARTED_PATCH_STAMP): $(PARTED_SRCPATCHDIR)/* $(PARTED_SOURCE_STAMP) + $(Q) rm -f $@ && eval $(PROFILE_STAMP) + $(Q) echo "==== Patching parted ====" + $(Q) $(SCRIPTDIR)/apply-patch-series $(PARTED_SRCPATCHDIR)/series $(PARTED_DIR) + $(Q) touch $@ + parted-configure: $(PARTED_CONFIGURE_STAMP) -$(PARTED_CONFIGURE_STAMP): $(PARTED_SOURCE_STAMP) $(E2FSPROGS_BUILD_STAMP) $(LVM2_BUILD_STAMP) | $(DEV_SYSROOT_INIT_STAMP) +$(PARTED_CONFIGURE_STAMP): $(PARTED_SOURCE_STAMP) $(E2FSPROGS_BUILD_STAMP) $(LVM2_BUILD_STAMP) $(PARTED_PATCH_STAMP) | \ + $(DEV_SYSROOT_INIT_STAMP) $(Q) rm -f $@ && eval $(PROFILE_STAMP) $(Q) echo "==== Configure parted-$(PARTED_VERSION) ====" $(Q) cd $(PARTED_DIR) && PATH='$(CROSSBIN):$(PATH)' \ @@ -80,7 +90,7 @@ $(PARTED_CONFIGURE_STAMP): $(PARTED_SOURCE_STAMP) $(E2FSPROGS_BUILD_STAMP) $(LVM $(Q) touch $@ # Print configure options for debug -parted-configure-help: $(PARTED_CONFIGURE_STAMP) +parted-configure-help: $(PARTED_CONFIGURE_STAMP) $(PARTED_PATCH_STAMP) $(Q) echo "==== Configure parted-$(PARTED_VERSION) ====" $(Q) $(PARTED_DIR)/configure -help diff --git a/patches/parted/fix-do_version-declaration.patch b/patches/parted/fix-do_version-declaration.patch new file mode 100644 index 000000000..04fb2d9d8 --- /dev/null +++ b/patches/parted/fix-do_version-declaration.patch @@ -0,0 +1,35 @@ +Subject: [PATCH] fix do_version declaration + +With gcc 15 compile fails with the below error, update the +do_version declaration to match the header in command.h + +parted.c: In function '_init_commands': +parted.c:1954:9: error: passing argument 2 of 'command_create' from incompatible pointer type [-Wincompatible-pointer-types] + 1954 | do_version, + | ^~~~~~~~~~ + | | + | int (*)(PedDevice **, PedDisk **) {aka int (*)(struct _PedDevice **, struct _PedDisk **)} +command.h:34:39: note: expected 'int (*)(PedDevice **)' {aka 'int (*)(struct _PedDevice **)'} but argument is of type 'int (*)(PedDevice **, PedDisk **)' {aka 'int (*)(struct _PedDevice **, struct _PedDisk **)'} + 34 | int (*method) (PedDevice** dev), + | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~ +parted.c:1696:1: note: 'do_version' declared here + 1696 | do_version (PedDevice** dev, PedDisk** diskp) + | ^~~~~~~~~~ +--- + parted/parted.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/parted/parted.c b/parted/parted.c +index 789030a..0cb6bc1 100644 +--- a/parted/parted.c ++++ b/parted/parted.c +@@ -1693,7 +1693,7 @@ do_unit (PedDevice** dev) + } + + static int +-do_version () ++do_version (PedDevice** dev) + { + printf ("\n%s\n%s", + prog_name, + diff --git a/patches/parted/series b/patches/parted/series new file mode 100644 index 000000000..24b7e0564 --- /dev/null +++ b/patches/parted/series @@ -0,0 +1 @@ +fix-do_version-declaration.patch From 2c6c0911b0d0f2133ec88ffddcebb9f78b4ff6c0 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 29 Oct 2025 14:26:41 +1300 Subject: [PATCH 07/15] e2fsprogs: Add upstream patch for build failure Add an upstream patch to resolve build issues with GCC 15. Signed-off-by: Chris Packham --- ...-libext2fs-fix-std-c23-build-failure.patch | 40 +++++++++++++++++++ patches/e2fsprogs/series | 1 + 2 files changed, 41 insertions(+) create mode 100644 patches/e2fsprogs/0001-libext2fs-fix-std-c23-build-failure.patch diff --git a/patches/e2fsprogs/0001-libext2fs-fix-std-c23-build-failure.patch b/patches/e2fsprogs/0001-libext2fs-fix-std-c23-build-failure.patch new file mode 100644 index 000000000..8b846989b --- /dev/null +++ b/patches/e2fsprogs/0001-libext2fs-fix-std-c23-build-failure.patch @@ -0,0 +1,40 @@ +From 49fd04d77b3244c6c6990be41142168eef373aef Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Fri, 22 Nov 2024 12:36:32 +0000 +Subject: [PATCH] libext2fs: fix -std=c23 build failure + +gcc-15 switched to -std=c23 by default: + + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=55e3bd376b2214e200fa76d12b67ff259b06c212 + +As a result `e2fsprogs` fails the build so only typedef int bool +for __STDC_VERSION__ <= 201710L (C17) + + ../../../lib/ext2fs/tdb.c:113:13: error: two or more data types in declaration specifiers + ../../../lib/ext2fs/tdb.c:113:1: warning: useless type name in empty declaration + 113 | typedef int bool; + | ^~~~~~~ + +https://github.com/tytso/e2fsprogs/issues/202 + +Signed-off-by: Rudi Heitbaum +Link: https://lore.kernel.org/r/Z0B60JhdvT9bpSQ6@6f91903e89da +Signed-off-by: Theodore Ts'o +--- + lib/ext2fs/tdb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/ext2fs/tdb.c b/lib/ext2fs/tdb.c +index b07b2917..98dc95d8 100644 +--- a/lib/ext2fs/tdb.c ++++ b/lib/ext2fs/tdb.c +@@ -110,7 +110,9 @@ static char *rep_strdup(const char *s) + #endif + #endif + ++#if defined __STDC__ && defined __STDC_VERSION__ && __STDC_VERSION__ <= 201710L + typedef int bool; ++#endif + + #include "tdb.h" + diff --git a/patches/e2fsprogs/series b/patches/e2fsprogs/series index e69de29bb..c59727f2e 100644 --- a/patches/e2fsprogs/series +++ b/patches/e2fsprogs/series @@ -0,0 +1 @@ +0001-libext2fs-fix-std-c23-build-failure.patch From 93f384edd3a32a830d2d6f007f8b1d7b66baa176 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 29 Oct 2025 14:52:03 +1300 Subject: [PATCH 08/15] mtdutils: Add patch for build failure Add a patch to fix a build error with GCC 15. This is based on changes in upstream commit 7dd42c5 ("Unify version string printing"). Signed-off-by: Chris Packham --- build-config/make/mtdutils.make | 12 ++++++- .../mtd-utils/flashcp-Don-t-define-bool.patch | 34 +++++++++++++++++++ patches/mtd-utils/series | 1 + 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 patches/mtd-utils/flashcp-Don-t-define-bool.patch create mode 100644 patches/mtd-utils/series diff --git a/build-config/make/mtdutils.make b/build-config/make/mtdutils.make index be6f3c134..fbb1c9b36 100644 --- a/build-config/make/mtdutils.make +++ b/build-config/make/mtdutils.make @@ -16,12 +16,15 @@ MTDUTILS_TARBALL = mtd-utils-$(MTDUTILS_VERSION).tar.gz MTDUTILS_TARBALL_URLS += $(ONIE_MIRROR) http://git.infradead.org/mtd-utils.git/snapshot MTDUTILS_BUILD_DIR = $(USER_BUILDDIR)/mtd-utils MTDUTILS_DIR = $(MTDUTILS_BUILD_DIR)/mtd-utils-e4c8885 +MTDUTILS_SRCPATCHDIR = $(PATCHDIR)/mtd-utils MTDUTILS_DOWNLOAD_STAMP = $(DOWNLOADDIR)/mtdutils-$(MTDUTILS_VERSION)-download MTDUTILS_SOURCE_STAMP = $(USER_STAMPDIR)/mtdutils-source +MTDUTILS_PATCH_STAMP = $(USER_STAMPDIR)/mtdutils-patch MTDUTILS_BUILD_STAMP = $(USER_STAMPDIR)/mtdutils-build MTDUTILS_INSTALL_STAMP = $(STAMPDIR)/mtdutils-install MTDUTILS_STAMP = $(MTDUTILS_SOURCE_STAMP) \ + $(MTDUTILS_PATCH_STAMP) \ $(MTDUTILS_BUILD_STAMP) \ $(MTDUTILS_INSTALL_STAMP) @@ -56,10 +59,17 @@ MTDUTILS_NEW_FILES = $(shell test -d $(MTDUTILS_DIR) && test -f $(MTDUTILS_BUILD find -L $(MTDUTILS_DIR) -newer $(MTDUTILS_BUILD_STAMP) -type f -print -quit) endif +mtdutils-patch: $(MTDUTILS_PATCH_STAMP) +$(MTDUTILS_PATCH_STAMP): $(MTDUTILS_SRCPATCHDIR)/* $(MTDUTILS_SOURCE_STAMP) + $(Q) rm -f $@ && eval $(PROFILE_STAMP) + $(Q) echo "==== Patching mtdutils ====" + $(Q) $(SCRIPTDIR)/apply-patch-series $(MTDUTILS_SRCPATCHDIR)/series $(MTDUTILS_DIR) + $(Q) touch $@ + mtdutils-build: $(MTDUTILS_BUILD_STAMP) $(MTDUTILS_BUILD_STAMP): $(MTDUTILS_NEW_FILES) $(UTILLINUX_BUILD_STAMP) \ $(LZO_BUILD_STAMP) $(ZLIB_BUILD_STAMP) \ - $(MTDUTILS_SOURCE_STAMP) | $(DEV_SYSROOT_INIT_STAMP) + $(MTDUTILS_SOURCE_STAMP) $(MTDUTILS_PATCH_STAMP) | $(DEV_SYSROOT_INIT_STAMP) $(Q) rm -f $@ && eval $(PROFILE_STAMP) $(Q) PATH='$(CROSSBIN):$(PATH)' \ $(MAKE) -C $(MTDUTILS_DIR) \ diff --git a/patches/mtd-utils/flashcp-Don-t-define-bool.patch b/patches/mtd-utils/flashcp-Don-t-define-bool.patch new file mode 100644 index 000000000..d32dec659 --- /dev/null +++ b/patches/mtd-utils/flashcp-Don-t-define-bool.patch @@ -0,0 +1,34 @@ +Date: Wed, 29 Oct 2025 14:33:30 +1300 +Subject: [PATCH] flashcp: Don't define bool + +GCC 15 complains: + + misc-utils/flashcp.c:46:13: error: 'bool' cannot be defined via 'typedef' + 46 | typedef int bool; + | ^~~~ + misc-utils/flashcp.c:46:13: note: 'bool' is a keyword with '-std=c23' onwards + misc-utils/flashcp.c:46:1: warning: useless type name in empty declaration + 46 | typedef int bool; + | ^~~~~~~ + +stdbool.h is already pulled in via common.h so just use that instead of +defining a bool type. +--- + misc-utils/flashcp.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/misc-utils/flashcp.c b/misc-utils/flashcp.c +index 3fddeb0..69f2a1d 100644 +--- a/misc-utils/flashcp.c ++++ b/misc-utils/flashcp.c +@@ -43,9 +43,7 @@ + #include + #include + +-typedef int bool; +-#define true 1 +-#define false 0 ++#include "common.h" + + #define EXIT_FAILURE 1 + #define EXIT_SUCCESS 0 diff --git a/patches/mtd-utils/series b/patches/mtd-utils/series new file mode 100644 index 000000000..046d7f11c --- /dev/null +++ b/patches/mtd-utils/series @@ -0,0 +1 @@ +flashcp-Don-t-define-bool.patch From 3c04516fb649467d3b514fa0ba0f9d4f00a07619 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 30 Oct 2025 17:02:30 +1300 Subject: [PATCH 09/15] efivar: Pass CFLAGS when building Ensure we are pointing to the dev-sysroot otherwise we end up picking up libraries that are present on the build machine. Signed-off-by: Chris Packham --- build-config/make/efivar.make | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-config/make/efivar.make b/build-config/make/efivar.make index c2b0b17e9..af2b243f7 100644 --- a/build-config/make/efivar.make +++ b/build-config/make/efivar.make @@ -79,9 +79,9 @@ $(EFIVAR_BUILD_STAMP): $(EFIVAR_PATCH_STAMP) $(EFIVAR_NEW_FILES) $(POPT_BUILD_ST $(Q) rm -f $@ && eval $(PROFILE_STAMP) $(Q) echo "==== Building efivar-$(EFIVAR_VERSION) ====" $(Q) PATH='$(CROSSBIN):$(PATH)' $(MAKE) -C $(EFIVAR_DIR) \ - CROSS_COMPILE=$(CROSSPREFIX) PKG_CONFIG=pkg-config $(ONIE_PKG_CONFIG) DESTDIR=$(DEV_SYSROOT) + CROSS_COMPILE=$(CROSSPREFIX) PKG_CONFIG=pkg-config $(ONIE_PKG_CONFIG) CFLAGS="$(ONIE_CFLAGS)" DESTDIR=$(DEV_SYSROOT) $(Q) PATH='$(CROSSBIN):$(PATH)' $(MAKE) -C $(EFIVAR_DIR) \ - CROSS_COMPILE=$(CROSSPREFIX) PKG_CONFIG=pkg-config $(ONIE_PKG_CONFIG) DESTDIR=$(DEV_SYSROOT) install + CROSS_COMPILE=$(CROSSPREFIX) PKG_CONFIG=pkg-config $(ONIE_PKG_CONFIG) CFLAGS="$(ONIE_CFLAGS)" DESTDIR=$(DEV_SYSROOT) install $(Q) touch $@ efivar-install: $(EFIVAR_INSTALL_STAMP) From 912626af4d1dcbc120e67693a17392beb7ed6481 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 29 Oct 2025 15:10:03 +1300 Subject: [PATCH 10/15] efivar: Fix build errors with newer GCC Bring in two upstream patches that resolve address-of-packed-member errors. Ensure we pass the correct CFLAGS when building efivars. Signed-off-by: Chris Packham --- ...es-Werror-address-of-packed-member-c.patch | 168 ++++++++++++++++++ ..._guid-handle-misaligned-guid-pointer.patch | 56 ++++++ patches/efivar/37/series | 3 + 3 files changed, 227 insertions(+) create mode 100644 patches/efivar/37/Fix-all-the-places-Werror-address-of-packed-member-c.patch create mode 100644 patches/efivar/37/dp.h-make-format_guid-handle-misaligned-guid-pointer.patch diff --git a/patches/efivar/37/Fix-all-the-places-Werror-address-of-packed-member-c.patch b/patches/efivar/37/Fix-all-the-places-Werror-address-of-packed-member-c.patch new file mode 100644 index 000000000..bbb6a99a3 --- /dev/null +++ b/patches/efivar/37/Fix-all-the-places-Werror-address-of-packed-member-c.patch @@ -0,0 +1,168 @@ +From c3c553db85ff10890209d0fe48fb4856ad68e4e0 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 Feb 2019 15:20:12 -0500 +Subject: [PATCH] Fix all the places -Werror=address-of-packed-member catches. + +This gets rid of all the places GCC 9's -Werror=address-of-packed-member +flags as problematic. + +Fixes github issue #123 + +Signed-off-by: Peter Jones +--- + src/dp-message.c | 6 ++++-- + src/dp.h | 12 ++++-------- + src/guid.c | 2 +- + src/include/efivar/efivar.h | 2 +- + src/ucs2.h | 27 +++++++++++++++++++-------- + 5 files changed, 29 insertions(+), 20 deletions(-) + +diff --git a/src/dp-message.c b/src/dp-message.c +index 3724e5f..9f96466 100644 +--- a/src/dp-message.c ++++ b/src/dp-message.c +@@ -620,11 +620,13 @@ _format_message_dn(char *buf, size_t size, const_efidp dp) + ) / sizeof(efi_ip_addr_t); + format(buf, size, off, "Dns", "Dns("); + for (int i=0; i < end; i++) { +- const efi_ip_addr_t *addr = &dp->dns.addrs[i]; ++ efi_ip_addr_t addr; ++ ++ memcpy(&addr, &dp->dns.addrs[i], sizeof(addr)); + if (i != 0) + format(buf, size, off, "Dns", ","); + format_ip_addr(buf, size, off, "Dns", +- dp->dns.is_ipv6, addr); ++ dp->dns.is_ipv6, &addr); + } + format(buf, size, off, "Dns", ")"); + break; +diff --git a/src/dp.h b/src/dp.h +index 20cb608..1f921d5 100644 +--- a/src/dp.h ++++ b/src/dp.h +@@ -71,13 +71,9 @@ + int _rc; \ + char *_guidstr = NULL; \ + efi_guid_t _guid; \ +- const efi_guid_t * const _guid_p = \ +- likely(__alignof__(guid) == sizeof(guid)) \ +- ? guid \ +- : &_guid; \ +- \ +- if (unlikely(__alignof__(guid) == sizeof(guid))) \ +- memmove(&_guid, guid, sizeof(_guid)); \ ++ const efi_guid_t * const _guid_p = &_guid; \ ++ \ ++ memmove(&_guid, guid, sizeof(_guid)); \ + _rc = efi_guid_to_str(_guid_p, &_guidstr); \ + if (_rc < 0) { \ + efi_error("could not build %s GUID DP string", \ +@@ -86,7 +82,7 @@ + _guidstr = onstack(_guidstr, \ + strlen(_guidstr)+1); \ + _rc = format(buf, size, off, dp_type, "%s", \ +- _guidstr); \ ++ _guidstr); \ + } \ + _rc; \ + }) +diff --git a/src/guid.c b/src/guid.c +index 306c9ff..3156b3b 100644 +--- a/src/guid.c ++++ b/src/guid.c +@@ -31,7 +31,7 @@ + extern const efi_guid_t efi_guid_zero; + + int NONNULL(1, 2) PUBLIC +-efi_guid_cmp(const efi_guid_t *a, const efi_guid_t *b) ++efi_guid_cmp(const void * const a, const void * const b) + { + return memcmp(a, b, sizeof (efi_guid_t)); + } +diff --git a/src/include/efivar/efivar.h b/src/include/efivar/efivar.h +index 316891c..ad6449d 100644 +--- a/src/include/efivar/efivar.h ++++ b/src/include/efivar/efivar.h +@@ -128,7 +128,7 @@ extern int efi_symbol_to_guid(const char *symbol, efi_guid_t *guid) + + extern int efi_guid_is_zero(const efi_guid_t *guid); + extern int efi_guid_is_empty(const efi_guid_t *guid); +-extern int efi_guid_cmp(const efi_guid_t *a, const efi_guid_t *b); ++extern int efi_guid_cmp(const void * const a, const void * const b); + + /* import / export functions */ + typedef struct efi_variable efi_variable_t; +diff --git a/src/ucs2.h b/src/ucs2.h +index dbb5900..edd8367 100644 +--- a/src/ucs2.h ++++ b/src/ucs2.h +@@ -23,16 +23,21 @@ + (((val) & ((mask) << (shift))) >> (shift)) + + static inline size_t UNUSED +-ucs2len(const uint16_t * const s, ssize_t limit) ++ucs2len(const void *vs, ssize_t limit) + { + ssize_t i; +- for (i = 0; i < (limit >= 0 ? limit : i+1) && s[i] != (uint16_t)0; i++) ++ const uint16_t *s = vs; ++ const uint8_t *s8 = vs; ++ ++ for (i = 0; ++ i < (limit >= 0 ? limit : i+1) && s8[0] != 0 && s8[1] != 0; ++ i++, s8 += 2, s++) + ; + return i; + } + + static inline size_t UNUSED +-ucs2size(const uint16_t * const s, ssize_t limit) ++ucs2size(const void *s, ssize_t limit) + { + size_t rc = ucs2len(s, limit); + rc *= sizeof (uint16_t); +@@ -69,10 +74,11 @@ utf8size(uint8_t *s, ssize_t limit) + } + + static inline unsigned char * UNUSED +-ucs2_to_utf8(const uint16_t * const chars, ssize_t limit) ++ucs2_to_utf8(const void * const voidchars, ssize_t limit) + { + ssize_t i, j; + unsigned char *ret; ++ const uint16_t * const chars = voidchars; + + if (limit < 0) + limit = ucs2len(chars, -1); +@@ -124,10 +130,12 @@ ucs2_to_utf8(const uint16_t * const chars, ssize_t limit) + } + + static inline ssize_t UNUSED NONNULL(4) +-utf8_to_ucs2(uint16_t *ucs2, ssize_t size, int terminate, uint8_t *utf8) ++utf8_to_ucs2(void *ucs2void, ssize_t size, int terminate, uint8_t *utf8) + { + ssize_t req; + ssize_t i, j; ++ uint16_t *ucs2 = ucs2void; ++ uint16_t val16; + + if (!ucs2 && size > 0) { + errno = EINVAL; +@@ -162,10 +170,13 @@ utf8_to_ucs2(uint16_t *ucs2, ssize_t size, int terminate, uint8_t *utf8) + val = utf8[i] & 0x7f; + i += 1; + } +- ucs2[j] = val; ++ val16 = val; ++ ucs2[j] = val16; ++ } ++ if (terminate) { ++ val16 = 0; ++ ucs2[j++] = val16; + } +- if (terminate) +- ucs2[j++] = (uint16_t)0; + return j; + }; + diff --git a/patches/efivar/37/dp.h-make-format_guid-handle-misaligned-guid-pointer.patch b/patches/efivar/37/dp.h-make-format_guid-handle-misaligned-guid-pointer.patch new file mode 100644 index 000000000..f40942f45 --- /dev/null +++ b/patches/efivar/37/dp.h-make-format_guid-handle-misaligned-guid-pointer.patch @@ -0,0 +1,56 @@ +From b98ba8921010d03f46704a476c69861515deb1ca Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 7 Jan 2019 10:30:59 -0500 +Subject: [PATCH] dp.h: make format_guid() handle misaligned guid pointers + safely. + +GCC 9 adds -Werror=address-of-packed-member, which causes us to see the +build error reported at + https://bugzilla.opensuse.org/show_bug.cgi?id=1120862 . + +That bug report shows us the following: + +In file included from dp.c:26: +dp.h: In function 'format_vendor_helper': +dp.h:120:37: error: taking address of packed member of 'struct ' may result in an unaligned pointer value [-Werror=address-of-packed-member] + 120 | format_guid(buf, size, off, label, &dp->hw_vendor.vendor_guid); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~ +dp.h:74:25: note: in definition of macro 'format_guid' + 74 | _rc = efi_guid_to_str(guid, &_guidstr); \ + | ^~~~ +cc1: all warnings being treated as errors + +This patch makes format_guid() use a local variable as a bounce buffer +in the case that the guid we're passed is aligned as chaotic neutral. + +Note that this only fixes this instance and there may be others that bz +didn't show because it exited too soon, and I don't have a gcc 9 build +in front of me right now. + +Signed-off-by: Peter Jones +--- + src/dp.h | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/src/dp.h b/src/dp.h +index aa4e390..20cb608 100644 +--- a/src/dp.h ++++ b/src/dp.h +@@ -70,8 +70,15 @@ + #define format_guid(buf, size, off, dp_type, guid) ({ \ + int _rc; \ + char *_guidstr = NULL; \ +- \ +- _rc = efi_guid_to_str(guid, &_guidstr); \ ++ efi_guid_t _guid; \ ++ const efi_guid_t * const _guid_p = \ ++ likely(__alignof__(guid) == sizeof(guid)) \ ++ ? guid \ ++ : &_guid; \ ++ \ ++ if (unlikely(__alignof__(guid) == sizeof(guid))) \ ++ memmove(&_guid, guid, sizeof(_guid)); \ ++ _rc = efi_guid_to_str(_guid_p, &_guidstr); \ + if (_rc < 0) { \ + efi_error("could not build %s GUID DP string", \ + dp_type); \ diff --git a/patches/efivar/37/series b/patches/efivar/37/series index dc13aca35..e975522a6 100644 --- a/patches/efivar/37/series +++ b/patches/efivar/37/series @@ -10,3 +10,6 @@ remove-arrows.patch 0005-Fix-variable-sz-uninitialized-error.patch 0006-Fix-parsing-for-nvme-subsystem-devices.patch Always-initialize-any-variable-we-use-with-sscanf-s-.patch +dp.h-make-format_guid-handle-misaligned-guid-pointer.patch +Fix-all-the-places-Werror-address-of-packed-member-c.patch + From b76bc58f6add49b16979f4ed96d508cd936ecb4c Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 31 Oct 2025 09:22:32 +1300 Subject: [PATCH 11/15] mokutil: Remove unused patches Drop the patches for mokutil that are not used. Signed-off-by: Chris Packham --- ...t-wchar-so-toggle-passwords-work-rig.patch | 42 --------- ...-Fix-the-32bit-signedness-comparison.patch | 34 -------- ...01-Fix-the-potential-buffer-overflow.patch | 36 -------- .../0001-Make-all-efi_guid_t-const.patch | 87 ------------------- patches/mokutil/efivar-30-support.patch | 35 -------- 5 files changed, 234 deletions(-) delete mode 100644 patches/mokutil/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch delete mode 100644 patches/mokutil/0001-Fix-the-32bit-signedness-comparison.patch delete mode 100644 patches/mokutil/0001-Fix-the-potential-buffer-overflow.patch delete mode 100644 patches/mokutil/0001-Make-all-efi_guid_t-const.patch delete mode 100644 patches/mokutil/efivar-30-support.patch diff --git a/patches/mokutil/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch b/patches/mokutil/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch deleted file mode 100644 index e4bdff205..000000000 --- a/patches/mokutil/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 9eb111a7f7b897ba4ae19a68708e010a5c384260 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 19 Jun 2015 16:53:36 -0400 -Subject: [PATCH] Build with -fshort-wchar so toggle passwords work right. - -This source tree uses: - -typedef wchar_t efi_char16_t; - -to define UEFI's UCS-2 character type. On many platforms, wchar_t is -32-bits by default. As a result, efichar_from_char winds up writing -4-byte characters instead of 2-byte characters. In the case where we -hash the password in mokutil, this works fine, because the same datatype -is used, and the values are the same. But for our feature toggles, -where we store the raw data and shim is interpretting the character -array, every other character winds up being L'\0', and verification -fails. - -So always build with -fshort-wchar to ensure we get 2-byte character -storage. - -Signed-off-by: Peter Jones ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index fe28fb9..69d412a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -37,7 +37,7 @@ else - default_strict=no - fi - --WARNINGFLAGS_C="$WARNINGFLAGS_C -std=gnu11" -+WARNINGFLAGS_C="$WARNINGFLAGS_C -std=gnu11 -fshort-wchar" - - AC_ARG_ENABLE(strict, AS_HELP_STRING([--enable-strict],[Enable strict compilation options]), enable_strict=$enableval, - enable_strict=$default_strict) --- -2.7.4 - diff --git a/patches/mokutil/0001-Fix-the-32bit-signedness-comparison.patch b/patches/mokutil/0001-Fix-the-32bit-signedness-comparison.patch deleted file mode 100644 index be52a078d..000000000 --- a/patches/mokutil/0001-Fix-the-32bit-signedness-comparison.patch +++ /dev/null @@ -1,34 +0,0 @@ -From cdb4b6f3bfd6ada6558ddfb889e27150f0841b28 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Mon, 24 Nov 2014 11:38:54 +0800 -Subject: [PATCH] Fix the 32bit signedness comparison - ---- - src/mokutil.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/mokutil.c b/src/mokutil.c -index 93fb6fa..a7e83f7 100644 ---- a/src/mokutil.c -+++ b/src/mokutil.c -@@ -1284,7 +1284,7 @@ issue_mok_request (char **files, uint32_t total, MokRequest req, - - /* Mok */ - read_size = read (fd, ptr, sizes[i]); -- if (read_size < 0 || read_size != sizes[i]) { -+ if (read_size < 0 || read_size != (int64_t)sizes[i]) { - fprintf (stderr, "Failed to read %s\n", files[i]); - goto error; - } -@@ -1645,7 +1645,7 @@ export_moks () - goto error; - } - -- while (offset < list[i].mok_size) { -+ while (offset < (int64_t)list[i].mok_size) { - write_size = write (fd, list[i].mok + offset, - list[i].mok_size - offset); - if (write_size < 0) { --- -1.9.1 - diff --git a/patches/mokutil/0001-Fix-the-potential-buffer-overflow.patch b/patches/mokutil/0001-Fix-the-potential-buffer-overflow.patch deleted file mode 100644 index f5d0d2feb..000000000 --- a/patches/mokutil/0001-Fix-the-potential-buffer-overflow.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 1313fa02a5b2bfe61ee6702696600fc148ec2d6e Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 4 Nov 2014 15:50:03 +0800 -Subject: [PATCH] Fix the potential buffer overflow - -Signed-off-by: Gary Ching-Pang Lin ---- - src/mokutil.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/mokutil.c b/src/mokutil.c -index 5b34f22..93fb6fa 100644 ---- a/src/mokutil.c -+++ b/src/mokutil.c -@@ -1743,7 +1743,7 @@ set_toggle (const char * VarName, uint32_t state) - MokToggleVar tvar; - char *password = NULL; - unsigned int pw_len; -- efi_char16_t efichar_pass[SB_PASSWORD_MAX]; -+ efi_char16_t efichar_pass[SB_PASSWORD_MAX+1]; - int ret = -1; - - printf ("password length: %d~%d\n", SB_PASSWORD_MIN, SB_PASSWORD_MAX); -@@ -1757,8 +1757,7 @@ set_toggle (const char * VarName, uint32_t state) - efichar_from_char (efichar_pass, password, - SB_PASSWORD_MAX * sizeof(efi_char16_t)); - -- memcpy(tvar.password, efichar_pass, -- SB_PASSWORD_MAX * sizeof(efi_char16_t)); -+ memcpy(tvar.password, efichar_pass, sizeof(tvar.password)); - - tvar.mok_toggle_state = state; - --- -2.7.4 - diff --git a/patches/mokutil/0001-Make-all-efi_guid_t-const.patch b/patches/mokutil/0001-Make-all-efi_guid_t-const.patch deleted file mode 100644 index b6f33ba63..000000000 --- a/patches/mokutil/0001-Make-all-efi_guid_t-const.patch +++ /dev/null @@ -1,87 +0,0 @@ -From eba569a8e6c33f07042758cbfa1706d7339464e1 Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Wed, 13 Jan 2016 16:05:21 +0800 -Subject: [PATCH] Make all efi_guid_t const - -All UEFI GUIDs defined in efivar are const. Declare all of them const -to make gcc happy. - -Signed-off-by: Gary Lin ---- - src/mokutil.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/src/mokutil.c b/src/mokutil.c -index 1fb34f9..d2c52b4 100644 ---- a/src/mokutil.c -+++ b/src/mokutil.c -@@ -200,7 +200,7 @@ efichar_from_char (efi_char16_t *dest, const char *src, size_t dest_len) - } - - static uint32_t --efi_hash_size (efi_guid_t *hash_type) -+efi_hash_size (const efi_guid_t *hash_type) - { - if (efi_guid_cmp (hash_type, &efi_guid_sha1) == 0) { - return SHA_DIGEST_LENGTH; -@@ -218,7 +218,7 @@ efi_hash_size (efi_guid_t *hash_type) - } - - static uint32_t --signature_size (efi_guid_t *hash_type) -+signature_size (const efi_guid_t *hash_type) - { - uint32_t hash_size; - -@@ -439,7 +439,7 @@ list_keys (uint8_t *data, size_t data_size) - - /* match the hash in the hash array and return the index if matched */ - static int --match_hash_array (efi_guid_t *hash_type, const void *hash, -+match_hash_array (const efi_guid_t *hash_type, const void *hash, - const void *hash_array, const uint32_t array_size) - { - uint32_t hash_size, hash_count; -@@ -469,8 +469,8 @@ match_hash_array (efi_guid_t *hash_type, const void *hash, - } - - static int --delete_data_from_list (efi_guid_t *var_guid, const char *var_name, -- efi_guid_t *type, void *data, uint32_t data_size) -+delete_data_from_list (const efi_guid_t *var_guid, const char *var_name, -+ const efi_guid_t *type, void *data, uint32_t data_size) - { - uint8_t *var_data = NULL; - size_t var_data_size = 0; -@@ -1006,8 +1006,8 @@ is_valid_cert (void *cert, uint32_t cert_size) - } - - static int --is_duplicate (efi_guid_t *type, const void *data, const uint32_t data_size, -- efi_guid_t *vendor, const char *db_name) -+is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size, -+ const efi_guid_t *vendor, const char *db_name) - { - uint8_t *var_data; - size_t var_data_size; -@@ -1059,7 +1059,7 @@ done: - } - - static int --is_valid_request (efi_guid_t *type, void *mok, uint32_t mok_size, -+is_valid_request (const efi_guid_t *type, void *mok, uint32_t mok_size, - MokRequest req) - { - switch (req) { -@@ -1096,7 +1096,7 @@ is_valid_request (efi_guid_t *type, void *mok, uint32_t mok_size, - } - - static int --in_pending_request (efi_guid_t *type, void *data, uint32_t data_size, -+in_pending_request (const efi_guid_t *type, void *data, uint32_t data_size, - MokRequest req) - { - uint8_t *authvar_data; --- -2.7.4 - diff --git a/patches/mokutil/efivar-30-support.patch b/patches/mokutil/efivar-30-support.patch deleted file mode 100644 index 0fb70e954..000000000 --- a/patches/mokutil/efivar-30-support.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Mathieu Trudel-Lapierre -Subject: Update efi_set_variable() calls to include mode where missing. - -efivar (30?) now insists on the mode being specified when calling -efi_set_variable(); so add it where it's missing. Use the mode -already specified in a later efi_chmod() call where available. - ---- - src/mokutil.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -Index: b/src/mokutil.c -=================================================================== ---- a/src/mokutil.c -+++ b/src/mokutil.c -@@ -574,7 +574,8 @@ delete_data_from_list (const efi_guid_t - | EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_RUNTIME_ACCESS; - ret = efi_set_variable (*var_guid, var_name, -- var_data, total, attributes); -+ var_data, total, attributes, -+ S_IRUSR | S_IWUSR); - if (ret < 0) { - fprintf (stderr, "Failed to write variable \"%s\": %m\n", - var_name); -@@ -938,7 +939,8 @@ update_request (void *new_list, int list - data_size = list_len; - - if (efi_set_variable (efi_guid_shim, req_name, -- data, data_size, attributes) < 0) { -+ data, data_size, attributes, -+ S_IRUSR | S_IWUSR) < 0) { - switch (req) { - case ENROLL_MOK: - fprintf (stderr, "Failed to enroll new keys\n"); From 98b36ef6c71d1db99a3651f25c7c061f3814fceb Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 31 Oct 2025 09:21:01 +1300 Subject: [PATCH 12/15] mokutil: Bring in upstream patches for build issues Bring in two patches from upstream to resolve build issues with newer compilers. Signed-off-by: Chris Packham --- ...void-taking-pointer-to-packed-struct.patch | 115 ++++++++++++++++++ ...002-mokutil-remove-unused-int_to_b64.patch | 57 +++++++++ patches/mokutil/series | 3 +- 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 patches/mokutil/0001-Avoid-taking-pointer-to-packed-struct.patch create mode 100644 patches/mokutil/0002-mokutil-remove-unused-int_to_b64.patch diff --git a/patches/mokutil/0001-Avoid-taking-pointer-to-packed-struct.patch b/patches/mokutil/0001-Avoid-taking-pointer-to-packed-struct.patch new file mode 100644 index 000000000..2858701a1 --- /dev/null +++ b/patches/mokutil/0001-Avoid-taking-pointer-to-packed-struct.patch @@ -0,0 +1,115 @@ +From 7e5d2180c09429955004f3dfd960293a39aaf731 Mon Sep 17 00:00:00 2001 +From: Harry Youd +Date: Wed, 31 Jul 2019 19:44:53 +0100 +Subject: [PATCH] Avoid taking pointer to packed struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes: +error: taking address of packed member of ‘struct ’ may result in an unaligned pointer value [-Werror=address-of-packed-member] +(cherry picked from commit 19e8c9071b3d9306ca7b7329b313b31f86c2936d) +--- + src/mokutil.c | 38 ++++++++++++++++++++++---------------- + 1 file changed, 22 insertions(+), 16 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index e2d567d..8892613 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -270,20 +270,22 @@ build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + return NULL; + } + +- if ((efi_guid_cmp (&CertList->SignatureType, &efi_guid_x509_cert) != 0) && +- (efi_guid_cmp (&CertList->SignatureType, &efi_guid_sha1) != 0) && +- (efi_guid_cmp (&CertList->SignatureType, &efi_guid_sha224) != 0) && +- (efi_guid_cmp (&CertList->SignatureType, &efi_guid_sha256) != 0) && +- (efi_guid_cmp (&CertList->SignatureType, &efi_guid_sha384) != 0) && +- (efi_guid_cmp (&CertList->SignatureType, &efi_guid_sha512) != 0)) { ++ efi_guid_t sigtype = CertList->SignatureType; ++ ++ if ((efi_guid_cmp (&sigtype, &efi_guid_x509_cert) != 0) && ++ (efi_guid_cmp (&sigtype, &efi_guid_sha1) != 0) && ++ (efi_guid_cmp (&sigtype, &efi_guid_sha224) != 0) && ++ (efi_guid_cmp (&sigtype, &efi_guid_sha256) != 0) && ++ (efi_guid_cmp (&sigtype, &efi_guid_sha384) != 0) && ++ (efi_guid_cmp (&sigtype, &efi_guid_sha512) != 0)) { + dbsize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *)((uint8_t *) CertList + + CertList->SignatureListSize); + continue; + } + +- if ((efi_guid_cmp (&CertList->SignatureType, &efi_guid_x509_cert) != 0) && +- (CertList->SignatureSize != signature_size (&CertList->SignatureType))) { ++ if ((efi_guid_cmp (&sigtype, &efi_guid_x509_cert) != 0) && ++ (CertList->SignatureSize != signature_size (&sigtype))) { + dbsize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *)((uint8_t *) CertList + + CertList->SignatureListSize); +@@ -312,7 +314,7 @@ build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + } + + list[count].header = CertList; +- if (efi_guid_cmp (&CertList->SignatureType, &efi_guid_x509_cert) == 0) { ++ if (efi_guid_cmp (&sigtype, &efi_guid_x509_cert) == 0) { + /* X509 certificate */ + list[count].mok_size = CertList->SignatureSize - + sizeof(efi_guid_t); +@@ -442,10 +444,11 @@ list_keys (uint8_t *data, size_t data_size) + + for (unsigned int i = 0; i < mok_num; i++) { + printf ("[key %d]\n", i+1); +- if (efi_guid_cmp (&list[i].header->SignatureType, &efi_guid_x509_cert) == 0) { ++ efi_guid_t sigtype = list[i].header->SignatureType; ++ if (efi_guid_cmp (&sigtype, &efi_guid_x509_cert) == 0) { + print_x509 ((char *)list[i].mok, list[i].mok_size); + } else { +- print_hash_array (&list[i].header->SignatureType, ++ print_hash_array (&sigtype, + list[i].mok, list[i].mok_size); + } + if (i < mok_num - 1) +@@ -523,7 +526,8 @@ delete_data_from_list (const efi_guid_t *var_guid, const char *var_name, + remain = total; + for (unsigned int i = 0; i < mok_num; i++) { + remain -= list[i].header->SignatureListSize; +- if (efi_guid_cmp (&list[i].header->SignatureType, type) != 0) ++ efi_guid_t sigtype = list[i].header->SignatureType; ++ if (efi_guid_cmp (&sigtype, type) != 0) + continue; + + sig_list_size = list[i].header->SignatureListSize; +@@ -1057,7 +1061,8 @@ is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size + } + + for (unsigned int i = 0; i < node_num; i++) { +- if (efi_guid_cmp (&list[i].header->SignatureType, type) != 0) ++ efi_guid_t sigtype = list[i].header->SignatureType; ++ if (efi_guid_cmp (&sigtype, type) != 0) + continue; + + if (efi_guid_cmp (type, &efi_guid_x509_cert) == 0) { +@@ -1510,8 +1515,8 @@ issue_hash_request (const char *hash_str, MokRequest req, + goto error; + /* Check if there is a signature list with the same type */ + for (unsigned int i = 0; i < mok_num; i++) { +- if (efi_guid_cmp (&mok_list[i].header->SignatureType, +- &hash_type) == 0) { ++ efi_guid_t sigtype = mok_list[i].header->SignatureType; ++ if (efi_guid_cmp (&sigtype, &hash_type) == 0) { + merge_ind = i; + list_size -= sizeof(EFI_SIGNATURE_LIST); + break; +@@ -1678,8 +1683,9 @@ export_db_keys (const DBName db_name) + for (unsigned i = 0; i < mok_num; i++) { + off_t offset = 0; + ssize_t write_size; ++ efi_guid_t sigtype = list[i].header->SignatureType; + +- if (efi_guid_cmp (&list[i].header->SignatureType, &efi_guid_x509_cert) != 0) ++ if (efi_guid_cmp (&sigtype, &efi_guid_x509_cert) != 0) + continue; + + /* Dump X509 certificate to files */ diff --git a/patches/mokutil/0002-mokutil-remove-unused-int_to_b64.patch b/patches/mokutil/0002-mokutil-remove-unused-int_to_b64.patch new file mode 100644 index 000000000..5165215d6 --- /dev/null +++ b/patches/mokutil/0002-mokutil-remove-unused-int_to_b64.patch @@ -0,0 +1,57 @@ +From 6b1d030983d012bfdc6e8b9269af4e4de21684cb Mon Sep 17 00:00:00 2001 +From: Nicolas Frayer +Date: Wed, 29 Jan 2025 17:37:36 +0100 +Subject: [PATCH] mokutil: remove unused int_to_b64() + +static const char b64t[64] triggers compiler warning +which in turn makes the build fail with +-Werror=unterminated-string-initialization, so removing +this string with the the unused int_to_b64() function +which is the only function using this array. + +Signed-off-by: Nicolas Frayer +(cherry picked from commit ea98ef56fa64e088d968a10c7bc751492abe672f) +--- + src/password-crypt.c | 9 --------- + src/password-crypt.h | 1 - + 2 files changed, 10 deletions(-) + +diff --git a/src/password-crypt.c b/src/password-crypt.c +index 0b31d64..a4225f0 100644 +--- a/src/password-crypt.c ++++ b/src/password-crypt.c +@@ -46,9 +46,6 @@ + #define SHA256_DEFAULT_ROUNDS 5000 + #define SHA512_DEFAULT_ROUNDS 5000 + +-static const char b64t[64] = +-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +- + static const char md5_prefix[] = "$1$"; + + static const char sha256_prefix[] = "$5$"; +@@ -357,12 +354,6 @@ decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt) + return -1; + } + +-char +-int_to_b64 (const int i) +-{ +- return b64t[i & 0x3f]; +-} +- + int + b64_to_int (const char c) + { +diff --git a/src/password-crypt.h b/src/password-crypt.h +index 5487363..572f9ce 100644 +--- a/src/password-crypt.h ++++ b/src/password-crypt.h +@@ -68,7 +68,6 @@ uint16_t get_salt_size (int method); + int get_hash_size (int method); + const char *get_crypt_prefix (int method); + int decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt); +-char int_to_b64 (const int i); + int b64_to_int (const char c); + + #endif /* __PASSWORD_CRYPT_H__ */ diff --git a/patches/mokutil/series b/patches/mokutil/series index a4e90d32d..bf2527e73 100644 --- a/patches/mokutil/series +++ b/patches/mokutil/series @@ -1 +1,2 @@ -# New version of mokutil has patches for 3.0 already, so nothing to do here yet... +0001-Avoid-taking-pointer-to-packed-struct.patch +0002-mokutil-remove-unused-int_to_b64.patch From 1ecc547533912d54410d4db1d06660a9ee3e2ef6 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 4 Nov 2025 13:01:30 +1300 Subject: [PATCH 13/15] shim: Fix build issues Bring in 3 patches that resolve build issues with newer versions of GCC. Signed-off-by: Chris Packham --- ...tuff-Waddress-of-packed-member-finds.patch | 87 ++++++++++++++ ...ompareMem-on-MokListNode.Type-instea.patch | 70 +++++++++++ ...void-Werror-address-of-packed-member.patch | 109 ++++++++++++++++++ patches/shim/series | 3 + 4 files changed, 269 insertions(+) create mode 100644 patches/shim/0001-Work-around-stuff-Waddress-of-packed-member-finds.patch create mode 100644 patches/shim/0002-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch create mode 100644 patches/shim/0003-MokManager-avoid-Werror-address-of-packed-member.patch diff --git a/patches/shim/0001-Work-around-stuff-Waddress-of-packed-member-finds.patch b/patches/shim/0001-Work-around-stuff-Waddress-of-packed-member-finds.patch new file mode 100644 index 000000000..f523c6561 --- /dev/null +++ b/patches/shim/0001-Work-around-stuff-Waddress-of-packed-member-finds.patch @@ -0,0 +1,87 @@ +From 8730a7735aa08c408c1702e8efc9db857ad5a8e7 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 13 May 2019 16:34:35 -0400 +Subject: [PATCH] Work around stuff -Waddress-of-packed-member finds. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In MokManager we get a lot of these: + +../src/MokManager.c:1063:19: error: taking address of packed member of ‘struct ’ may result in an unaligned pointer value [-Werror=address-of-packed-member] + 1063 | if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) + | ^~~~~~~~~~~~~~~ + +The reason for this is that gnu-efi takes EFI_GUID * as its argument +instead of VOID *, and there's nothing telling the compiler that it +doesn't have alignment constraints on the input, so the compiler wants +it to have 16-byte alignment. + +Just use CompareMem() for these, as that's all CompareGuid is calling +anyway. + +Signed-off-by: Peter Jones +Upstream-commit-id: 08c14376b59 +(cherry picked from commit 2cbf56b82a5102777b37c4f7f47c8cf058cea027) +--- + MokManager.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 7e40a38..5d0a979 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -22,6 +22,8 @@ + #define CERT_STRING L"Select an X509 certificate to enroll:\n\n" + #define HASH_STRING L"Select a file to trust:\n\n" + ++#define CompareMemberGuid(x, y) CompareMem(x, y, sizeof(EFI_GUID)) ++ + typedef struct { + UINT32 MokSize; + UINT8 *Mok; +@@ -1078,7 +1080,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + continue; + + DataSize += sizeof(EFI_SIGNATURE_LIST); +- if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) ++ if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) + DataSize += sizeof(EFI_GUID); + DataSize += list[i].MokSize; + } +@@ -1100,7 +1102,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + CertList->SignatureType = list[i].Type; + CertList->SignatureHeaderSize = 0; + +- if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) { ++ if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) { + CertList->SignatureListSize = list[i].MokSize + + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + CertList->SignatureSize = +@@ -1141,7 +1143,7 @@ static void delete_cert(void *key, UINT32 key_size, + int i; + + for (i = 0; i < mok_num; i++) { +- if (CompareGuid(&(mok[i].Type), &X509_GUID) != 0) ++ if (CompareMemberGuid(&(mok[i].Type), &X509_GUID) != 0) + continue; + + if (mok[i].MokSize == key_size && +@@ -1192,7 +1194,7 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + sig_size = hash_size + sizeof(EFI_GUID); + + for (i = 0; i < mok_num; i++) { +- if ((CompareGuid(&(mok[i].Type), &Type) != 0) || ++ if ((CompareMemberGuid(&(mok[i].Type), &Type) != 0) || + (mok[i].MokSize < sig_size)) + continue; + +@@ -1356,7 +1358,7 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + + /* Search and destroy */ + for (i = 0; i < del_num; i++) { +- if (CompareGuid(&(del_key[i].Type), &X509_GUID) == 0) { ++ if (CompareMemberGuid(&(del_key[i].Type), &X509_GUID) == 0) { + delete_cert(del_key[i].Mok, del_key[i].MokSize, + mok, mok_num); + } else if (is_sha2_hash(del_key[i].Type)) { diff --git a/patches/shim/0002-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch b/patches/shim/0002-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch new file mode 100644 index 000000000..b84e2d70b --- /dev/null +++ b/patches/shim/0002-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch @@ -0,0 +1,70 @@ +From 5203ad999e2692069583cbd0dec84f62bb58932d Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Tue, 26 Feb 2019 11:33:53 +0800 +Subject: [PATCH] MokManager: Use CompareMem on MokListNode.Type instead of + CompareGuid + +Fix the errors from gcc9 '-Werror=address-of-packed-member' + +https://github.com/rhboot/shim/issues/161 + +Signed-off-by: Gary Lin +Upstream-commit-id: aaa09b35e73 +(cherry picked from commit 5d30a31fef4eb7e773da24c5e6c20576282a9c3a) +--- + MokManager.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 5d0a979..e13400b 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1080,7 +1080,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + continue; + + DataSize += sizeof(EFI_SIGNATURE_LIST); +- if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) ++ if (CompareMem(&(list[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) == 0) + DataSize += sizeof(EFI_GUID); + DataSize += list[i].MokSize; + } +@@ -1102,7 +1103,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + CertList->SignatureType = list[i].Type; + CertList->SignatureHeaderSize = 0; + +- if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) { ++ if (CompareMem(&(list[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) == 0) { + CertList->SignatureListSize = list[i].MokSize + + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + CertList->SignatureSize = +@@ -1143,7 +1145,8 @@ static void delete_cert(void *key, UINT32 key_size, + int i; + + for (i = 0; i < mok_num; i++) { +- if (CompareMemberGuid(&(mok[i].Type), &X509_GUID) != 0) ++ if (CompareMem(&(mok[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) != 0) + continue; + + if (mok[i].MokSize == key_size && +@@ -1194,7 +1197,7 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + sig_size = hash_size + sizeof(EFI_GUID); + + for (i = 0; i < mok_num; i++) { +- if ((CompareMemberGuid(&(mok[i].Type), &Type) != 0) || ++ if ((CompareMem(&(mok[i].Type), &Type, sizeof(EFI_GUID)) != 0) || + (mok[i].MokSize < sig_size)) + continue; + +@@ -1358,7 +1361,8 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + + /* Search and destroy */ + for (i = 0; i < del_num; i++) { +- if (CompareMemberGuid(&(del_key[i].Type), &X509_GUID) == 0) { ++ if (CompareMem(&(del_key[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) == 0) { + delete_cert(del_key[i].Mok, del_key[i].MokSize, + mok, mok_num); + } else if (is_sha2_hash(del_key[i].Type)) { diff --git a/patches/shim/0003-MokManager-avoid-Werror-address-of-packed-member.patch b/patches/shim/0003-MokManager-avoid-Werror-address-of-packed-member.patch new file mode 100644 index 000000000..9f6bfaa4e --- /dev/null +++ b/patches/shim/0003-MokManager-avoid-Werror-address-of-packed-member.patch @@ -0,0 +1,109 @@ +From 652b6df40199032240d22e35a7eb9455a900b02c Mon Sep 17 00:00:00 2001 +From: Jonas Witschel +Date: Thu, 5 Sep 2019 10:39:37 +0200 +Subject: [PATCH] MokManager: avoid -Werror=address-of-packed-member +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When compiling with GCC 9, there are a couple of errors of the form + +MokManager.c: In function ‘write_back_mok_list’: +MokManager.c:1056:19: error: taking address of packed member of ‘struct ’ may result in an unaligned pointer value [-Werror=address-of-packed-member] + 1056 | if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) + | ^~~~~~~~~~~~~~~ + +Copying the member of the packed struct to a temporary variable and +pointing to that variable solves the problem. + +Upstream-commit-id: 58532e12e9a +(cherry picked from commit d57e53f3bddc4bc7299b3d5efd5ba8c547e8dfa5) +--- + MokManager.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index e13400b..1a8d666 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1065,6 +1065,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + EFI_STATUS efi_status; + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_DATA *CertData; ++ EFI_GUID type; + void *Data = NULL, *ptr; + INTN DataSize = 0; + int i; +@@ -1080,8 +1081,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + continue; + + DataSize += sizeof(EFI_SIGNATURE_LIST); +- if (CompareMem(&(list[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) == 0) ++ type = list[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if (CompareGuid(&type, &X509_GUID) == 0) + DataSize += sizeof(EFI_GUID); + DataSize += list[i].MokSize; + } +@@ -1103,8 +1104,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + CertList->SignatureType = list[i].Type; + CertList->SignatureHeaderSize = 0; + +- if (CompareMem(&(list[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) == 0) { ++ if (CompareGuid(&(CertList->SignatureType), &X509_GUID) == 0) { + CertList->SignatureListSize = list[i].MokSize + + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + CertList->SignatureSize = +@@ -1142,11 +1142,12 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + static void delete_cert(void *key, UINT32 key_size, + MokListNode * mok, INTN mok_num) + { ++ EFI_GUID type; + int i; + + for (i = 0; i < mok_num; i++) { +- if (CompareMem(&(mok[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) != 0) ++ type = mok[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if (CompareGuid(&type, &X509_GUID) != 0) + continue; + + if (mok[i].MokSize == key_size && +@@ -1188,6 +1189,7 @@ static void mem_move(void *dest, void *src, UINTN size) + static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + MokListNode * mok, INTN mok_num) + { ++ EFI_GUID type; + UINT32 sig_size; + UINT32 list_num; + int i, del_ind; +@@ -1197,7 +1199,8 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + sig_size = hash_size + sizeof(EFI_GUID); + + for (i = 0; i < mok_num; i++) { +- if ((CompareMem(&(mok[i].Type), &Type, sizeof(EFI_GUID)) != 0) || ++ type = mok[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if ((CompareGuid(&type, &Type) != 0) || + (mok[i].MokSize < sig_size)) + continue; + +@@ -1253,6 +1256,7 @@ static void delete_hash_list(EFI_GUID Type, void *hash_list, UINT32 list_size, + static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + { + EFI_STATUS efi_status; ++ EFI_GUID type; + CHAR16 *db_name; + CHAR16 *auth_name; + CHAR16 *err_strs[] = { NULL, NULL, NULL }; +@@ -1361,8 +1365,8 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + + /* Search and destroy */ + for (i = 0; i < del_num; i++) { +- if (CompareMem(&(del_key[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) == 0) { ++ type = del_key[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if (CompareGuid(&type, &X509_GUID) == 0) { + delete_cert(del_key[i].Mok, del_key[i].MokSize, + mok, mok_num); + } else if (is_sha2_hash(del_key[i].Type)) { diff --git a/patches/shim/series b/patches/shim/series index daeeed0f1..d5abceab1 100644 --- a/patches/shim/series +++ b/patches/shim/series @@ -1,2 +1,5 @@ # This series applies on GIT commit 6e13a921b2ad400d581d19edc1890d4269cd0ddf update-makefile.patch +0001-Work-around-stuff-Waddress-of-packed-member-finds.patch +0002-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch +0003-MokManager-avoid-Werror-address-of-packed-member.patch From 5f9bf76512469bb3c9d63103a5c9d88665e86299 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 4 Nov 2025 14:07:38 +1300 Subject: [PATCH 14/15] pesign: Add patch to resolve build issue Add a patch to resolve a build issue with GCC 15. The build error actually looks like a false positive or maybe a miss-optimization however it does highlight some dead code. Signed-off-by: Chris Packham --- .../authvar-Remove-unreachable-free.patch | 53 +++++++++++++++++++ patches/pesign/series | 5 +- 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 patches/pesign/authvar-Remove-unreachable-free.patch diff --git a/patches/pesign/authvar-Remove-unreachable-free.patch b/patches/pesign/authvar-Remove-unreachable-free.patch new file mode 100644 index 000000000..0fc3dc871 --- /dev/null +++ b/patches/pesign/authvar-Remove-unreachable-free.patch @@ -0,0 +1,53 @@ +From 43c3873cbbd773357606b5d3f1eeba229dcfe98d Mon Sep 17 00:00:00 2001 +From: Chris Packham +Date: Tue, 4 Nov 2025 13:49:03 +1300 +Subject: [PATCH] authvar: Remove unreachable free() + +When building using GCC 15 the following error is hit + + authvar.c: In function 'main': + authvar.c:450:17: error: 'free' called on a pointer to an unallocated object '"NSS Certificate DB"' [-Werror=free-nonheap-object] + 450 | free(tokenname); + | ^ + authvar.c:270:15: note: assigned here + 270 | char *tokenname = "NSS Certificate DB"; + | ^ + lto1: all warnings being treated as errors + lto-wrapper: fatal error: gcc returned 1 exit status + +This might be a false positive since the tokenname != origtoken +condition should never be satisfied but it might also be an indication +that lto or other optimisations have elided some code that they +shouldn't have. Regardless tokenname is allocated on the stack and never +modified so the call to free() and the origtoken local aren't needed and +can be dropped. + +Signed-off-by: Chris Packham +--- + src/authvar.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/authvar.c b/src/authvar.c +index f9a7dce..ad13c1d 100644 +--- a/src/authvar.c ++++ b/src/authvar.c +@@ -268,7 +268,6 @@ main(int argc, char *argv[]) + authvar_context *ctxp = &ctx; + char *time_str = NULL; + char *tokenname = "NSS Certificate DB"; +- char *origtoken = tokenname; + char *certdir = "/etc/pki/pesign"; + SECStatus status; + +@@ -446,8 +445,6 @@ main(int argc, char *argv[]) + PORT_ErrorToString(PORT_GetError())); + exit(1); + } +- if (tokenname != origtoken) +- free(tokenname); + + if (action & SIGN) { + rc = find_certificate(ctx.cms_ctx, 1); +-- +2.51.2 + diff --git a/patches/pesign/series b/patches/pesign/series index ccd457ba3..054222450 100644 --- a/patches/pesign/series +++ b/patches/pesign/series @@ -4,6 +4,5 @@ brace-initialization.patch Fix-unsigned-char-changes-value-from-496-to-240.patch # https://github.com/rhboot/pesign/commit/c555fd74c009242c3864576bd5f17a1f8f4fdffd pesigcheck-Fix-a-wrong-assignment.patch - - - +# https://github.com/rhboot/pesign/pull/128 +authvar-Remove-unreachable-free.patch From 31b76f9d1c936ab6ba229278f1313d4868d08b1c Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 3 Nov 2025 13:45:43 +1300 Subject: [PATCH 15/15] grub: Bring in upstream patch for python detection Bring in an upstream patch that allows GRUB's build process to detect the correct python interpreter. Remove the forced setting of PYTHON and let the auto detection decide which interpreter to use. Signed-off-by: Chris Packham --- build-config/Makefile | 8 -- .../grub/2.04/autogen.sh-Detect-python.patch | 82 +++++++++++++++++++ patches/grub/2.04/series | 1 + 3 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 patches/grub/2.04/autogen.sh-Detect-python.patch diff --git a/build-config/Makefile b/build-config/Makefile index 57c90c9d1..122518dd2 100644 --- a/build-config/Makefile +++ b/build-config/Makefile @@ -515,14 +515,6 @@ ifeq ($(FIRMWARE_UPDATE_ENABLE),yes) include make/firmware-update.make endif -# Pre Debian 11 environments just had /usr/bin/python -# Now the environment distinguishes between python2 and python3 -# If 'python' is not present, default to python2 -ifeq (, $(shell which python )) - export PYTHON=python2 -endif - - #------------------------------------------------------------------------------- # # top level targets diff --git a/patches/grub/2.04/autogen.sh-Detect-python.patch b/patches/grub/2.04/autogen.sh-Detect-python.patch new file mode 100644 index 000000000..52be95f65 --- /dev/null +++ b/patches/grub/2.04/autogen.sh-Detect-python.patch @@ -0,0 +1,82 @@ +From 1ca7ec0b23bac89fa403353c13defb6247842680 Mon Sep 17 00:00:00 2001 +From: Petr Vorel +Date: Mon, 30 Aug 2021 11:53:17 +0200 +Subject: [PATCH] autogen.sh: Detect python + +It helps to avoid an error on distros which has only python3 binary: + ./autogen.sh: line 20: python: command not found + +Use python3 as the default as python2 is EOL since Jan 2020. However, +check also for python which is on most distros, if not all, python2 +because code still works on python2. + +Although it should not be needed keep the possibility to define PYTHON +variable. + +For detection use "command -v" which is POSIX and supported on all +common shells (bash, zsh, dash, busybox sh, mksh) instead requiring +"which" as an extra dependency (usable on containers). + +Update the INSTALL file too. + +Signed-off-by: Petr Vorel +Reviewed-by: Daniel Kiper +(cherry picked from commit 8f35208db4154ede690a18e408375815bbf320b7) +--- + INSTALL | 7 +++---- + autogen.sh | 17 +++++++++++++++-- + 2 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/INSTALL b/INSTALL +index 991479b52..4c88f8fbe 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -46,7 +46,7 @@ To build GRUB's graphical terminal (gfxterm), you need: + If you use a development snapshot or want to hack on GRUB you may + need the following. + +-* Python 2.6 or later ++* Python 3 (NOTE: python 2.6 should still work, but it's not tested) + * Autoconf 2.63 or later + * Automake 1.11 or later + +@@ -91,9 +91,8 @@ The simplest way to compile this package is: + + 3. Type `./bootstrap'. + +- * autogen.sh (called by bootstrap) uses python. By default the +- invocation is "python", but it can be overridden by setting the +- variable $PYTHON. ++ The autogen.sh (called by bootstrap) uses python. By default autodetect ++ it, but it can be overridden by setting the PYTHON variable. + + 4. Type `./configure' to configure the package for your system. + If you're using `csh' on an old version of System V, you might +diff --git a/autogen.sh b/autogen.sh +index ef43270fc..46508e942 100755 +--- a/autogen.sh ++++ b/autogen.sh +@@ -7,8 +7,21 @@ if [ ! -e grub-core/lib/gnulib/stdlib.in.h ]; then + exit 1 + fi + +-# Set ${PYTHON} to plain 'python' if not set already +-: ${PYTHON:=python} ++# Detect python ++if [ -z "$PYTHON" ]; then ++ for i in python3 python; do ++ if command -v "$i" > /dev/null 2>&1; then ++ PYTHON="$i" ++ echo "Using $PYTHON..." ++ break ++ fi ++ done ++ ++ if [ -z "$PYTHON" ]; then ++ echo "python not found." >&2 ++ exit 1 ++ fi ++fi + + export LC_COLLATE=C + unset LC_ALL diff --git a/patches/grub/2.04/series b/patches/grub/2.04/series index b4d512fee..46a8c406b 100644 --- a/patches/grub/2.04/series +++ b/patches/grub/2.04/series @@ -102,3 +102,4 @@ use-stdbool.patch build-Fix-Werror-array-bounds-array-subscript-0-is-o.patch types-Make-bool-generally-available.patch gentpl.py-Remove-.interp-section-from-.img-files.patch +autogen.sh-Detect-python.patch