Skip to contentSkip to conversation

ARM: dts: chromecast: override bad bootloader memory info

PATCH In review Thomas Hebb 2 participants 3 messages May 14, 2018 – May 15, 2018 Device tree bindings

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ARM: dts: chromecast: override bad bootloader memory info

On the Chromecast, the bootloader provides us with an ATAG_MEM of start=0x01000000 and size=0x3eff8000. This is clearly incorrect, as the range given encompasses nearly a GiB but the Chromecast only has 512MiB of RAM! Additionally, this causes the kernel to be decompressed at 0x00008000, below the claimed beginning of RAM, and so the boot fails.

Since the existing ATAG parsing code runs before the kernel is even decompressed and irrevocably patches the device tree, don't even try to bypass it. Instead, use the "linux,usable-memory" property instead of the "reg" property to define the real range. The ATAG code only overwrites reg, but linux,usable-memory is checked first in the OF driver, so the fact that reg gets changed makes no difference.

---
 arch/arm/boot/dts/berlin2cd-google-chromecast.dts | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
arch/arm/boot/dts/berlin2cd-google-chromecast.dts +11 -1
index 20f31cdeaf38..54221f55bfa2 100644
@@ -52,7 +52,17 @@
 
 	memory at 0 {
 		device_type = "memory";
-		reg = <0x00000000 0x20000000>; /* 512 MB */
+
+		/*
+		 * We're using "linux,usable-memory" instead of "reg" here
+		 * because the (signed and encrypted) bootloader that shipped
+		 * with this device provides an incorrect memory range in
+		 * ATAG_MEM. Linux helpfully overrides the "reg" property with
+		 * data from the ATAG, so we can't specify the proper range
+		 * normally. Fortunately, this alternate property is checked
+		 * first by the OF driver, so we can (ab)use it instead.
+		 */
+		linux,usable-memory = <0x00000000 0x20000000>; /* 512 MB */
 	};
 
 	leds {
Signature · 1 line
2.17.0
#1 lore raw

Hi,

Quoted 8 lines · On Mon, 14 May 2018 17:56:45 -0400 Thomas Hebb wrote:

On the Chromecast, the bootloader provides us with an ATAG_MEM of start=0x01000000 and size=0x3eff8000. This is clearly incorrect, as the range given encompasses nearly a GiB but the Chromecast only has 512MiB of RAM! Additionally, this causes the kernel to be decompressed at 0x00008000, below the claimed beginning of RAM, and so the boot fails.

Since the existing ATAG parsing code runs before the kernel is even decompressed and irrevocably patches the device tree, don't even try

This means you enabled ARM_ATAG_DTB_COMPAT. could we disable it instead? The ATAG is useless when we provide dtb. And IIRC, the ATAG is provided due to legacy history code.

Thanks

Quoted 33 lines

to bypass it. Instead, use the "linux,usable-memory" property instead of the "reg" property to define the real range. The ATAG code only overwrites reg, but linux,usable-memory is checked first in the OF driver, so the fact that reg gets changed makes no difference.

---
 arch/arm/boot/dts/berlin2cd-google-chromecast.dts | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
arch/arm/boot/dts/berlin2cd-google-chromecast.dts +11 -1
index 20f31cdeaf38..54221f55bfa2 100644
@@ -52,7 +52,17 @@
 
 	memory at 0 {
 		device_type = "memory";
-		reg = <0x00000000 0x20000000>; /* 512 MB */
+
+		/*
+		 * We're using "linux,usable-memory" instead of "reg" here
+		 * because the (signed and encrypted) bootloader that shipped
+		 * with this device provides an incorrect memory range in
+		 * ATAG_MEM. Linux helpfully overrides the "reg" property with
+		 * data from the ATAG, so we can't specify the proper range
+		 * normally. Fortunately, this alternate property is checked
+		 * first by the OF driver, so we can (ab)use it instead.
+		 */
+		linux,usable-memory = <0x00000000 0x20000000>; /* 512 MB */
 	};
 
 	leds {
author
#2 lore raw

Hi,

Quoted 10 lines · Jisheng Zhang

Hi,

Quoted 6 lines · On Mon, 14 May 2018 17:56:45 -0400 Thomas Hebb wrote:

On the Chromecast, the bootloader provides us with an ATAG_MEM of start=0x01000000 and size=0x3eff8000. This is clearly incorrect, as the range given encompasses nearly a GiB but the Chromecast only has 512MiB of RAM! Additionally, this causes the kernel to be decompressed at 0x00008000, below the claimed beginning of RAM, and so the boot fails.

Quoted 8 lines
Quoted 2 lines

Since the existing ATAG parsing code runs before the kernel is even decompressed and irrevocably patches the device tree, don't even try

This means you enabled ARM_ATAG_DTB_COMPAT. could we disable it instead? The ATAG is useless when we provide dtb. And IIRC, the ATAG is provided due to legacy history code.

Thanks

Thanks for the quick review! It's true that compiling without ARM_ATAG_DTB_COMPAT will prevent ATAG_MEM from getting parsed at all. However, it will also prevent ATAG_CMDLINE from getting parsed, and the command line from the Chromecast's bootloader does actually contain some useful information--notably the mode in which the system was booted (normal or recovery).

Userspace could conceivably want this information, so it's preferable for the kernel to boot regardless of whether ARM_ATAG_DTB_COMPAT is enabled. That's the intent of this patch.

I do agree in principle that ARM_ATAG_DTB_COMPAT should be disabled whenever possible.

Quoted 34 lines
Quoted 33 lines

to bypass it. Instead, use the "linux,usable-memory" property instead of the "reg" property to define the real range. The ATAG code only overwrites reg, but linux,usable-memory is checked first in the OF driver, so the fact that reg gets changed makes no difference.

---
 arch/arm/boot/dts/berlin2cd-google-chromecast.dts | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
arch/arm/boot/dts/berlin2cd-google-chromecast.dts +11 -1
index 20f31cdeaf38..54221f55bfa2 100644
@@ -52,7 +52,17 @@
 
 	memory at 0 {
 		device_type = "memory";
-		reg = <0x00000000 0x20000000>; /* 512 MB */
+
+		/*
+		 * We're using "linux,usable-memory" instead of "reg" here
+		 * because the (signed and encrypted) bootloader that shipped
+		 * with this device provides an incorrect memory range in
+		 * ATAG_MEM. Linux helpfully overrides the "reg" property with
+		 * data from the ATAG, so we can't specify the proper range
+		 * normally. Fortunately, this alternate property is checked
+		 * first by the OF driver, so we can (ab)use it instead.
+		 */
+		linux,usable-memory = <0x00000000 0x20000000>; /* 512 MB */
 	};
 
 	leds {