diff options
-rw-r--r-- | boot/image-fdt.c | 7 | ||||
-rw-r--r-- | drivers/block/blkmap.c | 43 | ||||
-rw-r--r-- | include/blkmap.h | 29 | ||||
-rw-r--r-- | include/efi.h | 13 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 42 |
5 files changed, 134 insertions, 0 deletions
diff --git a/boot/image-fdt.c b/boot/image-fdt.c index 9d1598b1a93..8f718ad29f6 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -11,6 +11,7 @@ #include <command.h> #include <fdt_support.h> #include <fdtdec.h> +#include <efi.h> #include <env.h> #include <errno.h> #include <image.h> @@ -649,6 +650,12 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb) if (!ft_verify_fdt(blob)) goto err; + if (CONFIG_IS_ENABLED(BLKMAP) && CONFIG_IS_ENABLED(EFI_LOADER)) { + fdt_ret = fdt_efi_pmem_setup(blob); + if (fdt_ret) + goto err; + } + /* after here we are using a livetree */ if (!of_live_active() && CONFIG_IS_ENABLED(EVENT)) { struct event_ft_fixup fixup; diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c index 1b161bd90be..473c65b5911 100644 --- a/drivers/block/blkmap.c +++ b/drivers/block/blkmap.c @@ -517,6 +517,49 @@ err: return err; } +static bool blkmap_mem_preserve_slice(struct blkmap_slice *bms) +{ + return (bms->attr & (BLKMAP_SLICE_MEM | BLKMAP_SLICE_PRESERVE)) == + (BLKMAP_SLICE_MEM | BLKMAP_SLICE_PRESERVE); +} + +int blkmap_get_preserved_pmem_slices(int (*cb)(void *ctx, u64 addr, + u64 size), void *ctx) +{ + int ret; + u64 addr, size; + struct udevice *dev; + struct uclass *uc; + struct blkmap *bm; + struct blkmap_mem *bmm; + struct blkmap_slice *bms; + struct blk_desc *bd; + + if (!cb) { + log_debug("%s: No callback passed to the function\n", __func__); + return 0; + } + + uclass_id_foreach_dev(UCLASS_BLKMAP, dev, uc) { + bm = dev_get_plat(dev); + bd = dev_get_uclass_plat(bm->blk); + + list_for_each_entry(bms, &bm->slices, node) { + if (!blkmap_mem_preserve_slice(bms)) + continue; + + bmm = container_of(bms, struct blkmap_mem, slice); + addr = (u64)(uintptr_t)bmm->addr; + size = (u64)bms->blkcnt << bd->log2blksz; + ret = cb(ctx, addr, size); + if (ret) + return ret; + } + } + + return 0; +} + int blkmap_destroy(struct udevice *dev) { int err; diff --git a/include/blkmap.h b/include/blkmap.h index 754d8671b01..57555fda4fb 100644 --- a/include/blkmap.h +++ b/include/blkmap.h @@ -7,6 +7,7 @@ #ifndef _BLKMAP_H #define _BLKMAP_H +#include <blk.h> #include <dm/lists.h> /** @@ -104,4 +105,32 @@ int blkmap_destroy(struct udevice *dev); int blkmap_create_ramdisk(const char *label, ulong image_addr, ulong image_size, struct udevice **devp); +/** + * blkmap_get_preserved_pmem_slices() - Look for memory mapped preserved slices + * @cb: Callback function to call for the blkmap slice + * @ctx: Argument to be passed to the callback function + * + * The function is used to iterate through all the blkmap slices, looking + * specifically for memory mapped blkmap mapping which has been + * created with the preserve attribute. The function looks for such slices + * with the relevant attributes and then calls the callback function which + * then does additional configuration as needed. The callback function is + * invoked for all the discovered slices, unless there is an error returned + * by the callback, in which case the function returns that error. + * + * The callback function has the following arguments + * @ctx: Argument to be passed to the callback function + * @addr: Start address of the memory mapped slice + * @size: Size of the memory mapped slice + * + * Typically, the callback will perform some configuration needed for the + * information passed on to it. An example of this would be setting up the + * pmem node in a device-tree(passed through the ctx argument) with the + * parameters passed on to the callback. + * + * Return: 0 on success, negative error on failure + */ +int blkmap_get_preserved_pmem_slices(int (*cb)(void *ctx, u64 addr, + u64 size), void *ctx); + #endif /* _BLKMAP_H */ diff --git a/include/efi.h b/include/efi.h index d005cb6181e..f9bbb175c3a 100644 --- a/include/efi.h +++ b/include/efi.h @@ -705,4 +705,17 @@ static inline bool efi_use_host_arch(void) */ int efi_get_pxe_arch(void); +/** + * fdt_efi_pmem_setup() - Pmem setup in DT and EFI memory map + * @fdt: Devicetree to add the pmem nodes to + * + * Iterate through all the blkmap devices, look for BLKMAP_MEM devices, + * and add pmem nodes corresponding to the blkmap slice to the + * devicetree along with removing the corresponding region from the + * EFI memory map. + * + * Returns: 0 on success, negative error on failure + */ +int fdt_efi_pmem_setup(void *fdt); + #endif /* _LINUX_EFI_H */ diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index f6fbcdffe82..8c32059edda 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -5,6 +5,7 @@ #define LOG_CATEGORY LOGC_EFI +#include <blkmap.h> #include <bootm.h> #include <env.h> #include <image.h> @@ -687,3 +688,44 @@ out: return ret; } + +/** + * pmem_node_efi_memmap_setup() - Add pmem node and tweak EFI memmap + * @fdt: The devicetree to which pmem node is added + * @addr: start address of the pmem node + * @size: size of the memory of the pmem node + * + * The function adds the pmem node to the device-tree along with removing + * the corresponding region from the EFI memory map. Used primarily to + * pass the information of a RAM based ISO image to the OS. + * + * Return: 0 on success, -ve value on error + */ +static int pmem_node_efi_memmap_setup(void *fdt, u64 addr, u64 size) +{ + int ret; + u64 pages; + efi_status_t status; + + ret = fdt_fixup_pmem_region(fdt, addr, size); + if (ret) { + log_err("Failed to setup pmem node for addr %#llx, size %#llx, err %d\n", + addr, size, ret); + return ret; + } + + /* Remove the pmem region from the EFI memory map */ + pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); + status = efi_update_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, + false, true); + if (status != EFI_SUCCESS) + return -1; + + return 0; +} + +int fdt_efi_pmem_setup(void *fdt) +{ + return blkmap_get_preserved_pmem_slices(pmem_node_efi_memmap_setup, + fdt); +} |