@@ -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;
@@ -498,6 +498,51 @@ 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_slice(int (*cb)(void *ctx, ulong addr,
+ u32 size), void *ctx)
+{
+ int ret;
+ u32 size;
+ ulong addr;
+ 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 = (ulong)(uintptr_t)bmm->addr;
+ size = (u32)bms->blkcnt << bd->log2blksz;
+ ret = cb(ctx, addr, size);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+
+}
+
int blkmap_destroy(struct udevice *dev)
{
int err;
@@ -7,6 +7,7 @@
#ifndef _BLKMAP_H
#define _BLKMAP_H
+#include <blk.h>
#include <dm/lists.h>
/**
@@ -104,4 +105,20 @@ 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_slice() - Look for memory mapped preserved slice
+ * @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.
+ *
+ * Return: 0 on success, negative error on failure
+ */
+int blkmap_get_preserved_pmem_slice(int (*cb)(void *ctx, ulong addr,
+ u32 size), void *ctx);
+
#endif /* _BLKMAP_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 */
@@ -5,6 +5,7 @@
#define LOG_CATEGORY LOGC_EFI
+#include <blkmap.h>
#include <bootm.h>
#include <env.h>
#include <image.h>
@@ -680,3 +681,42 @@ 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, ulong addr, u32 size)
+{
+ int ret;
+ efi_status_t status;
+
+ ret = fdt_fixup_pmem_region(fdt, addr, size);
+ if (ret) {
+ log_err("Failed to setup pmem node for addr %#lx, size %#x, err %d\n",
+ addr, size, ret);
+ return ret;
+ }
+
+ status = efi_remove_memory_map(addr, size,
+ EFI_CONVENTIONAL_MEMORY);
+ if (status != EFI_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+int fdt_efi_pmem_setup(void *fdt)
+{
+
+ return blkmap_get_preserved_pmem_slice(pmem_node_efi_memmap_setup,
+ fdt);
+}