diff --git a/src/include/bootmem.h b/src/include/bootmem.h index 5796765ad6..b1352e395b 100644 --- a/src/include/bootmem.h +++ b/src/include/bootmem.h @@ -61,6 +61,22 @@ void bootmem_platform_add_ranges(void); void bootmem_add_range(uint64_t start, uint64_t size, const enum bootmem_type tag); +/* + * bootmem_add_range_from - Add a memory range of a specific type from another range + * @start: Start address of the new memory range + * @size: Size of the new memory range + * @new_tag: The new bootmem_type for the range + * @from_tag: The bootmem_type from which the new range should be carved out + * + * This function adds a memory range with `new_tag` only if it is fully + * contained within an existing range of `from_tag`. This is useful for + * carving out specific memory regions from a larger, already defined area. + * + * Return: 0 on success, or a negative error code on failure. + */ +int bootmem_add_range_from(uint64_t start, uint64_t size, const enum bootmem_type new_tag, + const enum bootmem_type from_tag); + /* Print current range map of boot memory. */ void bootmem_dump_ranges(void); diff --git a/src/lib/bootmem.c b/src/lib/bootmem.c index ab15e85d08..f8963f3299 100644 --- a/src/lib/bootmem.c +++ b/src/lib/bootmem.c @@ -14,6 +14,8 @@ static int table_written; static struct memranges bootmem; static struct memranges bootmem_os; +static const char *bootmem_range_string(const enum bootmem_type tag); + static int bootmem_is_initialized(void) { return initialized; @@ -106,6 +108,24 @@ void bootmem_add_range(uint64_t start, uint64_t size, }; } +int bootmem_add_range_from(uint64_t start, uint64_t size, const enum bootmem_type new_tag, + const enum bootmem_type from_tag) +{ + if (new_tag == from_tag) + return -1; + + if (!bootmem_region_targets_type(start, size, from_tag)) { + printk(BIOS_ERR, "%s: Failed to add the range [%#llx, %#llx)" + " from tag %s to %s\n", __func__, start, start + size, + bootmem_range_string(from_tag), bootmem_range_string(new_tag)); + return -1; + } + + bootmem_add_range(start, size, new_tag); + + return 0; +} + void bootmem_write_memory_table(struct lb_memory *mem) { const struct range_entry *r;