diff options
-rw-r--r-- | boot/fdt_support.c | 39 | ||||
-rw-r--r-- | boot/image-fdt.c | 7 | ||||
-rw-r--r-- | cmd/blkmap.c | 9 | ||||
-rw-r--r-- | drivers/block/blkmap.c | 82 | ||||
-rw-r--r-- | drivers/block/blkmap_helper.c | 2 | ||||
-rw-r--r-- | include/blkmap.h | 33 | ||||
-rw-r--r-- | include/efi.h | 13 | ||||
-rw-r--r-- | include/efi_loader.h | 15 | ||||
-rw-r--r-- | include/fdt_support.h | 14 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 25 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 85 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 34 |
12 files changed, 310 insertions, 48 deletions
diff --git a/boot/fdt_support.c b/boot/fdt_support.c index 49efeec3681..92f2f534ee0 100644 --- a/boot/fdt_support.c +++ b/boot/fdt_support.c @@ -18,6 +18,7 @@ #include <dm/ofnode.h> #include <linux/ctype.h> #include <linux/types.h> +#include <linux/sizes.h> #include <asm/global_data.h> #include <asm/unaligned.h> #include <linux/libfdt.h> @@ -464,7 +465,6 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat, do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create); } -#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY /* * fdt_pack_reg - pack address and size array into the "reg"-suitable stream */ @@ -493,6 +493,7 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size, return p - (char *)buf; } +#ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY #if CONFIG_NR_DRAM_BANKS > 4 #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS #else @@ -2222,3 +2223,39 @@ int fdt_valid(struct fdt_header **blobp) } return 1; } + +int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size) +{ + char node_name[32]; + int nodeoffset, len; + int err; + u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */ + + if (!IS_ALIGNED(pmem_start, SZ_2M) || + !IS_ALIGNED(pmem_start + pmem_size, SZ_2M)) { + printf("Start and end address must be 2MiB aligned\n"); + return -1; + } + + snprintf(node_name, sizeof(node_name), "pmem@%llx", pmem_start); + nodeoffset = fdt_find_or_add_subnode(fdt, 0, node_name); + if (nodeoffset < 0) + return nodeoffset; + + err = fdt_setprop_string(fdt, nodeoffset, "compatible", "pmem-region"); + if (err) + return err; + err = fdt_setprop_empty(fdt, nodeoffset, "volatile"); + if (err) + return err; + + len = fdt_pack_reg(fdt, tmp, &pmem_start, &pmem_size, 1); + err = fdt_setprop(fdt, nodeoffset, "reg", tmp, len); + if (err < 0) { + printf("WARNING: could not set pmem %s %s.\n", "reg", + fdt_strerror(err)); + return err; + } + + return 0; +} 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/cmd/blkmap.c b/cmd/blkmap.c index 164f80f1387..86a123b1cd3 100644 --- a/cmd/blkmap.c +++ b/cmd/blkmap.c @@ -62,13 +62,18 @@ static int do_blkmap_map_mem(struct map_ctx *ctx, int argc, char *const argv[]) { phys_addr_t addr; int err; + bool preserve = false; if (argc < 2) return CMD_RET_USAGE; addr = hextoul(argv[1], NULL); - err = blkmap_map_pmem(ctx->dev, ctx->blknr, ctx->blkcnt, addr); + if (argc == 3 && !strcmp(argv[2], "preserve")) + preserve = true; + + err = blkmap_map_pmem(ctx->dev, ctx->blknr, ctx->blkcnt, addr, + preserve); if (err) { printf("Unable to map %#llx at block 0x" LBAF ": %d\n", (unsigned long long)addr, ctx->blknr, err); @@ -221,7 +226,7 @@ U_BOOT_CMD_WITH_SUBCMDS( "blkmap create <label> - create device\n" "blkmap destroy <label> - destroy device\n" "blkmap map <label> <blk#> <cnt> linear <interface> <dev> <blk#> - device mapping\n" - "blkmap map <label> <blk#> <cnt> mem <addr> - memory mapping\n", + "blkmap map <label> <blk#> <cnt> mem <addr> [preserve] - memory mapping\n", U_BOOT_SUBCMD_MKENT(info, 2, 1, do_blkmap_common), U_BOOT_SUBCMD_MKENT(part, 2, 1, do_blkmap_common), U_BOOT_SUBCMD_MKENT(dev, 4, 1, do_blkmap_common), diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c index 34eed1380dc..473c65b5911 100644 --- a/drivers/block/blkmap.c +++ b/drivers/block/blkmap.c @@ -17,6 +17,30 @@ struct blkmap; /** + * define BLKMAP_SLICE_LINEAR - Linear mapping to another block device + * + * This blkmap slice type is used for mapping to other existing block + * devices. + */ +#define BLKMAP_SLICE_LINEAR BIT(0) + +/** + * define BLKMAP_SLICE_MEM - Linear mapping to memory based block device + * + * This blkmap slice type is used for mapping to memory based block + * devices, like ramdisks. + */ +#define BLKMAP_SLICE_MEM BIT(1) + +/** + * define BLKMAP_SLICE_PRESERVE - Preserved blkmap slice + * + * This blkmap slice is intended to be preserved, and it's + * information passed on to a later stage, like OS. + */ +#define BLKMAP_SLICE_PRESERVE BIT(2) + +/** * struct blkmap_slice - Region mapped to a blkmap * * Common data for a region mapped to a blkmap, specialized by each @@ -25,12 +49,14 @@ struct blkmap; * @node: List node used to associate this slice with a blkmap * @blknr: Start block number of the mapping * @blkcnt: Number of blocks covered by this mapping + * @attr: Attributes of blkmap slice */ struct blkmap_slice { struct list_head node; lbaint_t blknr; lbaint_t blkcnt; + uint attr; /** * @read: - Read from slice @@ -169,6 +195,7 @@ int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, .slice = { .blknr = blknr, .blkcnt = blkcnt, + .attr = BLKMAP_SLICE_LINEAR, .read = blkmap_linear_read, .write = blkmap_linear_write, @@ -234,7 +261,7 @@ static void blkmap_mem_destroy(struct blkmap *bm, struct blkmap_slice *bms) } int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, - void *addr, bool remapped) + void *addr, bool remapped, bool preserve) { struct blkmap *bm = dev_get_plat(dev); struct blkmap_mem *bmm; @@ -248,6 +275,7 @@ int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, .slice = { .blknr = blknr, .blkcnt = blkcnt, + .attr = BLKMAP_SLICE_MEM, .read = blkmap_mem_read, .write = blkmap_mem_write, @@ -258,6 +286,9 @@ int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, .remapped = remapped, }; + if (preserve) + bmm->slice.attr |= BLKMAP_SLICE_PRESERVE; + err = blkmap_slice_add(bm, &bmm->slice); if (err) free(bmm); @@ -268,11 +299,11 @@ int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, void *addr) { - return __blkmap_map_mem(dev, blknr, blkcnt, addr, false); + return __blkmap_map_mem(dev, blknr, blkcnt, addr, false, false); } int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, - phys_addr_t paddr) + phys_addr_t paddr, bool preserve) { struct blkmap *bm = dev_get_plat(dev); struct blk_desc *bd = dev_get_uclass_plat(bm->blk); @@ -283,7 +314,7 @@ int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, if (!addr) return -ENOMEM; - err = __blkmap_map_mem(dev, blknr, blkcnt, addr, true); + err = __blkmap_map_mem(dev, blknr, blkcnt, addr, true, preserve); if (err) unmap_sysmem(addr); @@ -486,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/drivers/block/blkmap_helper.c b/drivers/block/blkmap_helper.c index bfba14110d2..2f1bc28ee5d 100644 --- a/drivers/block/blkmap_helper.c +++ b/drivers/block/blkmap_helper.c @@ -28,7 +28,7 @@ int blkmap_create_ramdisk(const char *label, ulong image_addr, ulong image_size, bm = dev_get_plat(bm_dev); desc = dev_get_uclass_plat(bm->blk); blknum = image_size >> desc->log2blksz; - ret = blkmap_map_pmem(bm_dev, 0, blknum, image_addr); + ret = blkmap_map_pmem(bm_dev, 0, blknum, image_addr, true); if (ret) { log_err("Unable to map %#llx at block %d : %d\n", (unsigned long long)image_addr, 0, ret); diff --git a/include/blkmap.h b/include/blkmap.h index d53095437fa..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> /** @@ -60,10 +61,12 @@ int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, * @blknr: Start block number of the mapping * @blkcnt: Number of blocks to map * @paddr: The target physical memory address of the mapping + * @preserve: Mapping intended to be preserved for subsequent stages, + * like the OS (e.g. ISO installer) * Returns: 0 on success, negative error code on failure */ int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, - phys_addr_t paddr); + phys_addr_t paddr, bool preserve); /** * blkmap_from_label() - Find blkmap from label @@ -102,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/include/efi_loader.h b/include/efi_loader.h index e9c10819ba2..5f769786786 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -878,6 +878,21 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, /* Adds a range into the EFI memory map */ efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type); +/** + * efi_update_memory_map() - update the memory map by adding/removing pages + * + * @start: start address, must be a multiple of + * EFI_PAGE_SIZE + * @pages: number of pages to add + * @memory_type: type of memory added + * @overlap_conventional: region may only overlap free(conventional) + * memory + * @remove: remove memory map + * Return: status code + */ +efi_status_t efi_update_memory_map(u64 start, u64 pages, int memory_type, + bool overlap_conventional, bool remove); + /* Called by board init to initialize the EFI drivers */ efi_status_t efi_driver_init(void); /* Called when a block device is added */ diff --git a/include/fdt_support.h b/include/fdt_support.h index f0ad2e6b365..049190cf3d7 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -471,6 +471,20 @@ int fdt_valid(struct fdt_header **blobp); */ int fdt_get_cells_len(const void *blob, char *nr_cells_name); +/** + * fdt_fixup_pmem_region() - add a pmem node on the device tree + * + * This functions adds/updates a pmem node to the device tree. + * Usually used with EFI installers to preserve installer + * images + * + * @fdt: device tree provided by caller + * @addr: start address of the pmem node + * @size: size of the memory of the pmem node + * Return: 0 on success or < 0 on failure + */ +int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size); + #endif /* !USE_HOSTCC */ #ifdef USE_HOSTCC diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index c6124c590d9..f9534ef85ed 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -18,6 +18,8 @@ #include <efi_loader.h> #include <efi_variable.h> #include <asm/unaligned.h> +#include <linux/kernel.h> +#include <linux/sizes.h> static const struct efi_boot_services *bs; static const struct efi_runtime_services *rs; @@ -348,6 +350,7 @@ static efi_status_t prepare_loaded_image(u16 *label, ulong addr, ulong size, struct efi_device_path **dp, struct udevice **blk) { + u64 pages; efi_status_t ret; struct udevice *ramdisk_blk; @@ -362,13 +365,18 @@ static efi_status_t prepare_loaded_image(u16 *label, ulong addr, ulong size, } /* - * TODO: expose the ramdisk to OS. - * Need to pass the ramdisk information by the architecture-specific - * methods such as 'pmem' device-tree node. + * Linux supports 'pmem' which allows OS installers to find, reclaim + * the mounted images and continue the installation since the contents + * of the pmem region are treated as local media. + * + * The memory regions used for it needs to be carved out of the EFI + * memory map. */ - ret = efi_add_memory_map(addr, size, EFI_RESERVED_MEMORY_TYPE); + pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); + ret = efi_update_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, + false, true); if (ret != EFI_SUCCESS) { - log_err("Memory reservation failed\n"); + log_err("Failed to reserve memory\n"); goto err; } @@ -490,6 +498,13 @@ static efi_status_t try_load_from_uri_path(struct efi_device_path_uri *uridp, ret = EFI_INVALID_PARAMETER; goto err; } + /* + * Depending on the kernel configuration, pmem memory areas must be + * page aligned or 2MiB aligned. PowerPC is an exception here and + * requires 16MiB alignment, but since we don't have EFI support for + * it, limit the alignment to 2MiB. + */ + image_size = ALIGN(image_size, SZ_2M); /* * If the file extension is ".iso" or ".img", mount it and try to load diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 04b2efc4a3b..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> @@ -454,22 +455,29 @@ efi_status_t efi_env_set_load_options(efi_handle_t handle, */ static efi_status_t copy_fdt(void **fdtp) { - unsigned long fdt_ram_start = -1L, fdt_pages; efi_status_t ret = 0; void *fdt, *new_fdt; - u64 new_fdt_addr; - uint fdt_size; - int i; + static u64 new_fdt_addr; + static efi_uintn_t fdt_pages; + ulong fdt_size; - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - u64 ram_start = gd->bd->bi_dram[i].start; - u64 ram_size = gd->bd->bi_dram[i].size; + /* + * Remove the configuration table that might already be + * installed, ignoring EFI_NOT_FOUND if no device-tree + * is installed + */ + efi_install_configuration_table(&efi_guid_fdt, NULL); - if (!ram_size) - continue; + if (new_fdt_addr) { + log_debug("%s: Found allocated memory at %#llx, with %#zx pages\n", + __func__, new_fdt_addr, fdt_pages); - if (ram_start < fdt_ram_start) - fdt_ram_start = ram_start; + ret = efi_free_pages(new_fdt_addr, fdt_pages); + if (ret != EFI_SUCCESS) + log_err("Unable to free up existing FDT memory region\n"); + + new_fdt_addr = 0; + fdt_pages = 0; } /* @@ -485,15 +493,18 @@ static efi_status_t copy_fdt(void **fdtp) &new_fdt_addr); if (ret != EFI_SUCCESS) { log_err("Failed to reserve space for FDT\n"); - goto done; + return ret; } + log_debug("%s: Allocated memory at %#llx, with %#zx pages\n", + __func__, new_fdt_addr, fdt_pages); + new_fdt = (void *)(uintptr_t)new_fdt_addr; memcpy(new_fdt, fdt, fdt_totalsize(fdt)); fdt_set_totalsize(new_fdt, fdt_size); - *fdtp = (void *)(uintptr_t)new_fdt_addr; -done: - return ret; + *fdtp = new_fdt; + + return EFI_SUCCESS; } /** @@ -546,9 +557,6 @@ efi_status_t efi_install_fdt(void *fdt) const char *fdt_opt; uintptr_t fdt_addr; - /* Look for device tree that is already installed */ - if (efi_get_configuration_table(&efi_guid_fdt)) - return EFI_SUCCESS; /* Check if there is a hardware device tree */ fdt_opt = env_get("fdt_addr"); /* Use our own device tree as fallback */ @@ -680,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); +} diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index c39b53922bb..0abb1f6159a 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -258,7 +258,7 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map, } /** - * efi_add_memory_map_pg() - add pages to the memory map + * efi_update_memory_map() - update the memory map by adding/removing pages * * @start: start address, must be a multiple of * EFI_PAGE_SIZE @@ -266,12 +266,11 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map, * @memory_type: type of memory added * @overlap_conventional: region may only overlap free(conventional) * memory + * @remove: remove memory map * Return: status code */ -static -efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, - int memory_type, - bool overlap_conventional) +efi_status_t efi_update_memory_map(u64 start, u64 pages, int memory_type, + bool overlap_conventional, bool remove) { struct efi_mem_list *lmem; struct efi_mem_list *newlist; @@ -279,9 +278,9 @@ efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, uint64_t carved_pages = 0; struct efi_event *evt; - EFI_PRINT("%s: 0x%llx 0x%llx %d %s\n", __func__, + EFI_PRINT("%s: 0x%llx 0x%llx %d %s %s\n", __func__, start, pages, memory_type, overlap_conventional ? - "yes" : "no"); + "yes" : "no", remove ? "remove" : "add"); if (memory_type >= EFI_MAX_MEMORY_TYPE) return EFI_INVALID_PARAMETER; @@ -364,7 +363,10 @@ efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, } /* Add our new map */ - list_add_tail(&newlist->link, &efi_mem); + if (!remove) + list_add_tail(&newlist->link, &efi_mem); + else + free(newlist); /* And make sure memory is listed in descending order */ efi_mem_sort(); @@ -401,7 +403,7 @@ efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type) pages = efi_size_in_pages(size + (start & EFI_PAGE_MASK)); start &= ~EFI_PAGE_MASK; - return efi_add_memory_map_pg(start, pages, memory_type, false); + return efi_update_memory_map(start, pages, memory_type, false, false); } /** @@ -501,7 +503,7 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type, efi_addr = (u64)(uintptr_t)map_sysmem(addr, 0); /* Reserve that map in our memory maps */ - ret = efi_add_memory_map_pg(efi_addr, pages, memory_type, true); + ret = efi_update_memory_map(efi_addr, pages, memory_type, true, false); if (ret != EFI_SUCCESS) { /* Map would overlap, bail out */ lmb_free_flags(addr, (u64)pages << EFI_PAGE_SHIFT, flags); @@ -822,8 +824,8 @@ static void add_u_boot_and_runtime(void) uboot_stack_size) & ~EFI_PAGE_MASK; uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) - uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; - efi_add_memory_map_pg(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE, - false); + efi_update_memory_map(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE, + false, false); #if defined(__aarch64__) /* * Runtime Services must be 64KiB aligned according to the @@ -841,8 +843,8 @@ static void add_u_boot_and_runtime(void) runtime_end = (uintptr_t)__efi_runtime_stop; runtime_end = (runtime_end + runtime_mask) & ~runtime_mask; runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; - efi_add_memory_map_pg(runtime_start, runtime_pages, - EFI_RUNTIME_SERVICES_CODE, false); + efi_update_memory_map(runtime_start, runtime_pages, + EFI_RUNTIME_SERVICES_CODE, false, false); } int efi_memory_init(void) @@ -877,11 +879,11 @@ int efi_map_update_notify(phys_addr_t addr, phys_size_t size, pages = efi_size_in_pages(size + (efi_addr & EFI_PAGE_MASK)); efi_addr &= ~EFI_PAGE_MASK; - status = efi_add_memory_map_pg(efi_addr, pages, + status = efi_update_memory_map(efi_addr, pages, op == LMB_MAP_OP_RESERVE ? EFI_BOOT_SERVICES_DATA : EFI_CONVENTIONAL_MEMORY, - false); + false, false); if (status != EFI_SUCCESS) { log_err("LMB Map notify failure %lu\n", status & ~EFI_ERROR_MASK); |