Change-Id: Idb80b21bb5dc4b461f89a3414d51b7d98a8328d8 Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr> Reviewed-on: https://review.coreboot.org/c/coreboot/+/50521 Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
		
			
				
	
	
		
			89 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0-or-later */
 | |
| 
 | |
| #include <bootmem.h>
 | |
| #include <program_loading.h>
 | |
| #include <fit.h>
 | |
| #include <symbols.h>
 | |
| 
 | |
| /**
 | |
|  * Place the region in free memory range.
 | |
|  */
 | |
| static bool fit_place_mem(const struct range_entry *r, void *arg)
 | |
| {
 | |
| 	struct region *region = arg;
 | |
| 	resource_t start;
 | |
| 
 | |
| 	if (range_entry_tag(r) != BM_MEM_RAM)
 | |
| 		return true;
 | |
| 
 | |
| 	/* Linux 4.15 doesn't like 4KiB alignment. Align to 1 MiB for now. */
 | |
| 	start = ALIGN_UP(MAX(region->offset, range_entry_base(r)), 1 * MiB);
 | |
| 
 | |
| 	if (start + region->size < range_entry_end(r)) {
 | |
| 		region->offset = (size_t)start;
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| bool fit_payload_arch(struct prog *payload, struct fit_config_node *config,
 | |
| 		      struct region *kernel,
 | |
| 		      struct region *fdt,
 | |
| 		      struct region *initrd)
 | |
| {
 | |
| 	void *arg = NULL;
 | |
| 
 | |
| 	/**
 | |
| 	 * The kernel ARM documentation recommends loading the kernel above 32MiB
 | |
| 	 * in order to avoid the need to need to relocate prior to decompression.
 | |
| 	 */
 | |
| 	kernel->offset = (uintptr_t)_dram + 32 * MiB;
 | |
| 
 | |
| 	/**
 | |
| 	 * The code assumes that bootmem_walk provides a sorted list of memory
 | |
| 	 * regions, starting from the lowest address.
 | |
| 	 * The order of the calls here doesn't matter, as the placement is
 | |
| 	 * enforced in the called functions.
 | |
| 	 * For details check code on top.
 | |
| 	 */
 | |
| 	if (!bootmem_walk(fit_place_mem, kernel))
 | |
| 		return false;
 | |
| 
 | |
| 	/* Mark as reserved for future allocations. */
 | |
| 	bootmem_add_range(kernel->offset, kernel->size, BM_MEM_PAYLOAD);
 | |
| 
 | |
| 	/**
 | |
| 	 * To ensure the fdt is not overwritten by the kernel decompressor, place
 | |
| 	 * the fdt above the 128 MB from the start of RAM, as recommended by the
 | |
| 	 * kernel documentation.
 | |
| 	 */
 | |
| 	fdt->offset = (uintptr_t)_dram + 128 * MiB;
 | |
| 
 | |
| 	if (!bootmem_walk(fit_place_mem, fdt))
 | |
| 		return false;
 | |
| 
 | |
| 	/* Mark as reserved for future allocations. */
 | |
| 	bootmem_add_range(fdt->offset, fdt->size, BM_MEM_PAYLOAD);
 | |
| 
 | |
| 	/* Place INITRD */
 | |
| 	if (config->ramdisk) {
 | |
| 		initrd->offset = fdt->offset + fdt->size;
 | |
| 
 | |
| 		if (!bootmem_walk(fit_place_mem, initrd))
 | |
| 			return false;
 | |
| 
 | |
| 		/* Mark as reserved for future allocations. */
 | |
| 		bootmem_add_range(initrd->offset, initrd->size, BM_MEM_PAYLOAD);
 | |
| 	}
 | |
| 
 | |
| 	/* Kernel expects FDT as argument */
 | |
| 	arg = (void *)fdt->offset;
 | |
| 
 | |
| 	prog_set_entry(payload, (void *)kernel->offset, arg);
 | |
| 
 | |
| 	bootmem_dump_ranges();
 | |
| 
 | |
| 	return true;
 | |
| }
 |