"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'efi-next-26032025' of https://source.denx.de/u-boot/custodians/u-boot-tpm into next

When trying to boot an OS installer or a live image via EFI HTTP the
following happens
- U-Boot downloads the image and mounts it in memory
- The EFI subsystem is invoked and the image is started
- The OS calls ExitBootServices and the memory that holds the mounted
image might get overwritten

This results in installers complaining that they can't find installer
medium or live images complaining they can't find the root filesystem.

ACPI already deals with it by having NFIT and NVDIMM to provide ramdisks
that need to be preserved by the OS. Linux and device trees have support
for persistent memory devices (pmem).

We can use them and inject a pmem node in the DT to preserve memory across the
entire boot sequence. Linux will just create a block device over the reserved
memory and installers/images can re-discover it.

This is what it looks like from the OS perspective:

nd_pmem namespace0.0: unable to guarantee persistence of writes
pmem0: p1 p2 p3
EXT4-fs (pmem0p3): mounted filesystem f40f64a4-5b41-4828-856e-caaae2c1c2a0 r/w with ordered data mode. Quota mode: disabled.
EXT4-fs (pmem0p3): re-mounted f40f64a4-5b41-4828-856e-caaae2c1c2a0 r/w. Quota mode: disabled.
Adding 45052k swap on /dev/pmem0p2. Priority:-2 extents:1 across:45052k SS
root@genericarm64:~# mount | grep pmem
/dev/pmem0p3 on / type ext4 (rw,relatime)
/dev/pmem0p1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

It's worth noting that Linux behaves differently with reserved memory
(at least on arm64) and that depends on kernel config options.
CONFIG_ZONE_DEVICES and CONFIG_ARM64_PMEM are such options. It boils down to
how the kernel tries to map pages. If devm_memremap_pages() gets called instead
of devm_memremap() mapping the memory fails.

The only safe way is to remove the memory from the EFI memory map,
rather than defining it as /reserved no-map;/ in the DT.

