Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: Make initrd detection more robust.

Various boot loaders go to various extents to thwart the initrd detection
logic (mostly on account of not being able to be bothered with adhering
to the established boot ABI), so we make the detection logic a bit more
robust. This makes it possible to work around the SDK7786's firmware's
attempts to thwart compressed image booting. Victory is mine.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

+58 -20
+58 -20
arch/sh/kernel/setup.c
··· 188 188 {} 189 189 #endif 190 190 191 + static void __init check_for_initrd(void) 192 + { 193 + #ifdef CONFIG_BLK_DEV_INITRD 194 + unsigned long start, end; 195 + 196 + /* 197 + * Check for the rare cases where boot loaders adhere to the boot 198 + * ABI. 199 + */ 200 + if (!LOADER_TYPE || !INITRD_START || !INITRD_SIZE) 201 + goto disable; 202 + 203 + start = INITRD_START + __MEMORY_START; 204 + end = start + INITRD_SIZE; 205 + 206 + if (unlikely(end <= start)) 207 + goto disable; 208 + if (unlikely(start & ~PAGE_MASK)) { 209 + pr_err("initrd must be page aligned\n"); 210 + goto disable; 211 + } 212 + 213 + if (unlikely(start < PAGE_OFFSET)) { 214 + pr_err("initrd start < PAGE_OFFSET\n"); 215 + goto disable; 216 + } 217 + 218 + if (unlikely(end > lmb_end_of_DRAM())) { 219 + pr_err("initrd extends beyond end of memory " 220 + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", 221 + end, (unsigned long)lmb_end_of_DRAM()); 222 + goto disable; 223 + } 224 + 225 + /* 226 + * If we got this far inspite of the boot loader's best efforts 227 + * to the contrary, assume we actually have a valid initrd and 228 + * fix up the root dev. 229 + */ 230 + ROOT_DEV = Root_RAM0; 231 + 232 + /* 233 + * Address sanitization 234 + */ 235 + initrd_start = (unsigned long)__va(__pa(start)); 236 + initrd_end = initrd_start + INITRD_SIZE; 237 + 238 + reserve_bootmem(__pa(initrd_start), INITRD_SIZE, BOOTMEM_DEFAULT); 239 + 240 + return; 241 + 242 + disable: 243 + pr_info("initrd disabled\n"); 244 + initrd_start = initrd_end = 0; 245 + #endif 246 + } 247 + 191 248 void __cpuinit calibrate_delay(void) 192 249 { 193 250 struct clk *clk = clk_get(NULL, "cpu_clk"); ··· 334 277 335 278 sparse_memory_present_with_active_regions(0); 336 279 337 - #ifdef CONFIG_BLK_DEV_INITRD 338 - ROOT_DEV = Root_RAM0; 339 - 340 - if (LOADER_TYPE && INITRD_START) { 341 - unsigned long initrd_start_phys = INITRD_START + __MEMORY_START; 342 - 343 - if (initrd_start_phys + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) { 344 - reserve_bootmem(initrd_start_phys, INITRD_SIZE, 345 - BOOTMEM_DEFAULT); 346 - initrd_start = (unsigned long)__va(initrd_start_phys); 347 - initrd_end = initrd_start + INITRD_SIZE; 348 - } else { 349 - printk("initrd extends beyond end of memory " 350 - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", 351 - initrd_start_phys + INITRD_SIZE, 352 - (unsigned long)PFN_PHYS(max_low_pfn)); 353 - initrd_start = 0; 354 - } 355 - } 356 - #endif 280 + check_for_initrd(); 357 281 358 282 reserve_crashkernel(); 359 283 }