123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- #include <dragonstub/dragonstub.h>
- #include <dragonstub/linux/math.h>
- #include <dragonstub/linux/align.h>
- #include <dragonstub/minmax.h>
- efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
- bool install_cfg_tbl)
- {
- int memtype = install_cfg_tbl ? EfiACPIReclaimMemory : EfiLoaderData;
- efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID;
- struct efi_boot_memmap *m, tmp;
- efi_status_t status;
- unsigned long size;
- tmp.map_size = 0;
- status = efi_bs_call(GetMemoryMap, &tmp.map_size, NULL, &tmp.map_key,
- &tmp.desc_size, &tmp.desc_ver);
- if (status != EFI_BUFFER_TOO_SMALL)
- return EFI_LOAD_ERROR;
- size = tmp.map_size + tmp.desc_size * EFI_MMAP_NR_SLACK_SLOTS;
- status = efi_bs_call(AllocatePool, memtype, sizeof(*m) + size,
- (void **)&m);
- if (status != EFI_SUCCESS)
- return status;
- if (install_cfg_tbl) {
-
- status = efi_bs_call(InstallConfigurationTable, &tbl_guid, m);
- if (status != EFI_SUCCESS)
- goto free_map;
- }
- m->buff_size = m->map_size = size;
- status = efi_bs_call(GetMemoryMap, &m->map_size, m->map, &m->map_key,
- &m->desc_size, &m->desc_ver);
- if (status != EFI_SUCCESS)
- goto uninstall_table;
- *map = m;
- return EFI_SUCCESS;
- uninstall_table:
- if (install_cfg_tbl)
- efi_bs_call(InstallConfigurationTable, &tbl_guid, NULL);
- free_map:
- efi_bs_call(FreePool, m);
- return status;
- }
- efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
- unsigned long max)
- {
- efi_physical_addr_t alloc_addr;
- efi_status_t status;
- max = min(max, EFI_ALLOC_LIMIT);
-
-
-
- alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;
- status = efi_bs_call(AllocatePages, EFI_ALLOCATE_MAX_ADDRESS,
- EfiLoaderData, DIV_ROUND_UP(size, EFI_PAGE_SIZE),
- &alloc_addr);
- if (status != EFI_SUCCESS)
- return status;
- *addr = alloc_addr;
- return EFI_SUCCESS;
- }
- efi_status_t efi_allocate_pages_exact(unsigned long size, unsigned long addr)
- {
- efi_status_t status;
- u64 addr_rounded = addr & ~(EFI_ALLOC_ALIGN - 1);
- size += addr - addr_rounded;
- u32 pagecount = DIV_ROUND_UP(size, EFI_PAGE_SIZE);
- efi_debug(
- "efi_allocate_pages_exact: size=%d, addr=%p, addr_rounded=%p, pagecount=%d\n",
- size, addr, addr_rounded, pagecount);
- status = efi_bs_call(AllocatePages, AllocateAddress, EfiLoaderData,
- pagecount, (EFI_PHYSICAL_ADDRESS *)&addr);
-
-
-
- if (status != EFI_SUCCESS)
- return status;
- return EFI_SUCCESS;
- }
- void efi_free(unsigned long size, unsigned long addr)
- {
- unsigned long nr_pages;
- if (!size)
- return;
- nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
- efi_bs_call(FreePages, addr, nr_pages);
- }
|