[PATCH] arm64: head: set TEXT_OFFSET to the historical value

Dmitry Baryshkov posted 1 patch 2 months, 1 week ago
arch/arm64/kernel/head.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] arm64: head: set TEXT_OFFSET to the historical value
Posted by Dmitry Baryshkov 2 months, 1 week ago
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

Historically arm64 kernel contained (almost fixed) value of 0x8000 at
the TEXT_OFFSET. The commit cfa7ede20f13 ("arm64: set TEXT_OFFSET to 0x0
in preparation for removing it entirely") and then commit 120dc60d0bdb
("arm64: get rid of TEXT_OFFSET") replaced this field with 0.

This caused no problems so far, because nobody seemed to be playing with
the extremely picky Qualcomm bootloader as used on some of Google Pixel
phones. Current attempting to boot the Linux kernel on those devices
will fail to load on those phones with the following message:

KernelDecompress failed: Invalid Parameter Kernel TextOffset does not match
Error calling BootPrepareAsync Invalid Parameter

Since the kernel ignores the field, set it to the expected value of
0x8000, unbreaking boot of upstream kernels on Qualcomm devices.

Note: I purposedly didn't add Fixes tags, since those commits didn't
break any of devices that were supported at that time.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
 arch/arm64/kernel/head.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index ca04b338cb0d173f6d9f5bcee52f6d3d06552599..05e874977de376835625f52bfdda78305dca28b5 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -60,7 +60,7 @@
 	 */
 	efi_signature_nop			// special NOP to identity as PE/COFF executable
 	b	primary_entry			// branch to kernel start, magic
-	.quad	0				// Image load offset from start of RAM, little-endian
+	.quad	0x80000				// Image load offset from start of RAM, little-endian
 	le64sym	_kernel_size_le			// Effective size of kernel image, little-endian
 	le64sym	_kernel_flags_le		// Informative flags, little-endian
 	.quad	0				// reserved

---
base-commit: bd773c01d149aec064ea0fc890a54be277acfa3b
change-id: 20251006-arm64-text-offset-a45fee505c4d

Best regards,
-- 
With best wishes
Dmitry
Re: [PATCH] arm64: head: set TEXT_OFFSET to the historical value
Posted by Will Deacon 2 months, 1 week ago
[+Ard and Mark]

On Mon, Oct 06, 2025 at 01:21:04AM +0300, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> 
> Historically arm64 kernel contained (almost fixed) value of 0x8000 at

0x8000 or 0x80000?

> the TEXT_OFFSET. The commit cfa7ede20f13 ("arm64: set TEXT_OFFSET to 0x0
> in preparation for removing it entirely") and then commit 120dc60d0bdb
> ("arm64: get rid of TEXT_OFFSET") replaced this field with 0.

Given that we made the initial change over five years ago, I'm struggling
to see why we should start caring about old broken bootloaders _now_.

In fact, I'm far more concerned about changing this to a non-zero value
and having more recent bootloaders misbehave.

> This caused no problems so far, because nobody seemed to be playing with
> the extremely picky Qualcomm bootloader as used on some of Google Pixel
> phones. Current attempting to boot the Linux kernel on those devices
> will fail to load on those phones with the following message:
> 
> KernelDecompress failed: Invalid Parameter Kernel TextOffset does not match
> Error calling BootPrepareAsync Invalid Parameter
> 
> Since the kernel ignores the field, set it to the expected value of
> 0x8000, unbreaking boot of upstream kernels on Qualcomm devices.

(same typo)

> Note: I purposedly didn't add Fixes tags, since those commits didn't
> break any of devices that were supported at that time.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
>  arch/arm64/kernel/head.S | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index ca04b338cb0d173f6d9f5bcee52f6d3d06552599..05e874977de376835625f52bfdda78305dca28b5 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -60,7 +60,7 @@
>  	 */
>  	efi_signature_nop			// special NOP to identity as PE/COFF executable
>  	b	primary_entry			// branch to kernel start, magic
> -	.quad	0				// Image load offset from start of RAM, little-endian
> +	.quad	0x80000				// Image load offset from start of RAM, little-endian
>  	le64sym	_kernel_size_le			// Effective size of kernel image, little-endian
>  	le64sym	_kernel_flags_le		// Informative flags, little-endian
>  	.quad	0				// reserved

Could you wrap the kernel Image in your own header to workaround the
issue?

Will
Re: [PATCH] arm64: head: set TEXT_OFFSET to the historical value
Posted by Ard Biesheuvel 2 months, 1 week ago
On Mon, 6 Oct 2025 at 16:01, Will Deacon <will@kernel.org> wrote:
>
> [+Ard and Mark]
>
> On Mon, Oct 06, 2025 at 01:21:04AM +0300, Dmitry Baryshkov wrote:
> > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >
> > Historically arm64 kernel contained (almost fixed) value of 0x8000 at
>
> 0x8000 or 0x80000?
>
> > the TEXT_OFFSET. The commit cfa7ede20f13 ("arm64: set TEXT_OFFSET to 0x0
> > in preparation for removing it entirely") and then commit 120dc60d0bdb
> > ("arm64: get rid of TEXT_OFFSET") replaced this field with 0.
>
> Given that we made the initial change over five years ago, I'm struggling
> to see why we should start caring about old broken bootloaders _now_.
>
> In fact, I'm far more concerned about changing this to a non-zero value
> and having more recent bootloaders misbehave.
>
> > This caused no problems so far, because nobody seemed to be playing with
> > the extremely picky Qualcomm bootloader as used on some of Google Pixel
> > phones. Current attempting to boot the Linux kernel on those devices
> > will fail to load on those phones with the following message:
> >
> > KernelDecompress failed: Invalid Parameter Kernel TextOffset does not match
> > Error calling BootPrepareAsync Invalid Parameter
> >
> > Since the kernel ignores the field, set it to the expected value of
> > 0x8000, unbreaking boot of upstream kernels on Qualcomm devices.
>
> (same typo)
>

Just setting the header field and not updating the base address also
means that the boot breaks without CONFIG_RELOCATABLE, and you will
get a warning in the kernel log about the load address not being
aligned to 2 MiB.

So I don't think this is the right solution.

If this is really something that needs to be fixed upstream, we should
just bring back TEXT_OFFSET in its entirety, but I'm not convinced
that this is really justified here. As a workaround, you could just
add 2 MiB - 0x80000 bytes of padding at the start of the image, and
add your own header (as Will alludes to as well)
Re: [PATCH] arm64: head: set TEXT_OFFSET to the historical value
Posted by Dmitry Baryshkov 2 months, 1 week ago
On Tue, Oct 07, 2025 at 01:46:08AM +0200, Ard Biesheuvel wrote:
> On Mon, 6 Oct 2025 at 16:01, Will Deacon <will@kernel.org> wrote:
> >
> > [+Ard and Mark]
> >
> > On Mon, Oct 06, 2025 at 01:21:04AM +0300, Dmitry Baryshkov wrote:
> > > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > >
> > > Historically arm64 kernel contained (almost fixed) value of 0x8000 at
> >
> > 0x8000 or 0x80000?
> >
> > > the TEXT_OFFSET. The commit cfa7ede20f13 ("arm64: set TEXT_OFFSET to 0x0
> > > in preparation for removing it entirely") and then commit 120dc60d0bdb
> > > ("arm64: get rid of TEXT_OFFSET") replaced this field with 0.
> >
> > Given that we made the initial change over five years ago, I'm struggling
> > to see why we should start caring about old broken bootloaders _now_.

Well... because support for these devices wasn't upstreamed and so a
similar patch was being kept in the down-upstream kernel.

> >
> > In fact, I'm far more concerned about changing this to a non-zero value
> > and having more recent bootloaders misbehave.

I see.

> >
> > > This caused no problems so far, because nobody seemed to be playing with
> > > the extremely picky Qualcomm bootloader as used on some of Google Pixel
> > > phones. Current attempting to boot the Linux kernel on those devices
> > > will fail to load on those phones with the following message:
> > >
> > > KernelDecompress failed: Invalid Parameter Kernel TextOffset does not match
> > > Error calling BootPrepareAsync Invalid Parameter
> > >
> > > Since the kernel ignores the field, set it to the expected value of
> > > 0x8000, unbreaking boot of upstream kernels on Qualcomm devices.
> >
> > (same typo)
> >
> 
> Just setting the header field and not updating the base address also
> means that the boot breaks without CONFIG_RELOCATABLE, and you will
> get a warning in the kernel log about the load address not being
> aligned to 2 MiB.
> 
> So I don't think this is the right solution.

Since most of the people build the kernel with CONFIG_RELOCATABLE, would
it be better to set it to 0x80000 for relocatable kernels and to 0
otherwise?

> 
> If this is really something that needs to be fixed upstream, we should
> just bring back TEXT_OFFSET in its entirety, but I'm not convinced
> that this is really justified here. As a workaround, you could just
> add 2 MiB - 0x80000 bytes of padding at the start of the image, and
> add your own header (as Will alludes to as well)

Does it mean building a device specific kernel? Or just packing
everything while building the Android boot image?

-- 
With best wishes
Dmitry
Re: [PATCH] arm64: head: set TEXT_OFFSET to the historical value
Posted by Ard Biesheuvel 2 months, 1 week ago
On Wed, 8 Oct 2025 at 12:51, Dmitry Baryshkov
<dmitry.baryshkov@oss.qualcomm.com> wrote:
>
> On Tue, Oct 07, 2025 at 01:46:08AM +0200, Ard Biesheuvel wrote:
...
> >
> > Just setting the header field and not updating the base address also
> > means that the boot breaks without CONFIG_RELOCATABLE, and you will
> > get a warning in the kernel log about the load address not being
> > aligned to 2 MiB.
> >
> > So I don't think this is the right solution.
>
> Since most of the people build the kernel with CONFIG_RELOCATABLE, would
> it be better to set it to 0x80000 for relocatable kernels and to 0
> otherwise?
>

When CONFIG_RELOCATABLE is set, any multiple of 64k is acceptable in
practice, but given that this violates the documented boot protocol
for arm64, we only permit this when booting via the EFI stub.

When we set this field to 0x80000, we are basically instructing
bootloaders to violate the boot protocol, which is not ideal, and we
should definitely not issue the pr_warn() we have today in
arch/arm64/kernel/setup.c.

> >
> > If this is really something that needs to be fixed upstream, we should
> > just bring back TEXT_OFFSET in its entirety, but I'm not convinced
> > that this is really justified here. As a workaround, you could just
> > add 2 MiB - 0x80000 bytes of padding at the start of the image, and
> > add your own header (as Will alludes to as well)
>
> Does it mean building a device specific kernel? Or just packing
> everything while building the Android boot image?
>

No idea. What does the Android boot image contain? Is the first thing
that gets loaded the kernel image? In that case, you would wrap the
kernel image before sticking it into the Android boot image, yes.
Re: [PATCH] arm64: head: set TEXT_OFFSET to the historical value
Posted by David Heidelberg 2 months, 1 week ago
Hi.

So far, only Pixel 3 and 3 XL with "recent" bootloaders are affected.

As I see it, the cost of making it compatible is accepting the commit at 
zero maintenance or runtime cost.

Would make sense to also update the comment in the code to reflect the 
change?

Thank you!

Reviewed-by: David Heidelberg <david@ixit.cz>


On 06/10/2025 00:21, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> 
> Historically arm64 kernel contained (almost fixed) value of 0x8000 at
> the TEXT_OFFSET. The commit cfa7ede20f13 ("arm64: set TEXT_OFFSET to 0x0
> in preparation for removing it entirely") and then commit 120dc60d0bdb
> ("arm64: get rid of TEXT_OFFSET") replaced this field with 0.
> 
> This caused no problems so far, because nobody seemed to be playing with
> the extremely picky Qualcomm bootloader as used on some of Google Pixel
> phones. Current attempting to boot the Linux kernel on those devices
> will fail to load on those phones with the following message:
> 
> KernelDecompress failed: Invalid Parameter Kernel TextOffset does not match
> Error calling BootPrepareAsync Invalid Parameter
> 
> Since the kernel ignores the field, set it to the expected value of
> 0x8000, unbreaking boot of upstream kernels on Qualcomm devices.
> 
> Note: I purposedly didn't add Fixes tags, since those commits didn't
> break any of devices that were supported at that time.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
>   arch/arm64/kernel/head.S | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index ca04b338cb0d173f6d9f5bcee52f6d3d06552599..05e874977de376835625f52bfdda78305dca28b5 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -60,7 +60,7 @@
>   	 */
>   	efi_signature_nop			// special NOP to identity as PE/COFF executable
>   	b	primary_entry			// branch to kernel start, magic
> -	.quad	0				// Image load offset from start of RAM, little-endian
> +	.quad	0x80000				// Image load offset from start of RAM, little-endian
>   	le64sym	_kernel_size_le			// Effective size of kernel image, little-endian
>   	le64sym	_kernel_flags_le		// Informative flags, little-endian
>   	.quad	0				// reserved
> 
> ---
> base-commit: bd773c01d149aec064ea0fc890a54be277acfa3b
> change-id: 20251006-arm64-text-offset-a45fee505c4d
> 
> Best regards,

-- 
David Heidelberg