* [PATCH master 01/39] efi: fix potential NULL dereference
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 02/39] efi: trace: fix EFI_EXIT2 to not evaluate output value on error Ahmad Fatoum
` (37 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
Add NULL check for name buffer before writing to it. When called with
name=NULL (for length query), the loop would dereference a NULL pointer.
Reported-by: clang-analyzer 19.1.7
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/efivar-filename.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/efi/efivar-filename.c b/efi/efivar-filename.c
index 984e40bc1c85..96a00ed001ff 100644
--- a/efi/efivar-filename.c
+++ b/efi/efivar-filename.c
@@ -79,6 +79,9 @@ int __efivarfs_parse_filename(const char *filename, efi_guid_t *vendor,
if (ret)
return ret;
+ if (!name)
+ return 0;
+
for (i = 0; i < *namelen - 1; i++)
name[i] = filename[i];
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 02/39] efi: trace: fix EFI_EXIT2 to not evaluate output value on error
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 01/39] efi: fix potential NULL dereference Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 03/39] efi: loader: fix CRC32 computation in table header update Ahmad Fatoum
` (36 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
EFI_EXIT2(ret, val) unconditionally evaluates 'val' for debug output,
even when ret indicates an error. This leads to NULL pointer
dereferences at 13 call sites in boot.c where the output pointer is
only valid on success (e.g., *memory after failed allocate_pages,
*event after failed create_event).
Fix by reusing EFI_EXIT() on the error path, which skips evaluation
of the second argument entirely. The extended output with the value
is only printed on the success path.
Reported-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/efi/loader/trace.h | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/include/efi/loader/trace.h b/include/efi/loader/trace.h
index 93bba7bb88c7..4acf7c1634cc 100644
--- a/include/efi/loader/trace.h
+++ b/include/efi/loader/trace.h
@@ -44,9 +44,13 @@ const char *__efi_nesting_dec(void);
#ifndef EFI_EXIT2
#define EFI_EXIT2(ret, val) ({ \
typeof(ret) _r = ret; \
- __EFI_PRINT("%sEFI: Exit: %s: %s (%u) = 0x%llx\n", __efi_nesting_dec(), \
- __func__, efi_strerror((uintptr_t)_r), (u32)((uintptr_t) _r & ~EFI_ERROR_MASK), \
- (u64)(uintptr_t)(val)); \
+ if (EFI_ERROR(_r)) \
+ EFI_EXIT(_r); \
+ else \
+ __EFI_PRINT("%sEFI: Exit: %s: %s (%u) = 0x%llx\n", __efi_nesting_dec(), \
+ __func__, efi_strerror((uintptr_t)_r), \
+ (u32)((uintptr_t) _r & ~EFI_ERROR_MASK), \
+ (u64)(uintptr_t)(val)); \
_r; \
})
#endif
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 03/39] efi: loader: fix CRC32 computation in table header update
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 01/39] efi: fix potential NULL dereference Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 02/39] efi: trace: fix EFI_EXIT2 to not evaluate output value on error Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 04/39] efi: loader: fix pointer vs value comparison in free_efi_only Ahmad Fatoum
` (35 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
The CRC32 is computed over the full table header, which includes the
crc32 field itself. Without zeroing the field first, the old CRC
value is included as input data in the new computation, producing
incorrect results on any update after the first.
The UEFI specification requires the field to be zero during CRC32
computation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/table.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/efi/loader/table.c b/efi/loader/table.c
index 0c200365b835..dc2ec893cb2e 100644
--- a/efi/loader/table.c
+++ b/efi/loader/table.c
@@ -13,6 +13,7 @@
*/
void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table)
{
+ table->crc32 = 0;
table->crc32 = __pi_crc32(0, table, table->headersize);
}
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 04/39] efi: loader: fix pointer vs value comparison in free_efi_only
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (2 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 03/39] efi: loader: fix CRC32 computation in table header update Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 05/39] efi: loader: fix disk write return value check Ahmad Fatoum
` (34 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
The check 'nfreed >= 0' compares the pointer itself (which is always
true for valid pointers) instead of the pointed-to value. This causes
the freed counter to be incremented even after it has been set to -1
to indicate an error.
Fix by dereferencing the pointer: '*nfreed >= 0'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/memory.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/loader/memory.c b/efi/loader/memory.c
index 6ed7f76714f9..e8dfd59ee8ca 100644
--- a/efi/loader/memory.c
+++ b/efi/loader/memory.c
@@ -275,7 +275,7 @@ static int free_efi_only(struct resource *res, void *data)
return false;
}
- if (nfreed >= 0)
+ if (*nfreed >= 0)
++*nfreed;
return true;
}
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 05/39] efi: loader: fix disk write return value check
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (3 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 04/39] efi: loader: fix pointer vs value comparison in free_efi_only Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 06/39] efi: loader: fix EFI_ENTRY/EFI_EXIT ordering in efi_set_time Ahmad Fatoum
` (33 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
cdev_write() returns the number of bytes written on success (a
positive value), not zero. Using 'ret ?' treats any successful write
as an error. Fix by checking 'ret < 0' which correctly detects only
actual errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/disk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/loader/protocols/disk.c b/efi/loader/protocols/disk.c
index 835dee4e2e26..b4a3a7ab0c97 100644
--- a/efi/loader/protocols/disk.c
+++ b/efi/loader/protocols/disk.c
@@ -99,7 +99,7 @@ static efi_status_t EFIAPI efi_disk_write(struct efi_block_io_protocol *this,
ret = cdev_write(disk->cdev, buffer, buffer_size, lba << disk->blockbits, 0);
- return ret ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+ return ret < 0 ? EFI_DEVICE_ERROR : EFI_SUCCESS;
}
static efi_status_t EFIAPI efi_disk_flush(struct efi_block_io_protocol *this)
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 06/39] efi: loader: fix EFI_ENTRY/EFI_EXIT ordering in efi_set_time
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (4 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 05/39] efi: loader: fix disk write return value check Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 07/39] efi: runtime: fix missing EFI_EXIT in efirt_query_variable_info Ahmad Fatoum
` (32 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
When CONFIG_EFI_LOADER_SET_TIME is disabled, the function calls
EFI_EXIT(EFI_UNSUPPORTED) before EFI_ENTRY, corrupting the EFI
nesting depth counter. Move EFI_ENTRY before the IS_ENABLED check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/runtime.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/efi/loader/runtime.c b/efi/loader/runtime.c
index 4b3cb6df1350..f0fbd263fe55 100644
--- a/efi/loader/runtime.c
+++ b/efi/loader/runtime.c
@@ -240,11 +240,11 @@ static efi_status_t EFIAPI efi_set_time_boottime(struct efi_time *time)
struct rtc_time tm;
struct rtc_device *rtc;
+ EFI_ENTRY("%p", time);
+
if (!IS_ENABLED(CONFIG_EFI_LOADER_SET_TIME))
return EFI_EXIT(EFI_UNSUPPORTED);
- EFI_ENTRY("%p", time);
-
if (efi_validate_time(time)) {
ret = EFI_INVALID_PARAMETER;
goto out;
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 07/39] efi: runtime: fix missing EFI_EXIT in efirt_query_variable_info
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (5 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 06/39] efi: loader: fix EFI_ENTRY/EFI_EXIT ordering in efi_set_time Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 08/39] efi: loader: fix file handle leak in efi_file_from_path Ahmad Fatoum
` (31 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
Two early return paths after EFI_ENTRY() return raw EFI status codes
without going through EFI_EXIT(), corrupting the nesting depth
counter. Wrap both returns with EFI_EXIT().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/runtime/services.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/efi/runtime/services.c b/efi/runtime/services.c
index 11a1c5cb6cb6..5044e16c7c5c 100644
--- a/efi/runtime/services.c
+++ b/efi/runtime/services.c
@@ -241,11 +241,11 @@ efirt_query_variable_info(u32 attributes,
EFI_ENTRY(L"");
if (!(attributes & EFI_VARIABLE_RUNTIME_ACCESS))
- return EFI_INVALID_PARAMETER;
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
if ((attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS |
EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS)))
- return EFI_UNSUPPORTED;
+ return EFI_EXIT(EFI_UNSUPPORTED);
ret = efi_query_variable_info_int(attributes,
maximum_variable_storage_size,
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 08/39] efi: loader: fix file handle leak in efi_file_from_path
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (6 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 07/39] efi: runtime: fix missing EFI_EXIT in efirt_query_variable_info Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 09/39] efi: loader: fix missing field init in deferred protocol add Ahmad Fatoum
` (30 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
Two early return paths in the device path traversal loop fail to
close the current file handle 'f' before returning NULL:
- when the device path node has an invalid length
- when memdup fails to allocate the filename
Add f->close(f) calls before both returns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/file.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/efi/loader/protocols/file.c b/efi/loader/protocols/file.c
index 03d2dc3a0d38..e002057d59ea 100644
--- a/efi/loader/protocols/file.c
+++ b/efi/loader/protocols/file.c
@@ -968,17 +968,23 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
* protocol member functions to be aligned. So memcpy it
* unconditionally
*/
- if (fdp->header.length <= offsetof(struct efi_device_path_file_path, path_name))
+ if (fdp->header.length <= offsetof(struct efi_device_path_file_path, path_name)) {
+ f->close(f);
return NULL;
+ }
filename_sz = fdp->header.length -
offsetof(struct efi_device_path_file_path, path_name);
filename = memdup(fdp->path_name, filename_sz);
- if (!filename)
+ if (!filename) {
+ f->close(f);
return NULL;
+ }
efiret = f->open(f, &f2, filename, EFI_FILE_MODE_READ, 0);
free(filename);
- if (efiret != EFI_SUCCESS)
+ if (efiret != EFI_SUCCESS) {
+ f->close(f);
return NULL;
+ }
fp = efi_dp_next(fp);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 09/39] efi: loader: fix missing field init in deferred protocol add
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (7 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 08/39] efi: loader: fix file handle leak in efi_file_from_path Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 10/39] efi: loader: fix memory leak in efi_var_to_file Ahmad Fatoum
` (29 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_add_root_node_protocol_deferred() allocates a deferred context
but never stores the protocol and interface pointers in it. When
the deferred callback fires, it calls efi_add_protocol with zero
protocol GUID and NULL interface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/setup.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/efi/loader/setup.c b/efi/loader/setup.c
index a24d3044afdc..e27929aaeae9 100644
--- a/efi/loader/setup.c
+++ b/efi/loader/setup.c
@@ -117,6 +117,8 @@ void efi_add_root_node_protocol_deferred(const efi_guid_t *protocol, const void
deferred->base.cb = add_protocol;
deferred->base.data = &deferred->ctx;
+ deferred->ctx.protocol = protocol;
+ deferred->ctx.interface = interface;
list_add_tail(&deferred->base.list, &efi_deferred_cbs);
}
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 10/39] efi: loader: fix memory leak in efi_var_to_file
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (8 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 09/39] efi: loader: fix missing field init in deferred protocol add Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 11/39] efi: loader: fix multiple bugs in efi_loader_bootm Ahmad Fatoum
` (28 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
On the success path, the function returns directly at line 87,
bypassing the 'out:' label where 'buf' is freed. Every successful
variable persist leaks the collected variable buffer.
Fix by setting efiret to EFI_SUCCESS and jumping to the out label.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/efi_var_file.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/efi/loader/efi_var_file.c b/efi/loader/efi_var_file.c
index e0dec999b779..c0150baa27ac 100644
--- a/efi/loader/efi_var_file.c
+++ b/efi/loader/efi_var_file.c
@@ -84,7 +84,8 @@ efi_status_t efi_var_to_file(void)
goto error;
}
- return 0;
+ efiret = EFI_SUCCESS;
+ goto out;
error:
if (efiret != EFI_SUCCESS)
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 11/39] efi: loader: fix multiple bugs in efi_loader_bootm
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (9 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 10/39] efi: loader: fix memory leak in efi_var_to_file Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 12/39] efi: loader: fix return type and memory leak in efi_smbios_register Ahmad Fatoum
` (27 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
Fix several issues:
- ERR_PTR(-efi_errno(ret)) uses 'ret' which is 0 at that point
instead of 'efiret' which holds the actual error.
- Two return statements (PTR_ERR(fdt) and efi_install_fdt error)
bypass the 'out:' cleanup label, leaking file_path, load_option,
and the source sdram region. Replace with goto out.
- efi_set_watchdog() and __efi_start_image() return efi_status_t
(unsigned long, 64-bit on ARM64) but were stored in 'int ret',
truncating the value. Use 'efiret' for these calls. Also fix the
success return path to convert efiret properly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/bootm.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/efi/loader/bootm.c b/efi/loader/bootm.c
index da664847def8..a74002e292f7 100644
--- a/efi/loader/bootm.c
+++ b/efi/loader/bootm.c
@@ -233,19 +233,21 @@ static int efi_loader_bootm(struct image_data *data)
efiret = efi_init_obj_list();
if (efiret) {
pr_err("Cannot initialize UEFI sub-system: %pe\n",
- ERR_PTR(-efi_errno(ret)));
+ ERR_PTR(-efi_errno(efiret)));
goto out;
}
ret = -EINVAL;
fdt = bootm_get_devicetree(data);
- if (IS_ERR(fdt))
- return PTR_ERR(fdt);
+ if (IS_ERR(fdt)) {
+ ret = PTR_ERR(fdt);
+ goto out;
+ }
if (fdt) {
ret = efi_install_fdt(fdt);
if (ret)
- return ret;
+ goto out;
}
efiret = efi_install_initrd(data, source);
@@ -280,17 +282,17 @@ static int efi_loader_bootm(struct image_data *data)
* Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
* 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
*/
- ret = efi_set_watchdog(300);
- if (ret != EFI_SUCCESS) {
+ efiret = efi_set_watchdog(300);
+ if (efiret != EFI_SUCCESS) {
pr_err("failed to set watchdog timer\n");
goto out;
}
/* Call our payload! */
- ret = __efi_start_image(handle, &exit_data_size, &exit_data, flags);
- if (ret != EFI_SUCCESS) {
+ efiret = __efi_start_image(handle, &exit_data_size, &exit_data, flags);
+ if (efiret != EFI_SUCCESS) {
pr_err("## Application failed, r = %lu\n",
- ret & ~EFI_ERROR_MASK);
+ efiret & ~EFI_ERROR_MASK);
if (exit_data) {
pr_err("## %ls\n", exit_data);
efi_free_pool(exit_data);
@@ -311,7 +313,7 @@ static int efi_loader_bootm(struct image_data *data)
/* Control is returned to us, disable EFI watchdog */
efi_set_watchdog(0);
- return ret;
+ return -efi_errno(efiret);
out:
efi_initrd_unregister();
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 12/39] efi: loader: fix return type and memory leak in efi_smbios_register
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (10 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 11/39] efi: loader: fix multiple bugs in efi_loader_bootm Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 13/39] efi: loader: fix memory leak in efi_dp_split_file_path Ahmad Fatoum
` (26 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
The function returns efi_status_t but returned -EINVAL (a POSIX error
code) on SMBIOS table write failure. Additionally, the EFI pages
allocated for the table were leaked on this error path.
Return EFI_LOAD_ERROR and free the allocated pages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/smbios.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/efi/loader/smbios.c b/efi/loader/smbios.c
index 81ba77c24017..d8a708978e11 100644
--- a/efi/loader/smbios.c
+++ b/efi/loader/smbios.c
@@ -40,7 +40,8 @@ static efi_status_t efi_smbios_register(void *data)
if (!write_smbios_table(buf)) {
pr_err("Failed to write SMBIOS table\n");
- return -EINVAL;
+ efi_free_pages(memory, efi_size_in_pages(TABLE_SIZE));
+ return EFI_LOAD_ERROR;
}
/* Install SMBIOS information as configuration table */
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 13/39] efi: loader: fix memory leak in efi_dp_split_file_path
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (11 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 12/39] efi: loader: fix return type and memory leak in efi_smbios_register Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 14/39] efi: loader: fix HII string table realloc and memset bugs Ahmad Fatoum
` (25 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
When efi_dp_dup(p) fails to duplicate the file path portion, the
function returns EFI_OUT_OF_RESOURCES without freeing the already
duplicated device path 'dp'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/devicepath.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/efi/loader/devicepath.c b/efi/loader/devicepath.c
index 17c659e4c5d8..a12ab24caaa1 100644
--- a/efi/loader/devicepath.c
+++ b/efi/loader/devicepath.c
@@ -465,8 +465,10 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
goto out;
}
fp = efi_dp_dup(p);
- if (!fp)
+ if (!fp) {
+ free(dp);
return EFI_OUT_OF_RESOURCES;
+ }
p->type = DEVICE_PATH_TYPE_END;
p->sub_type = DEVICE_PATH_SUB_TYPE_END;
p->length = sizeof(*p);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 14/39] efi: loader: fix HII string table realloc and memset bugs
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (12 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 13/39] efi: loader: fix memory leak in efi_dp_split_file_path Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 15/39] efi: loader: fix format specifier and missing EFI_EXIT in boot services Ahmad Fatoum
` (24 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
Three bugs in the set_string HII protocol implementation when
expanding the string table:
1. The memset used stbl->strings which still points to the old
(potentially freed) buffer after realloc. Move the
'stbl->strings = buf' assignment before the memset.
2. The memset offset was string_id-1 (the target slot) instead of
stbl->nstrings (the first uninitialized slot), leaving a gap of
uninitialized entries.
3. stbl->nstrings was never updated after expansion, causing every
subsequent set_string to re-expand and re-zero the table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/hii.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/efi/loader/protocols/hii.c b/efi/loader/protocols/hii.c
index f35489eba283..f9719a91a94a 100644
--- a/efi/loader/protocols/hii.c
+++ b/efi/loader/protocols/hii.c
@@ -977,10 +977,11 @@ set_string(const struct efi_hii_string_protocol *this,
if (!buf)
return EFI_EXIT(EFI_OUT_OF_RESOURCES);
- memset(&stbl->strings[string_id - 1], 0,
+ stbl->strings = buf;
+ memset(&stbl->strings[stbl->nstrings], 0,
(string_id - stbl->nstrings)
* sizeof(stbl->strings[0]));
- stbl->strings = buf;
+ stbl->nstrings = string_id;
}
str = u16_strdup(string);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 15/39] efi: loader: fix format specifier and missing EFI_EXIT in boot services
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (13 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 14/39] efi: loader: fix HII string table realloc and memset bugs Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 16/39] efi: fix unreachable free in efi_set_variable_printf Ahmad Fatoum
` (23 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
Fix efi_create_event_ext using %lu for efi_uintn_t (which is size_t),
should be %zx.
Fix efi_disconnect_controller returning 'r' directly without
EFI_EXIT after EFI_ENTRY, corrupting the nesting depth counter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/boot.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/efi/loader/boot.c b/efi/loader/boot.c
index 93a3412f5794..adeb2ff337b3 100644
--- a/efi/loader/boot.c
+++ b/efi/loader/boot.c
@@ -729,7 +729,7 @@ static efi_status_t EFIAPI efi_create_event_ext(
void *context),
void *notify_context, struct efi_event **event)
{
- EFI_ENTRY("%d, 0x%lu, %p, %p", type, notify_tpl, notify_function,
+ EFI_ENTRY("%d, 0x%zx, %p, %p", type, notify_tpl, notify_function,
notify_context);
return EFI_EXIT2(efi_create_event(type, notify_tpl, notify_function,
notify_context, NULL, event), *event);
@@ -3741,7 +3741,7 @@ efi_status_t EFIAPI efi_disconnect_controller(
&number_of_children,
&child_handle_buffer);
if (r != EFI_SUCCESS)
- return r;
+ return EFI_EXIT(r);
sole_child = (number_of_children == 1);
if (child_handle) {
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 16/39] efi: fix unreachable free in efi_set_variable_printf
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (14 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 15/39] efi: loader: fix format specifier and missing EFI_EXIT in boot services Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 17/39] efi: payload: fix missing NULL check after read_file in handover Ahmad Fatoum
` (22 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
The return statement before the free() calls makes them unreachable,
leaking both buf and buf16 on every call. Store the return value,
free the buffers, then return.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/efivar.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/efi/efivar.c b/efi/efivar.c
index 1e82afcb8798..16c3228dc79b 100644
--- a/efi/efivar.c
+++ b/efi/efivar.c
@@ -96,18 +96,21 @@ int efi_set_variable_printf(char *name, efi_guid_t *vendor, const char *fmt, ...
va_list args;
char *buf;
wchar_t *buf16;
+ int ret;
va_start(args, fmt);
buf = xvasprintf(fmt, args);
va_end(args);
buf16 = xstrdup_char_to_wchar(buf);
- return efi_set_variable(name, vendor,
+ ret = efi_set_variable(name, vendor,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS, buf16,
(strlen(buf)+1) * sizeof(wchar_t));
free(buf);
free(buf16);
+
+ return ret;
}
int efi_set_variable_uint64_le(char *name, efi_guid_t *vendor, uint64_t value)
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 17/39] efi: payload: fix missing NULL check after read_file in handover
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (15 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 16/39] efi: fix unreachable free in efi_set_variable_printf Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 18/39] efi: payload: fix EFI page leak in efi_read_file Ahmad Fatoum
` (21 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
read_file() can return NULL on failure, but the result is used
without checking, leading to a NULL pointer dereference in the
subsequent xmemalign/memcpy. Additionally, 'size' would be
uninitialized, causing xmemalign to allocate an arbitrary amount.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/handover.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/efi/payload/handover.c b/efi/payload/handover.c
index c7f1deabfffa..bef726ae303c 100644
--- a/efi/payload/handover.c
+++ b/efi/payload/handover.c
@@ -142,6 +142,10 @@ static int do_bootm_efi(struct image_data *data)
if (data->initrd_file) {
tmp = read_file(data->initrd_file, &size);
+ if (!tmp) {
+ ret = -errno;
+ goto err_free;
+ }
initrd = xmemalign(PAGE_SIZE, PAGE_ALIGN(size));
memcpy(initrd, tmp, size);
memset(initrd + size, 0, PAGE_ALIGN(size) - size);
@@ -169,10 +173,8 @@ static int do_bootm_efi(struct image_data *data)
printf("...\n");
if (data->dryrun) {
- BS->unload_image(handle);
- free(boot_header);
- free(initrd);
- return 0;
+ ret = 0;
+ goto err_free;
}
efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
@@ -182,6 +184,12 @@ static int do_bootm_efi(struct image_data *data)
linux_efi_handover(handle, boot_header);
return 0;
+
+err_free:
+ BS->unload_image(handle);
+ free(boot_header);
+ free(initrd);
+ return ret;
}
struct image_handler efi_x86_linux_handle_handover = {
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 18/39] efi: payload: fix EFI page leak in efi_read_file
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (16 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 17/39] efi: payload: fix missing NULL check after read_file in handover Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 19/39] efi: payload: fix inverted error check after state_load Ahmad Fatoum
` (20 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
When read_file_into_buf() fails, the function returns NULL without
freeing the EFI pages allocated by BS->allocate_pages(). Free them
before returning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/image.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/efi/payload/image.c b/efi/payload/image.c
index 976327e08842..83094cda6d89 100644
--- a/efi/payload/image.c
+++ b/efi/payload/image.c
@@ -55,8 +55,10 @@ static void *efi_read_file(const char *file, size_t *size)
buf = efi_phys_to_virt(mem);
ret = read_file_into_buf(file, buf, s.st_size);
- if (ret < 0)
+ if (ret < 0) {
+ BS->free_pages(mem, DIV_ROUND_UP(s.st_size, EFI_PAGE_SIZE));
return NULL;
+ }
*size = ret;
return buf;
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 19/39] efi: payload: fix inverted error check after state_load
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (17 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 18/39] efi: payload: fix EFI page leak in efi_read_file Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 20/39] efi: fix out-of-bounds read in device path unknown node printing Ahmad Fatoum
` (19 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
The condition 'ret != -ENOMEDIUM' is true for ret == 0 (success),
causing a spurious warning on every successful state load. Add a
check for ret != 0 first.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/init.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/payload/init.c b/efi/payload/init.c
index d8a4410f22e6..f74ac4966fb1 100644
--- a/efi/payload/init.c
+++ b/efi/payload/init.c
@@ -316,7 +316,7 @@ static int efi_late_init(void)
return PTR_ERR(state);
ret = state_load(state);
- if (ret != -ENOMEDIUM)
+ if (ret && ret != -ENOMEDIUM)
pr_warn("Failed to load persistent state, continuing with defaults, %d\n",
ret);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 20/39] efi: fix out-of-bounds read in device path unknown node printing
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (18 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 19/39] efi: payload: fix inverted error check after state_load Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 21/39] efi: payload: fix wrong page count in efi_unload_fdt Ahmad Fatoum
` (18 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
dev_path_node_unknown() initializes 'value' to point past the 4-byte
device path header (type + sub_type + length), but uses
Path->length as the loop count. Since Path->length includes the
header, the loop reads 4 bytes beyond the node's data.
Subtract the header size from the loop bound.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/devicepath.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/devicepath.c b/efi/devicepath.c
index 8298073572ae..31a509f99e42 100644
--- a/efi/devicepath.c
+++ b/efi/devicepath.c
@@ -622,7 +622,7 @@ dev_path_node_unknown(struct string *str, const void *dev_path)
break;
}
}
- length = Path->length;
+ length = Path->length - sizeof(struct efi_device_path);
for (index = 0; index < length; index++) {
if (index == 0)
cprintf(str, ",0x");
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 21/39] efi: payload: fix wrong page count in efi_unload_fdt
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (19 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 20/39] efi: fix out-of-bounds read in device path unknown node printing Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 22/39] efi: fix out-of-bounds read in 1394 device path printing Ahmad Fatoum
` (17 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_load_fdt() allocates with DIV_ROUND_UP(SZ_2M, EFI_PAGE_SIZE) = 512
pages, but efi_unload_fdt() passes the raw byte count SZ_2M (2097152)
as the page count to free_pages(). This frees 2 million pages (~8 GB)
instead of 512 pages (2 MB), corrupting the firmware memory map.
Use DIV_ROUND_UP(SZ_2M, EFI_PAGE_SIZE) consistently in both allocation
and deallocation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/bootm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
index f4e6e6324bcd..623d9f621ac0 100644
--- a/efi/payload/bootm.c
+++ b/efi/payload/bootm.c
@@ -228,7 +228,7 @@ static void efi_unload_fdt(void *fdt)
return;
BS->install_configuration_table(&efi_fdt_guid, NULL);
- BS->free_pages(efi_virt_to_phys(fdt), SZ_2M);
+ BS->free_pages(efi_virt_to_phys(fdt), DIV_ROUND_UP(SZ_2M, EFI_PAGE_SIZE));
}
static int do_bootm_efi_stub(struct image_data *data)
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 22/39] efi: fix out-of-bounds read in 1394 device path printing
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (20 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 21/39] efi: payload: fix wrong page count in efi_unload_fdt Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 23/39] efi: loader: initialize block IO ops before installing protocol Ahmad Fatoum
` (16 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
The F1394 device path Guid field is a u64 (8 bytes), but it was printed
with %pUl which expects a 16-byte efi_guid_t pointer. This reads 8
bytes past the field boundary.
Use %016llx to correctly format the u64 value.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/devicepath.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/devicepath.c b/efi/devicepath.c
index 31a509f99e42..bf65325fed8a 100644
--- a/efi/devicepath.c
+++ b/efi/devicepath.c
@@ -242,7 +242,7 @@ dev_path1394(struct string *str, const void *dev_path)
const struct efi_device_path_f1394 *F1394;
F1394 = dev_path;
- cprintf(str, "1394(%pUl)", &F1394->Guid);
+ cprintf(str, "1394(0x%016llx)", F1394->Guid);
}
static void
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 23/39] efi: loader: initialize block IO ops before installing protocol
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (21 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 22/39] efi: fix out-of-bounds read in 1394 device path printing Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 24/39] efi: runtime: fix variable store bounds check to account for alignment Ahmad Fatoum
` (15 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_disk_add_cdev() installs the EFI_BLOCK_IO_PROTOCOL with
efi_install_multiple_protocol_interfaces() before populating the ops
structure and media fields. Between installation and initialization,
any consumer of the protocol (e.g., efi_simple_file_system() called
immediately after) would see zeroed-out function pointers.
Move the ops, media, and cdev initialization before the protocol
installation so the interface is fully populated when it becomes
visible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/disk.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/efi/loader/protocols/disk.c b/efi/loader/protocols/disk.c
index b4a3a7ab0c97..5494f9197cb4 100644
--- a/efi/loader/protocols/disk.c
+++ b/efi/loader/protocols/disk.c
@@ -248,6 +248,18 @@ static efi_status_t efi_disk_add_cdev(efi_handle_t parent,
diskobj->dp = efi_dp_from_cdev(cdev, true);
}
+ diskobj->media.removable_media = removable;
+ diskobj->media.media_present = true;
+ diskobj->media.read_only = cdev->flags & DEVFS_PARTITION_READONLY;
+ diskobj->media.block_size = 512;
+ diskobj->media.io_align = 512;
+ diskobj->media.last_block = cdev->size / diskobj->media.block_size - 1;
+
+ diskobj->ops = block_io_disk_template;
+ diskobj->ops.media = &diskobj->media;
+
+ diskobj->cdev = cdev;
+
/*
* Install the device path and the block IO protocol.
*
@@ -272,18 +284,6 @@ static efi_status_t efi_disk_add_cdev(efi_handle_t parent,
return ret;
}
- diskobj->media.removable_media = removable;
- diskobj->media.media_present = true;
- diskobj->media.read_only = cdev->flags & DEVFS_PARTITION_READONLY;
- diskobj->media.block_size = 512;
- diskobj->media.io_align = 512;
- diskobj->media.last_block = cdev->size / diskobj->media.block_size - 1;
-
- diskobj->ops = block_io_disk_template;
- diskobj->ops.media = &diskobj->media;
-
- diskobj->cdev = cdev;
-
if (disk)
*disk = diskobj;
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 24/39] efi: runtime: fix variable store bounds check to account for alignment
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (22 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 23/39] efi: loader: initialize block IO ops before installing protocol Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 25/39] efi: fix Fibre Channel device path type vs sub_type comparison Ahmad Fatoum
` (14 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_var_mem_ins() checks whether the new variable fits in the buffer,
but doesn't account for the up-to-7 bytes of ALIGN(..., 8) padding
that is applied when computing the final buffer length. This means a
variable insertion at the boundary of available space can write past
efi_var_buf_rtsize.
Use ALIGN() in the bounds check to match the actual space consumption.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/runtime/efi_var_mem.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/efi/runtime/efi_var_mem.c b/efi/runtime/efi_var_mem.c
index 83b5c53b063b..9752f1ca5fa4 100644
--- a/efi/runtime/efi_var_mem.c
+++ b/efi/runtime/efi_var_mem.c
@@ -192,8 +192,8 @@ efi_status_t __efi_runtime efi_var_mem_ins(
var_name_len = u16_strlen(variable_name) + 1;
data = var->name + var_name_len;
- if ((uintptr_t)data - (uintptr_t)efi_var_buf + size1 + size2 >
- efi_var_buf_rtsize)
+ if (ALIGN((uintptr_t)data + size1 + size2, 8) -
+ (uintptr_t)efi_var_buf > efi_var_buf_rtsize)
return EFI_OUT_OF_RESOURCES;
var->attr = attributes;
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 25/39] efi: fix Fibre Channel device path type vs sub_type comparison
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (23 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 24/39] efi: runtime: fix variable store bounds check to account for alignment Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 26/39] efi: loader: fix file open mode always setting O_RDWR Ahmad Fatoum
` (13 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
dev_path_fibre() uses device_path_type() to distinguish FibreChannel
from FibreChannelEx, but device_path_type() returns the major type
field (DEVICE_PATH_TYPE_MESSAGING_DEVICE = 0x03), not the sub_type.
Since DEVICE_PATH_SUB_TYPE_MSG_FIBRECHANNEL also happens to be in the
messaging range, the comparison is coincidentally always true, making
FibreChannelEx paths incorrectly display as "Fibre" instead of
"FibreEx".
Compare header.sub_type directly to get the correct behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/devicepath.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/devicepath.c b/efi/devicepath.c
index bf65325fed8a..131c3df16641 100644
--- a/efi/devicepath.c
+++ b/efi/devicepath.c
@@ -232,7 +232,7 @@ dev_path_fibre(struct string *str, const void *dev_path)
Fibre = dev_path;
cprintf(str, "Fibre%s(0x%016llx,0x%016llx)",
- device_path_type(&Fibre->header) ==
+ Fibre->header.sub_type ==
DEVICE_PATH_SUB_TYPE_MSG_FIBRECHANNEL ? "" : "Ex", Fibre->WWN, Fibre->Lun);
}
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 26/39] efi: loader: fix file open mode always setting O_RDWR
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (24 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 25/39] efi: fix Fibre Channel device path type vs sub_type comparison Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 27/39] efi: loader: fix NULL pointer dereference when deleting root volume handle Ahmad Fatoum
` (12 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_file_open_int() checks (open_mode & (EFI_FILE_MODE_READ |
EFI_FILE_MODE_WRITE)) which is always true for any valid open mode
since EFI_FILE_MODE_READ is always set. This means files opened with
only EFI_FILE_MODE_READ get O_RDWR instead of O_RDONLY.
Check only for EFI_FILE_MODE_WRITE to correctly distinguish read-only
from read-write opens.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/file.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/loader/protocols/file.c b/efi/loader/protocols/file.c
index e002057d59ea..93700d2d3bdc 100644
--- a/efi/loader/protocols/file.c
+++ b/efi/loader/protocols/file.c
@@ -113,7 +113,7 @@ static struct efi_file_handle *file_open(struct file_handle *parent,
dirfd = parent->dir ? parent->fd : parent->parent->fd;
- if (open_mode & (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE))
+ if (open_mode & EFI_FILE_MODE_WRITE)
flags |= O_RDWR;
else
flags |= O_RDONLY;
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 27/39] efi: loader: fix NULL pointer dereference when deleting root volume handle
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (25 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 26/39] efi: loader: fix file open mode always setting O_RDWR Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 28/39] efi: loader: fix memory leak of variable file buffer on success Ahmad Fatoum
` (11 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_file_delete() unconditionally dereferences fh->parent->fd, but the
root volume handle created by efi_open_volume() has fh->parent = NULL.
If a UEFI application calls Delete() on the root handle, this crashes.
Check for a NULL parent and return EFI_WARN_DELETE_FAILURE, as the root
volume cannot be deleted.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/file.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/efi/loader/protocols/file.c b/efi/loader/protocols/file.c
index 93700d2d3bdc..0796b3f0c26a 100644
--- a/efi/loader/protocols/file.c
+++ b/efi/loader/protocols/file.c
@@ -285,6 +285,11 @@ static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file)
file_close(fh);
+ if (!fh->parent) {
+ free(fh);
+ return EFI_EXIT(EFI_WARN_DELETE_FAILURE);
+ }
+
ret = unlinkat(fh->parent->fd, fh->path, flags);
free(fh);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 28/39] efi: loader: fix memory leak of variable file buffer on success
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (26 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 27/39] efi: loader: fix NULL pointer dereference when deleting root volume handle Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 29/39] efi: loader: fix memory leak in efi_var_collect on buffer overflow Ahmad Fatoum
` (10 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_var_from_file() returns EFI_SUCCESS directly without freeing the
buf allocated by read_fd(). The free only happens on the error path.
Use the common error label for both paths so buf is always freed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/efi_var_file.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/loader/efi_var_file.c b/efi/loader/efi_var_file.c
index c0150baa27ac..12543bce2851 100644
--- a/efi/loader/efi_var_file.c
+++ b/efi/loader/efi_var_file.c
@@ -180,7 +180,7 @@ efi_status_t efi_var_from_file(int dirfd, const char *filename)
goto error;
}
- return EFI_SUCCESS;
+ ret = EFI_SUCCESS;
error:
free(buf);
return ret;
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 29/39] efi: loader: fix memory leak in efi_var_collect on buffer overflow
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (27 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 28/39] efi: loader: fix memory leak of variable file buffer on success Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 30/39] efi: fix signed format specifier for uint64_t timestamp Ahmad Fatoum
` (9 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
When the variable buffer is too small, efi_var_collect() returns
EFI_BUFFER_TOO_SMALL directly without freeing the buf allocated by
calloc() at the top of the function.
Free buf before returning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/efi_var_common.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/efi/loader/efi_var_common.c b/efi/loader/efi_var_common.c
index bd5af007ed9c..4c6cb77e7c2c 100644
--- a/efi/loader/efi_var_common.c
+++ b/efi/loader/efi_var_common.c
@@ -430,8 +430,10 @@ efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *
efi_status_t ret;
if ((uintptr_t)buf + len <=
- (uintptr_t)var->name + old_var_name_length)
+ (uintptr_t)var->name + old_var_name_length) {
+ free(buf);
return EFI_BUFFER_TOO_SMALL;
+ }
var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name;
memcpy(var->name, old_var->name, old_var_name_length);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 30/39] efi: fix signed format specifier for uint64_t timestamp
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (28 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 29/39] efi: loader: fix memory leak in efi_var_collect on buffer overflow Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 31/39] efi: payload: fix possible memory leaks during init Ahmad Fatoum
` (8 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_set_variable_usec() uses %lld (signed) to format a uint64_t value.
Values above LLONG_MAX would be printed as negative numbers. Use %llu
to match the unsigned type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/efivar.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/efivar.c b/efi/efivar.c
index 16c3228dc79b..c302ceec621e 100644
--- a/efi/efivar.c
+++ b/efi/efivar.c
@@ -82,7 +82,7 @@ int efi_set_variable_usec(char *name, efi_guid_t *vendor, uint64_t usec)
char buf[20];
wchar_t buf16[40];
- snprintf(buf, sizeof(buf), "%lld", usec);
+ snprintf(buf, sizeof(buf), "%llu", usec);
strcpy_char_to_wchar(buf16, buf);
return efi_set_variable(name, vendor,
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 31/39] efi: payload: fix possible memory leaks during init
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (29 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 30/39] efi: fix signed format specifier for uint64_t timestamp Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 32/39] efi: payload: protect against missing state alias Ahmad Fatoum
` (7 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_get_boot(): buf from efi_get_global_var() is never freed after
parsing the Boot variable. Add free(buf) before return.
efi_late_init(): the flat DTB blob from read_file() is never freed
after of_unflatten_dtb() creates the unflattened tree. Free it
immediately after unflattening.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/init.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/efi/payload/init.c b/efi/payload/init.c
index f74ac4966fb1..03f831840de7 100644
--- a/efi/payload/init.c
+++ b/efi/payload/init.c
@@ -96,6 +96,8 @@ static struct efi_boot *efi_get_boot(int num)
printf("path: %s\n", device_path_to_str(boot->path, true));
+ free(buf);
+
return boot;
}
@@ -301,6 +303,8 @@ static int efi_late_init(void)
}
state_root = of_unflatten_dtb(fdt, size);
+ free(fdt);
+
if (!IS_ERR(state_root)) {
struct device_node *np = NULL;
struct state *state;
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 32/39] efi: payload: protect against missing state alias
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (30 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 31/39] efi: payload: fix possible memory leaks during init Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 33/39] efi: loader: fix stale return value in console out-of-memory path Ahmad Fatoum
` (6 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
of_find_node_by_alias() can return NULL if the "state" alias doesn't
exist. The NULL result was passed directly to state_new_from_node(),
causing a NULL pointer dereference.
Add a NULL check with a warning message.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/init.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/efi/payload/init.c b/efi/payload/init.c
index 03f831840de7..6d2bd046e4c2 100644
--- a/efi/payload/init.c
+++ b/efi/payload/init.c
@@ -306,7 +306,7 @@ static int efi_late_init(void)
free(fdt);
if (!IS_ERR(state_root)) {
- struct device_node *np = NULL;
+ struct device_node *np;
struct state *state;
ret = barebox_register_of(state_root);
@@ -314,6 +314,10 @@ static int efi_late_init(void)
pr_warn("Failed to register device-tree: %pe\n", ERR_PTR(ret));
np = of_find_node_by_alias(state_root, "state");
+ if (!np) {
+ pr_warn("No state alias in %s\n", state_desc);
+ return 0;
+ }
state = state_new_from_node(np, false);
if (IS_ERR(state))
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 33/39] efi: loader: fix stale return value in console out-of-memory path
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (31 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 32/39] efi: payload: protect against missing state alias Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 34/39] efi: loader: fix off-by-one in FAT codepage translation Ahmad Fatoum
` (5 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_console_register() returns the stale value of r in the
out_of_memory path. If efi_install_multiple_protocol_interfaces()
succeeded but a later allocation failed, r still holds EFI_SUCCESS,
masking the error.
Return EFI_OUT_OF_RESOURCES explicitly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/console.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/loader/protocols/console.c b/efi/loader/protocols/console.c
index d2c13196e4c2..857b38f5df32 100644
--- a/efi/loader/protocols/console.c
+++ b/efi/loader/protocols/console.c
@@ -1316,7 +1316,7 @@ static efi_status_t efi_console_register(void *data)
return r;
out_of_memory:
pr_err("Out of memory\n");
- return r;
+ return EFI_OUT_OF_RESOURCES;
}
static int efi_console_init(void)
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 34/39] efi: loader: fix off-by-one in FAT codepage translation
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (32 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 33/39] efi: loader: fix stale return value in console out-of-memory path Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 35/39] efi: loader: fix co-existence with EFI payload support Ahmad Fatoum
` (4 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum, Claude Opus 4.6
efi_fat_to_str() uses 'c > 0x80' to decide whether to apply codepage
translation, but character 0x80 (C-cedilla in CP437) also requires
translation. Use 'c >= 0x80' to include it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/unicode_collation.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/loader/protocols/unicode_collation.c b/efi/loader/protocols/unicode_collation.c
index 4d9a26501723..9e522410fa2e 100644
--- a/efi/loader/protocols/unicode_collation.c
+++ b/efi/loader/protocols/unicode_collation.c
@@ -251,7 +251,7 @@ static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this,
EFI_ENTRY("%p, %zu, %s, %p", this, fat_size, fat, string);
for (i = 0; i < fat_size; ++i) {
c = (unsigned char)fat[i];
- if (c > 0x80)
+ if (c >= 0x80)
c = codepage[c - 0x60];
string[i] = c;
if (!c)
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 35/39] efi: loader: fix co-existence with EFI payload support
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (33 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 34/39] efi: loader: fix off-by-one in FAT codepage translation Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 36/39] efi: payload: skip ELF MMU handling when booted via stub Ahmad Fatoum
` (3 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We can enable both EFI loader and payload support at the same time,
so we should take care at runtime to skip initialization that's not
applicable. On the payload side, this is taken care of by EFI payload
specific initcalls, but on the EFI loader side, we are missing some
explicit handling for defaultvars and deferred protocol inits.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/defaultvars.c | 4 ++++
efi/loader/setup.c | 6 +++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/efi/loader/defaultvars.c b/efi/loader/defaultvars.c
index 4d8ec72d9166..906a68a47cf7 100644
--- a/efi/loader/defaultvars.c
+++ b/efi/loader/defaultvars.c
@@ -8,6 +8,7 @@
#include <efi/error.h>
#include <efi/guid.h>
#include <efi/loader.h>
+#include <efi/mode.h>
#include <efi/variable.h>
#include <linux/printk.h>
#include <linux/string.h>
@@ -109,6 +110,9 @@ static char *efi_lang_codes;
static int efi_defaultvars_init(void)
{
+ if (efi_is_payload())
+ return 0;
+
efi_lang_codes = xstrdup("en-US");
dev_add_param_string(&efidev, "lang.codes", NULL, NULL,
&efi_lang_codes, NULL);
diff --git a/efi/loader/setup.c b/efi/loader/setup.c
index e27929aaeae9..8309c0338b8f 100644
--- a/efi/loader/setup.c
+++ b/efi/loader/setup.c
@@ -97,8 +97,12 @@ static LIST_HEAD(efi_deferred_cbs);
void efi_register_deferred_init(efi_status_t (*init)(void *), void *data)
{
- struct efi_deferred_cb *deferred = xzalloc(sizeof(*deferred));
+ struct efi_deferred_cb *deferred;
+ if (efi_is_payload())
+ return;
+
+ deferred = xzalloc(sizeof(*deferred));
deferred->cb = init;
deferred->data = data;
list_add_tail(&deferred->list, &efi_deferred_cbs);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 36/39] efi: payload: skip ELF MMU handling when booted via stub
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (34 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 35/39] efi: loader: fix co-existence with EFI payload support Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 37/39] efi: payload: register dummy device tree Ahmad Fatoum
` (2 subsequent siblings)
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We should not touch the MMU when running as EFI app and must trust
that the EFI firmware has taken care of it.
This was so far realized by skipping MMU setup if MMU is already
enabled, but with the switch to ELF for barebox proper, the same check
can't be repeated in pbl_mmu_setup_from_elf(), so add an explicit check
that barebox wasn't invoked via the PE entry point.
Fixes: 6cb7fc2edbb6 ("ARM: PBL: setup MMU with proper permissions from ELF segments")
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/entry-multi.c | 13 +++++++++++++
include/efi/mode.h | 6 +++++-
pbl/mmu.c | 4 ++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/efi/payload/entry-multi.c b/efi/payload/entry-multi.c
index ef90ee077622..de977efc50b8 100644
--- a/efi/payload/entry-multi.c
+++ b/efi/payload/entry-multi.c
@@ -7,11 +7,23 @@
#include <asm/common.h>
#include <efi/protocol/text.h>
#include <efi/payload.h>
+#include <efi/mode.h>
#include <pbl.h>
#include <pbl/handoff-data.h>
asmlinkage void __efistub_efi_pe_entry(void *image, struct efi_system_table *sys_table);
+/*
+ * Put these in the data section so that they survive the clearing of the
+ * BSS segment.
+ */
+static __attribute__ ((section(".data"))) bool is_efi_payload;
+
+bool efi_is_payload(void)
+{
+ return is_efi_payload;
+}
+
static void efi_putc(void *ctx, int ch)
{
struct efi_system_table *sys_table = ctx;
@@ -30,6 +42,7 @@ void __efistub_efi_pe_entry(void *image, struct efi_system_table *sys_table)
#endif
pbl_set_putc(efi_putc, sys_table);
+ is_efi_payload = true;
efidata.image = image;
efidata.sys_table = sys_table;
diff --git a/include/efi/mode.h b/include/efi/mode.h
index d63c47e88dbb..5093e9b2971f 100644
--- a/include/efi/mode.h
+++ b/include/efi/mode.h
@@ -18,10 +18,14 @@ enum efi_loader_state {
EFI_LOADER_RUNTIME,
};
+#if IN_PBL && defined(CONFIG_EFI_STUB)
+bool efi_is_payload(void);
+#else
static inline bool efi_is_payload(void)
{
- return IS_ENABLED(CONFIG_EFI_PAYLOAD) && BS;
+ return IS_ENABLED(CONFIG_EFI_PAYLOAD) && IN_PROPER && BS;
}
+#endif
#ifdef CONFIG_EFI_LOADER
enum efi_loader_state efi_is_loader(void);
diff --git a/pbl/mmu.c b/pbl/mmu.c
index e7c9b8b1e8e4..897221c53f9b 100644
--- a/pbl/mmu.c
+++ b/pbl/mmu.c
@@ -10,6 +10,7 @@
#include <asm/mmu.h>
#include <linux/bits.h>
#include <linux/sizes.h>
+#include <efi/mode.h>
/*
* Map ELF segment permissions (p_flags) to architecture MMU flags
@@ -45,6 +46,9 @@ int pbl_mmu_setup_from_elf(struct elf_image *elf, unsigned long membase,
void *phdr;
int i = -1;
+ if (efi_is_payload())
+ return 0;
+
pr_debug("Setting up MMU from ELF segments\n");
/*
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 37/39] efi: payload: register dummy device tree
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (35 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 36/39] efi: payload: skip ELF MMU handling when booted via stub Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 38/39] console: introduce helper for printing binary buffers as-is Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 39/39] efi: loader: protocol: console: don't turn LF into CRLF Ahmad Fatoum
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
EFI payload support can enabled on top of an existing multi-image build
and thus runs into problems when the SoC specific initcalls implicitly
assume a device tree to be available.
Register a tentative empty device tree in this case to avoid issues.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/of/base.c | 8 ++++++--
efi/payload/boarddata.c | 11 +++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 4e83a757a4e9..8a17b0853ad4 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2103,8 +2103,12 @@ of_populate_initcall(barebox_of_populate);
int barebox_register_of(struct device_node *root)
{
- if (root_node)
- return -EBUSY;
+ if (root_node) {
+ if (!list_empty(&root->children))
+ return -EBUSY;
+ /* Not necessarily safe to free, so leak it.. */
+ root_node = NULL;
+ }
of_set_root_node(root);
of_fix_tree(root);
diff --git a/efi/payload/boarddata.c b/efi/payload/boarddata.c
index a2f4b8d21b4a..ec6ee7bbd98f 100644
--- a/efi/payload/boarddata.c
+++ b/efi/payload/boarddata.c
@@ -14,6 +14,7 @@
#include <linux/printk.h>
#include <debug_ll.h>
#include <init.h>
+#include <of.h>
#include <pbl/handoff-data.h>
static int handle_efi_boarddata(void)
@@ -46,3 +47,13 @@ static int handle_efi_boarddata(void)
return 0;
}
pure_initcall(handle_efi_boarddata);
+
+static __maybe_unused int efi_register_of(void)
+{
+ if (!BS)
+ return 0;
+ return barebox_register_of(of_new_node(NULL, NULL));
+}
+#ifdef CONFIG_OFDEVICE
+core_initcall(efi_register_of);
+#endif
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 38/39] console: introduce helper for printing binary buffers as-is
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (36 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 37/39] efi: payload: register dummy device tree Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
2026-02-16 8:44 ` [PATCH master 39/39] efi: loader: protocol: console: don't turn LF into CRLF Ahmad Fatoum
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Both console_putc(), console_puts() and console->puts always do
LF to CRLF conversion. For cases where this is not desired, code must
manually call console_putc in a loop.
Add a helper to simplify this.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/console.c | 31 +++++++++++++++++++++++++++++++
include/console.h | 1 +
2 files changed, 32 insertions(+)
diff --git a/common/console.c b/common/console.c
index 8a55fd1a1dc6..62ca57e43b05 100644
--- a/common/console.c
+++ b/common/console.c
@@ -637,6 +637,37 @@ int console_puts(unsigned int ch, const char *str)
}
EXPORT_SYMBOL(console_puts);
+void console_putbin(unsigned int ch, const u8 *str, size_t len)
+{
+ struct console_device *cdev;
+
+ switch (initialized) {
+ case CONSOLE_UNINITIALIZED:
+ console_init_early();
+ fallthrough;
+ case CONSOLE_INITIALIZED_BUFFER:
+ kfifo_put(console_output_fifo, str, len);
+ for (size_t i = 0; i < len; i++)
+ putc_ll(str[i]);
+ return;
+ case CONSOLE_INIT_FULL:
+ for_each_console(cdev) {
+ if (!(cdev->f_active & ch))
+ continue;
+
+ for (size_t i = 0; i < len; i++)
+ cdev->putc(cdev, str[i]);
+ }
+ return;
+ default:
+ /* If we have problems inititalizing our data
+ * get them early
+ */
+ hang();
+ }
+}
+EXPORT_SYMBOL(console_putbin);
+
void console_flush(void)
{
struct console_device *cdev;
diff --git a/include/console.h b/include/console.h
index 149378fc2839..b163c6684ee1 100644
--- a/include/console.h
+++ b/include/console.h
@@ -230,6 +230,7 @@ int arch_ctrlc(void);
/* stdout */
void console_putc(unsigned int ch, const char c);
int console_puts(unsigned int ch, const char *s);
+void console_putbin(unsigned int ch, const u8 *str, size_t len);
void console_flush(void);
int ctrlc(void);
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread* [PATCH master 39/39] efi: loader: protocol: console: don't turn LF into CRLF
2026-02-16 8:44 [PATCH master 00/39] efi: fix bugs Ahmad Fatoum
` (37 preceding siblings ...)
2026-02-16 8:44 ` [PATCH master 38/39] console: introduce helper for printing binary buffers as-is Ahmad Fatoum
@ 2026-02-16 8:44 ` Ahmad Fatoum
38 siblings, 0 replies; 40+ messages in thread
From: Ahmad Fatoum @ 2026-02-16 8:44 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
puts() does LF to CRLF conversion, when it really shouldn't as the EFI
app is supposed to do it, so we end up with stray line feeds.
Use the newer console_putbin helper to avoid them and while at it, just
skip the unnecessary memory duplication as we are going to loop through
the original string anyway.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/loader/protocols/console.c | 30 +++++++++++-------------------
1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/efi/loader/protocols/console.c b/efi/loader/protocols/console.c
index 857b38f5df32..ff56525341d4 100644
--- a/efi/loader/protocols/console.c
+++ b/efi/loader/protocols/console.c
@@ -170,8 +170,6 @@ static efi_status_t EFIAPI efi_cout_output_string(
{
struct simple_text_output_mode *con = &efi_con_mode;
struct cout_mode *mode = &efi_cout_modes[con->mode];
- char *buf, *pos;
- const u16 *p;
efi_status_t ret = EFI_SUCCESS;
EFI_ENTRY("%p, '%ls'", this, string);
@@ -181,16 +179,6 @@ static efi_status_t EFIAPI efi_cout_output_string(
goto out;
}
- buf = malloc(utf16_utf8_strlen(string) + 1);
- if (!buf) {
- ret = EFI_OUT_OF_RESOURCES;
- goto out;
- }
- pos = buf;
- utf16_utf8_strcpy(&pos, string);
- puts(buf);
- free(buf);
-
/*
* Update the cursor position.
*
@@ -198,7 +186,15 @@ static efi_status_t EFIAPI efi_cout_output_string(
* and U000D. All other control characters are ignored. Any non-control
* character increase the column by one.
*/
- for (p = string; *p; ++p) {
+ for (const u16 *p = string; *p; ++p) {
+ bool is_high_surrogate = p[1] && 0xd800 <= *p && *p <= 0xdbff;
+ u8 utf8[9], *end;
+
+ end = utf16_to_utf8(utf8, p, is_high_surrogate ? 2 : 1);
+
+ /* console_puts turns \n into \r\n, which we want to avoid */
+ console_putbin(CONSOLE_STDOUT, utf8, end - utf8);
+
switch (*p) {
case '\b': /* U+0008, backspace */
if (con->cursor_column)
@@ -211,16 +207,12 @@ static efi_status_t EFIAPI efi_cout_output_string(
case '\r': /* U+000D, carriage-return */
con->cursor_column = 0;
break;
- case 0xd800 ... 0xdbff:
- /*
- * Ignore high surrogates, we do not want to count a
- * Unicode character twice.
- */
- break;
default:
/* Exclude control codes */
if (*p > 0x1f)
con->cursor_column++;
+ if (is_high_surrogate)
+ p++;
break;
}
if (con->cursor_column >= mode->columns) {
--
2.47.3
^ permalink raw reply [flat|nested] 40+ messages in thread