+310 -48
+38 -1
boot/fdt_support.c
··· 18 18 #include <dm/ofnode.h> 19 19 #include <linux/ctype.h> 20 20 #include <linux/types.h> 21 + #include <linux/sizes.h> 21 22 #include <asm/global_data.h> 22 23 #include <asm/unaligned.h> 23 24 #include <linux/libfdt.h> ··· 464 465 do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create); 465 466 } 466 467 467 - #ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY 468 468 /* 469 469 * fdt_pack_reg - pack address and size array into the "reg"-suitable stream 470 470 */ ··· 493 493 return p - (char *)buf; 494 494 } 495 495 496 + #ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY 496 497 #if CONFIG_NR_DRAM_BANKS > 4 497 498 #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS 498 499 #else ··· 2222 2223 } 2223 2224 return 1; 2224 2225 } 2226 + 2227 + int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size) 2228 + { 2229 + char node_name[32]; 2230 + int nodeoffset, len; 2231 + int err; 2232 + u8 tmp[4 * 16]; /* Up to 64-bit address + 64-bit size */ 2233 + 2234 + if (!IS_ALIGNED(pmem_start, SZ_2M) || 2235 + !IS_ALIGNED(pmem_start + pmem_size, SZ_2M)) { 2236 + printf("Start and end address must be 2MiB aligned\n"); 2237 + return -1; 2238 + } 2239 + 2240 + snprintf(node_name, sizeof(node_name), "pmem@%llx", pmem_start); 2241 + nodeoffset = fdt_find_or_add_subnode(fdt, 0, node_name); 2242 + if (nodeoffset < 0) 2243 + return nodeoffset; 2244 + 2245 + err = fdt_setprop_string(fdt, nodeoffset, "compatible", "pmem-region"); 2246 + if (err) 2247 + return err; 2248 + err = fdt_setprop_empty(fdt, nodeoffset, "volatile"); 2249 + if (err) 2250 + return err; 2251 + 2252 + len = fdt_pack_reg(fdt, tmp, &pmem_start, &pmem_size, 1); 2253 + err = fdt_setprop(fdt, nodeoffset, "reg", tmp, len); 2254 + if (err < 0) { 2255 + printf("WARNING: could not set pmem %s %s.\n", "reg", 2256 + fdt_strerror(err)); 2257 + return err; 2258 + } 2259 + 2260 + return 0; 2261 + }
+7
boot/image-fdt.c
··· 11 11 #include <command.h> 12 12 #include <fdt_support.h> 13 13 #include <fdtdec.h> 14 + #include <efi.h> 14 15 #include <env.h> 15 16 #include <errno.h> 16 17 #include <image.h> ··· 648 649 649 650 if (!ft_verify_fdt(blob)) 650 651 goto err; 652 + 653 + if (CONFIG_IS_ENABLED(BLKMAP) && CONFIG_IS_ENABLED(EFI_LOADER)) { 654 + fdt_ret = fdt_efi_pmem_setup(blob); 655 + if (fdt_ret) 656 + goto err; 657 + } 651 658 652 659 /* after here we are using a livetree */ 653 660 if (!of_live_active() && CONFIG_IS_ENABLED(EVENT)) {
+7 -2
cmd/blkmap.c
··· 62 62 { 63 63 phys_addr_t addr; 64 64 int err; 65 + bool preserve = false; 65 66 66 67 if (argc < 2) 67 68 return CMD_RET_USAGE; 68 69 69 70 addr = hextoul(argv[1], NULL); 70 71 71 - err = blkmap_map_pmem(ctx->dev, ctx->blknr, ctx->blkcnt, addr); 72 + if (argc == 3 && !strcmp(argv[2], "preserve")) 73 + preserve = true; 74 + 75 + err = blkmap_map_pmem(ctx->dev, ctx->blknr, ctx->blkcnt, addr, 76 + preserve); 72 77 if (err) { 73 78 printf("Unable to map %#llx at block 0x" LBAF ": %d\n", 74 79 (unsigned long long)addr, ctx->blknr, err); ··· 221 226 "blkmap create <label> - create device\n" 222 227 "blkmap destroy <label> - destroy device\n" 223 228 "blkmap map <label> <blk#> <cnt> linear <interface> <dev> <blk#> - device mapping\n" 224 - "blkmap map <label> <blk#> <cnt> mem <addr> - memory mapping\n", 229 + "blkmap map <label> <blk#> <cnt> mem <addr> [preserve] - memory mapping\n", 225 230 U_BOOT_SUBCMD_MKENT(info, 2, 1, do_blkmap_common), 226 231 U_BOOT_SUBCMD_MKENT(part, 2, 1, do_blkmap_common), 227 232 U_BOOT_SUBCMD_MKENT(dev, 4, 1, do_blkmap_common),
+78 -4
drivers/block/blkmap.c
··· 17 17 struct blkmap; 18 18 19 19 /** 20 + * define BLKMAP_SLICE_LINEAR - Linear mapping to another block device 21 + * 22 + * This blkmap slice type is used for mapping to other existing block 23 + * devices. 24 + */ 25 + #define BLKMAP_SLICE_LINEAR BIT(0) 26 + 27 + /** 28 + * define BLKMAP_SLICE_MEM - Linear mapping to memory based block device 29 + * 30 + * This blkmap slice type is used for mapping to memory based block 31 + * devices, like ramdisks. 32 + */ 33 + #define BLKMAP_SLICE_MEM BIT(1) 34 + 35 + /** 36 + * define BLKMAP_SLICE_PRESERVE - Preserved blkmap slice 37 + * 38 + * This blkmap slice is intended to be preserved, and it's 39 + * information passed on to a later stage, like OS. 40 + */ 41 + #define BLKMAP_SLICE_PRESERVE BIT(2) 42 + 43 + /** 20 44 * struct blkmap_slice - Region mapped to a blkmap 21 45 * 22 46 * Common data for a region mapped to a blkmap, specialized by each ··· 25 49 * @node: List node used to associate this slice with a blkmap 26 50 * @blknr: Start block number of the mapping 27 51 * @blkcnt: Number of blocks covered by this mapping 52 + * @attr: Attributes of blkmap slice 28 53 */ 29 54 struct blkmap_slice { 30 55 struct list_head node; 31 56 32 57 lbaint_t blknr; 33 58 lbaint_t blkcnt; 59 + uint attr; 34 60 35 61 /** 36 62 * @read: - Read from slice ··· 169 195 .slice = { 170 196 .blknr = blknr, 171 197 .blkcnt = blkcnt, 198 + .attr = BLKMAP_SLICE_LINEAR, 172 199 173 200 .read = blkmap_linear_read, 174 201 .write = blkmap_linear_write, ··· 234 261 } 235 262 236 263 int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, 237 - void *addr, bool remapped) 264 + void *addr, bool remapped, bool preserve) 238 265 { 239 266 struct blkmap *bm = dev_get_plat(dev); 240 267 struct blkmap_mem *bmm; ··· 248 275 .slice = { 249 276 .blknr = blknr, 250 277 .blkcnt = blkcnt, 278 + .attr = BLKMAP_SLICE_MEM, 251 279 252 280 .read = blkmap_mem_read, 253 281 .write = blkmap_mem_write, ··· 258 286 .remapped = remapped, 259 287 }; 260 288 289 + if (preserve) 290 + bmm->slice.attr |= BLKMAP_SLICE_PRESERVE; 291 + 261 292 err = blkmap_slice_add(bm, &bmm->slice); 262 293 if (err) 263 294 free(bmm); ··· 268 299 int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, 269 300 void *addr) 270 301 { 271 - return __blkmap_map_mem(dev, blknr, blkcnt, addr, false); 302 + return __blkmap_map_mem(dev, blknr, blkcnt, addr, false, false); 272 303 } 273 304 274 305 int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, 275 - phys_addr_t paddr) 306 + phys_addr_t paddr, bool preserve) 276 307 { 277 308 struct blkmap *bm = dev_get_plat(dev); 278 309 struct blk_desc *bd = dev_get_uclass_plat(bm->blk); ··· 283 314 if (!addr) 284 315 return -ENOMEM; 285 316 286 - err = __blkmap_map_mem(dev, blknr, blkcnt, addr, true); 317 + err = __blkmap_map_mem(dev, blknr, blkcnt, addr, true, preserve); 287 318 if (err) 288 319 unmap_sysmem(addr); 289 320 ··· 484 515 free(hlabel); 485 516 err: 486 517 return err; 518 + } 519 + 520 + static bool blkmap_mem_preserve_slice(struct blkmap_slice *bms) 521 + { 522 + return (bms->attr & (BLKMAP_SLICE_MEM | BLKMAP_SLICE_PRESERVE)) == 523 + (BLKMAP_SLICE_MEM | BLKMAP_SLICE_PRESERVE); 524 + } 525 + 526 + int blkmap_get_preserved_pmem_slices(int (*cb)(void *ctx, u64 addr, 527 + u64 size), void *ctx) 528 + { 529 + int ret; 530 + u64 addr, size; 531 + struct udevice *dev; 532 + struct uclass *uc; 533 + struct blkmap *bm; 534 + struct blkmap_mem *bmm; 535 + struct blkmap_slice *bms; 536 + struct blk_desc *bd; 537 + 538 + if (!cb) { 539 + log_debug("%s: No callback passed to the function\n", __func__); 540 + return 0; 541 + } 542 + 543 + uclass_id_foreach_dev(UCLASS_BLKMAP, dev, uc) { 544 + bm = dev_get_plat(dev); 545 + bd = dev_get_uclass_plat(bm->blk); 546 + 547 + list_for_each_entry(bms, &bm->slices, node) { 548 + if (!blkmap_mem_preserve_slice(bms)) 549 + continue; 550 + 551 + bmm = container_of(bms, struct blkmap_mem, slice); 552 + addr = (u64)(uintptr_t)bmm->addr; 553 + size = (u64)bms->blkcnt << bd->log2blksz; 554 + ret = cb(ctx, addr, size); 555 + if (ret) 556 + return ret; 557 + } 558 + } 559 + 560 + return 0; 487 561 } 488 562 489 563 int blkmap_destroy(struct udevice *dev)
+1 -1
drivers/block/blkmap_helper.c
··· 28 28 bm = dev_get_plat(bm_dev); 29 29 desc = dev_get_uclass_plat(bm->blk); 30 30 blknum = image_size >> desc->log2blksz; 31 - ret = blkmap_map_pmem(bm_dev, 0, blknum, image_addr); 31 + ret = blkmap_map_pmem(bm_dev, 0, blknum, image_addr, true); 32 32 if (ret) { 33 33 log_err("Unable to map %#llx at block %d : %d\n", 34 34 (unsigned long long)image_addr, 0, ret);
+32 -1
include/blkmap.h
··· 7 7 #ifndef _BLKMAP_H 8 8 #define _BLKMAP_H 9 9 10 + #include <blk.h> 10 11 #include <dm/lists.h> 11 12 12 13 /** ··· 60 61 * @blknr: Start block number of the mapping 61 62 * @blkcnt: Number of blocks to map 62 63 * @paddr: The target physical memory address of the mapping 64 + * @preserve: Mapping intended to be preserved for subsequent stages, 65 + * like the OS (e.g. ISO installer) 63 66 * Returns: 0 on success, negative error code on failure 64 67 */ 65 68 int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, 66 - phys_addr_t paddr); 69 + phys_addr_t paddr, bool preserve); 67 70 68 71 /** 69 72 * blkmap_from_label() - Find blkmap from label ··· 101 104 */ 102 105 int blkmap_create_ramdisk(const char *label, ulong image_addr, ulong image_size, 103 106 struct udevice **devp); 107 + 108 + /** 109 + * blkmap_get_preserved_pmem_slices() - Look for memory mapped preserved slices 110 + * @cb: Callback function to call for the blkmap slice 111 + * @ctx: Argument to be passed to the callback function 112 + * 113 + * The function is used to iterate through all the blkmap slices, looking 114 + * specifically for memory mapped blkmap mapping which has been 115 + * created with the preserve attribute. The function looks for such slices 116 + * with the relevant attributes and then calls the callback function which 117 + * then does additional configuration as needed. The callback function is 118 + * invoked for all the discovered slices, unless there is an error returned 119 + * by the callback, in which case the function returns that error. 120 + * 121 + * The callback function has the following arguments 122 + * @ctx: Argument to be passed to the callback function 123 + * @addr: Start address of the memory mapped slice 124 + * @size: Size of the memory mapped slice 125 + * 126 + * Typically, the callback will perform some configuration needed for the 127 + * information passed on to it. An example of this would be setting up the 128 + * pmem node in a device-tree(passed through the ctx argument) with the 129 + * parameters passed on to the callback. 130 + * 131 + * Return: 0 on success, negative error on failure 132 + */ 133 + int blkmap_get_preserved_pmem_slices(int (*cb)(void *ctx, u64 addr, 134 + u64 size), void *ctx); 104 135 105 136 #endif /* _BLKMAP_H */
+13
include/efi.h
··· 705 705 */ 706 706 int efi_get_pxe_arch(void); 707 707 708 + /** 709 + * fdt_efi_pmem_setup() - Pmem setup in DT and EFI memory map 710 + * @fdt: Devicetree to add the pmem nodes to 711 + * 712 + * Iterate through all the blkmap devices, look for BLKMAP_MEM devices, 713 + * and add pmem nodes corresponding to the blkmap slice to the 714 + * devicetree along with removing the corresponding region from the 715 + * EFI memory map. 716 + * 717 + * Returns: 0 on success, negative error on failure 718 + */ 719 + int fdt_efi_pmem_setup(void *fdt); 720 + 708 721 #endif /* _LINUX_EFI_H */
+15
include/efi_loader.h
··· 878 878 /* Adds a range into the EFI memory map */ 879 879 efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type); 880 880 881 + /** 882 + * efi_update_memory_map() - update the memory map by adding/removing pages 883 + * 884 + * @start: start address, must be a multiple of 885 + * EFI_PAGE_SIZE 886 + * @pages: number of pages to add 887 + * @memory_type: type of memory added 888 + * @overlap_conventional: region may only overlap free(conventional) 889 + * memory 890 + * @remove: remove memory map 891 + * Return: status code 892 + */ 893 + efi_status_t efi_update_memory_map(u64 start, u64 pages, int memory_type, 894 + bool overlap_conventional, bool remove); 895 + 881 896 /* Called by board init to initialize the EFI drivers */ 882 897 efi_status_t efi_driver_init(void); 883 898 /* Called when a block device is added */
+14
include/fdt_support.h
··· 471 471 */ 472 472 int fdt_get_cells_len(const void *blob, char *nr_cells_name); 473 473 474 + /** 475 + * fdt_fixup_pmem_region() - add a pmem node on the device tree 476 + * 477 + * This functions adds/updates a pmem node to the device tree. 478 + * Usually used with EFI installers to preserve installer 479 + * images 480 + * 481 + * @fdt: device tree provided by caller 482 + * @addr: start address of the pmem node 483 + * @size: size of the memory of the pmem node 484 + * Return: 0 on success or < 0 on failure 485 + */ 486 + int fdt_fixup_pmem_region(void *fdt, u64 pmem_start, u64 pmem_size); 487 + 474 488 #endif /* !USE_HOSTCC */ 475 489 476 490 #ifdef USE_HOSTCC
+20 -5
lib/efi_loader/efi_bootmgr.c
··· 18 18 #include <efi_loader.h> 19 19 #include <efi_variable.h> 20 20 #include <asm/unaligned.h> 21 + #include <linux/kernel.h> 22 + #include <linux/sizes.h> 21 23 22 24 static const struct efi_boot_services *bs; 23 25 static const struct efi_runtime_services *rs; ··· 348 350 struct efi_device_path **dp, 349 351 struct udevice **blk) 350 352 { 353 + u64 pages; 351 354 efi_status_t ret; 352 355 struct udevice *ramdisk_blk; 353 356 ··· 362 365 } 363 366 364 367 /* 365 - * TODO: expose the ramdisk to OS. 366 - * Need to pass the ramdisk information by the architecture-specific 367 - * methods such as 'pmem' device-tree node. 368 + * Linux supports 'pmem' which allows OS installers to find, reclaim 369 + * the mounted images and continue the installation since the contents 370 + * of the pmem region are treated as local media. 371 + * 372 + * The memory regions used for it needs to be carved out of the EFI 373 + * memory map. 368 374 */ 369 - ret = efi_add_memory_map(addr, size, EFI_RESERVED_MEMORY_TYPE); 375 + pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); 376 + ret = efi_update_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, 377 + false, true); 370 378 if (ret != EFI_SUCCESS) { 371 - log_err("Memory reservation failed\n"); 379 + log_err("Failed to reserve memory\n"); 372 380 goto err; 373 381 } 374 382 ··· 490 498 ret = EFI_INVALID_PARAMETER; 491 499 goto err; 492 500 } 501 + /* 502 + * Depending on the kernel configuration, pmem memory areas must be 503 + * page aligned or 2MiB aligned. PowerPC is an exception here and 504 + * requires 16MiB alignment, but since we don't have EFI support for 505 + * it, limit the alignment to 2MiB. 506 + */ 507 + image_size = ALIGN(image_size, SZ_2M); 493 508 494 509 /* 495 510 * If the file extension is ".iso" or ".img", mount it and try to load
+67 -18
lib/efi_loader/efi_helper.c
··· 5 5 6 6 #define LOG_CATEGORY LOGC_EFI 7 7 8 + #include <blkmap.h> 8 9 #include <bootm.h> 9 10 #include <env.h> 10 11 #include <image.h> ··· 454 455 */ 455 456 static efi_status_t copy_fdt(void **fdtp) 456 457 { 457 - unsigned long fdt_ram_start = -1L, fdt_pages; 458 458 efi_status_t ret = 0; 459 459 void *fdt, *new_fdt; 460 - u64 new_fdt_addr; 461 - uint fdt_size; 462 - int i; 460 + static u64 new_fdt_addr; 461 + static efi_uintn_t fdt_pages; 462 + ulong fdt_size; 463 463 464 - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 465 - u64 ram_start = gd->bd->bi_dram[i].start; 466 - u64 ram_size = gd->bd->bi_dram[i].size; 464 + /* 465 + * Remove the configuration table that might already be 466 + * installed, ignoring EFI_NOT_FOUND if no device-tree 467 + * is installed 468 + */ 469 + efi_install_configuration_table(&efi_guid_fdt, NULL); 467 470 468 - if (!ram_size) 469 - continue; 471 + if (new_fdt_addr) { 472 + log_debug("%s: Found allocated memory at %#llx, with %#zx pages\n", 473 + __func__, new_fdt_addr, fdt_pages); 474 + 475 + ret = efi_free_pages(new_fdt_addr, fdt_pages); 476 + if (ret != EFI_SUCCESS) 477 + log_err("Unable to free up existing FDT memory region\n"); 470 478 471 - if (ram_start < fdt_ram_start) 472 - fdt_ram_start = ram_start; 479 + new_fdt_addr = 0; 480 + fdt_pages = 0; 473 481 } 474 482 475 483 /* ··· 485 493 &new_fdt_addr); 486 494 if (ret != EFI_SUCCESS) { 487 495 log_err("Failed to reserve space for FDT\n"); 488 - goto done; 496 + return ret; 489 497 } 498 + log_debug("%s: Allocated memory at %#llx, with %#zx pages\n", 499 + __func__, new_fdt_addr, fdt_pages); 500 + 490 501 new_fdt = (void *)(uintptr_t)new_fdt_addr; 491 502 memcpy(new_fdt, fdt, fdt_totalsize(fdt)); 492 503 fdt_set_totalsize(new_fdt, fdt_size); 493 504 494 - *fdtp = (void *)(uintptr_t)new_fdt_addr; 495 - done: 496 - return ret; 505 + *fdtp = new_fdt; 506 + 507 + return EFI_SUCCESS; 497 508 } 498 509 499 510 /** ··· 546 557 const char *fdt_opt; 547 558 uintptr_t fdt_addr; 548 559 549 - /* Look for device tree that is already installed */ 550 - if (efi_get_configuration_table(&efi_guid_fdt)) 551 - return EFI_SUCCESS; 552 560 /* Check if there is a hardware device tree */ 553 561 fdt_opt = env_get("fdt_addr"); 554 562 /* Use our own device tree as fallback */ ··· 680 688 681 689 return ret; 682 690 } 691 + 692 + /** 693 + * pmem_node_efi_memmap_setup() - Add pmem node and tweak EFI memmap 694 + * @fdt: The devicetree to which pmem node is added 695 + * @addr: start address of the pmem node 696 + * @size: size of the memory of the pmem node 697 + * 698 + * The function adds the pmem node to the device-tree along with removing 699 + * the corresponding region from the EFI memory map. Used primarily to 700 + * pass the information of a RAM based ISO image to the OS. 701 + * 702 + * Return: 0 on success, -ve value on error 703 + */ 704 + static int pmem_node_efi_memmap_setup(void *fdt, u64 addr, u64 size) 705 + { 706 + int ret; 707 + u64 pages; 708 + efi_status_t status; 709 + 710 + ret = fdt_fixup_pmem_region(fdt, addr, size); 711 + if (ret) { 712 + log_err("Failed to setup pmem node for addr %#llx, size %#llx, err %d\n", 713 + addr, size, ret); 714 + return ret; 715 + } 716 + 717 + /* Remove the pmem region from the EFI memory map */ 718 + pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); 719 + status = efi_update_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, 720 + false, true); 721 + if (status != EFI_SUCCESS) 722 + return -1; 723 + 724 + return 0; 725 + } 726 + 727 + int fdt_efi_pmem_setup(void *fdt) 728 + { 729 + return blkmap_get_preserved_pmem_slices(pmem_node_efi_memmap_setup, 730 + fdt); 731 + }
+18 -16
lib/efi_loader/efi_memory.c
··· 258 258 } 259 259 260 260 /** 261 - * efi_add_memory_map_pg() - add pages to the memory map 261 + * efi_update_memory_map() - update the memory map by adding/removing pages 262 262 * 263 263 * @start: start address, must be a multiple of 264 264 * EFI_PAGE_SIZE ··· 266 266 * @memory_type: type of memory added 267 267 * @overlap_conventional: region may only overlap free(conventional) 268 268 * memory 269 + * @remove: remove memory map 269 270 * Return: status code 270 271 */ 271 - static 272 - efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, 273 - int memory_type, 274 - bool overlap_conventional) 272 + efi_status_t efi_update_memory_map(u64 start, u64 pages, int memory_type, 273 + bool overlap_conventional, bool remove) 275 274 { 276 275 struct efi_mem_list *lmem; 277 276 struct efi_mem_list *newlist; ··· 279 278 uint64_t carved_pages = 0; 280 279 struct efi_event *evt; 281 280 282 - EFI_PRINT("%s: 0x%llx 0x%llx %d %s\n", __func__, 281 + EFI_PRINT("%s: 0x%llx 0x%llx %d %s %s\n", __func__, 283 282 start, pages, memory_type, overlap_conventional ? 284 - "yes" : "no"); 283 + "yes" : "no", remove ? "remove" : "add"); 285 284 286 285 if (memory_type >= EFI_MAX_MEMORY_TYPE) 287 286 return EFI_INVALID_PARAMETER; ··· 364 363 } 365 364 366 365 /* Add our new map */ 367 - list_add_tail(&newlist->link, &efi_mem); 366 + if (!remove) 367 + list_add_tail(&newlist->link, &efi_mem); 368 + else 369 + free(newlist); 368 370 369 371 /* And make sure memory is listed in descending order */ 370 372 efi_mem_sort(); ··· 401 403 pages = efi_size_in_pages(size + (start & EFI_PAGE_MASK)); 402 404 start &= ~EFI_PAGE_MASK; 403 405 404 - return efi_add_memory_map_pg(start, pages, memory_type, false); 406 + return efi_update_memory_map(start, pages, memory_type, false, false); 405 407 } 406 408 407 409 /** ··· 501 503 502 504 efi_addr = (u64)(uintptr_t)map_sysmem(addr, 0); 503 505 /* Reserve that map in our memory maps */ 504 - ret = efi_add_memory_map_pg(efi_addr, pages, memory_type, true); 506 + ret = efi_update_memory_map(efi_addr, pages, memory_type, true, false); 505 507 if (ret != EFI_SUCCESS) { 506 508 /* Map would overlap, bail out */ 507 509 lmb_free_flags(addr, (u64)pages << EFI_PAGE_SHIFT, flags); ··· 822 824 uboot_stack_size) & ~EFI_PAGE_MASK; 823 825 uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) - 824 826 uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; 825 - efi_add_memory_map_pg(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE, 826 - false); 827 + efi_update_memory_map(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE, 828 + false, false); 827 829 #if defined(__aarch64__) 828 830 /* 829 831 * Runtime Services must be 64KiB aligned according to the ··· 841 843 runtime_end = (uintptr_t)__efi_runtime_stop; 842 844 runtime_end = (runtime_end + runtime_mask) & ~runtime_mask; 843 845 runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; 844 - efi_add_memory_map_pg(runtime_start, runtime_pages, 845 - EFI_RUNTIME_SERVICES_CODE, false); 846 + efi_update_memory_map(runtime_start, runtime_pages, 847 + EFI_RUNTIME_SERVICES_CODE, false, false); 846 848 } 847 849 848 850 int efi_memory_init(void) ··· 877 879 pages = efi_size_in_pages(size + (efi_addr & EFI_PAGE_MASK)); 878 880 efi_addr &= ~EFI_PAGE_MASK; 879 881 880 - status = efi_add_memory_map_pg(efi_addr, pages, 882 + status = efi_update_memory_map(efi_addr, pages, 881 883 op == LMB_MAP_OP_RESERVE ? 882 884 EFI_BOOT_SERVICES_DATA : 883 885 EFI_CONVENTIONAL_MEMORY, 884 - false); 886 + false, false); 885 887 if (status != EFI_SUCCESS) { 886 888 log_err("LMB Map notify failure %lu\n", 887 889 status & ~EFI_ERROR_MASK);