diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/image-fdt.c | 77 |
1 files changed, 57 insertions, 20 deletions
diff --git a/boot/image-fdt.c b/boot/image-fdt.c index a3a4fb8b558..1150131a11e 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -69,35 +69,50 @@ static const struct legacy_img_hdr *image_get_fdt(ulong fdt_addr) } #endif -static void boot_fdt_reserve_region(u64 addr, u64 size, u32 flags) +/** + * boot_fdt_handle_region - Reserve or free a given FDT region in LMB + * @addr: Reservation base address + * @size: Reservation size + * @flags: Reservation flags + * @free: Indicate if region is being freed or allocated + * + * Add or free a given reservation from LMB. This reports to the user if any + * errors occurred during either operation. + */ +static void boot_fdt_handle_region(u64 addr, u64 size, u32 flags, bool free) { long ret; phys_addr_t rsv_addr; rsv_addr = (phys_addr_t)addr; - ret = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &rsv_addr, size, flags); + if (free) + ret = lmb_free(rsv_addr, size, flags); + else + ret = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &rsv_addr, size, + flags); + if (!ret) { - debug(" reserving fdt memory region: addr=%llx size=%llx flags=%x\n", - (unsigned long long)addr, + debug(" %s fdt memory region: addr=%llx size=%llx flags=%x\n", + free ? "freed" : "reserved", (unsigned long long)addr, (unsigned long long)size, flags); - } else if (ret != -EEXIST && ret != -EINVAL) { - puts("ERROR: reserving fdt memory region failed "); - printf("(addr=%llx size=%llx flags=%x)\n", - (unsigned long long)addr, - (unsigned long long)size, flags); + } else { + printf("ERROR: %s fdt memory region failed (addr=%llx size=%llx flags=%x): %ld\n", + free ? "freeing" : "reserving", (unsigned long long)addr, + (unsigned long long)size, flags, ret); } } /** - * boot_fdt_add_mem_rsv_regions - Mark the memreserve and reserved-memory - * sections as unusable + * boot_fdt_handle_mem_rsv_regions - Handle FDT memreserve and reserved-memory + * sections * @fdt_blob: pointer to fdt blob base address + * @free: indicate if regions are being freed * - * Adds the and reserved-memorymemreserve regions in the dtb to the lmb block. - * Adding the memreserve regions prevents u-boot from using them to store the - * initrd or the fdt blob. + * Adds or removes reserved-memory and memreserve regions in the dtb to the lmb + * block. Adding the memreserve regions prevents u-boot from using them to store + * the initrd or the fdt blob. */ -void boot_fdt_add_mem_rsv_regions(void *fdt_blob) +static void boot_fdt_handle_mem_rsv_regions(const void *fdt_blob, bool free) { uint64_t addr, size; int i, total, ret; @@ -105,15 +120,12 @@ void boot_fdt_add_mem_rsv_regions(void *fdt_blob) struct fdt_resource res; u32 flags; - if (fdt_check_header(fdt_blob) != 0) - return; - /* process memreserve sections */ total = fdt_num_mem_rsv(fdt_blob); for (i = 0; i < total; i++) { if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0) continue; - boot_fdt_reserve_region(addr, size, LMB_NOOVERWRITE); + boot_fdt_handle_region(addr, size, LMB_NOOVERWRITE, free); } /* process reserved-memory */ @@ -131,7 +143,7 @@ void boot_fdt_add_mem_rsv_regions(void *fdt_blob) flags = LMB_NOMAP; addr = res.start; size = res.end - res.start + 1; - boot_fdt_reserve_region(addr, size, flags); + boot_fdt_handle_region(addr, size, flags, free); } subnode = fdt_next_subnode(fdt_blob, subnode); @@ -140,6 +152,31 @@ void boot_fdt_add_mem_rsv_regions(void *fdt_blob) } /** + * boot_fdt_add_mem_rsv_regions - Add FDT memreserve and reserved-memory + * sections + * @fdt_blob: pointer to fdt blob base address + * + * Adds reserved-memory and memreserve regions in the dtb to the lmb block. + * Adding the memreserve regions prevents u-boot from using them to store the + * initrd or the fdt blob. + * + * This function will attempt to clean the currently active reservations if a + * new device tree blob is given. This must be called before gd->fdt_blob is + * switched. + */ +void boot_fdt_add_mem_rsv_regions(const void *fdt_blob) +{ + if (fdt_check_header(fdt_blob) != 0) + return; + + /* Remove old regions */ + if (gd->fdt_blob != fdt_blob) + boot_fdt_handle_mem_rsv_regions(gd->fdt_blob, true); + + boot_fdt_handle_mem_rsv_regions(fdt_blob, false); +} + +/** * boot_relocate_fdt - relocate flat device tree * @of_flat_tree: pointer to a char* variable, will hold fdt start address * @of_size: pointer to a ulong variable, will hold fdt length |
