0001
0002
0003 #include <linux/efi.h>
0004 #include <asm/efi.h>
0005
0006 #include "efistub.h"
0007
0008 static inline bool mmap_has_headroom(unsigned long buff_size,
0009 unsigned long map_size,
0010 unsigned long desc_size)
0011 {
0012 unsigned long slack = buff_size - map_size;
0013
0014 return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS;
0015 }
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
0027 {
0028 efi_memory_desc_t *m = NULL;
0029 efi_status_t status;
0030 unsigned long key;
0031 u32 desc_version;
0032
0033 *map->desc_size = sizeof(*m);
0034 *map->map_size = *map->desc_size * 32;
0035 *map->buff_size = *map->map_size;
0036 again:
0037 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
0038 *map->map_size, (void **)&m);
0039 if (status != EFI_SUCCESS)
0040 goto fail;
0041
0042 *map->desc_size = 0;
0043 key = 0;
0044 status = efi_bs_call(get_memory_map, map->map_size, m,
0045 &key, map->desc_size, &desc_version);
0046 if (status == EFI_BUFFER_TOO_SMALL ||
0047 !mmap_has_headroom(*map->buff_size, *map->map_size,
0048 *map->desc_size)) {
0049 efi_bs_call(free_pool, m);
0050
0051
0052
0053
0054
0055
0056
0057 *map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS;
0058 *map->buff_size = *map->map_size;
0059 goto again;
0060 }
0061
0062 if (status == EFI_SUCCESS) {
0063 if (map->key_ptr)
0064 *map->key_ptr = key;
0065 if (map->desc_ver)
0066 *map->desc_ver = desc_version;
0067 } else {
0068 efi_bs_call(free_pool, m);
0069 }
0070
0071 fail:
0072 *map->map = m;
0073 return status;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
0092 unsigned long max)
0093 {
0094 efi_physical_addr_t alloc_addr;
0095 efi_status_t status;
0096
0097 if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)
0098 return efi_allocate_pages_aligned(size, addr, max,
0099 EFI_ALLOC_ALIGN);
0100
0101 alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;
0102 status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
0103 EFI_LOADER_DATA, DIV_ROUND_UP(size, EFI_PAGE_SIZE),
0104 &alloc_addr);
0105 if (status != EFI_SUCCESS)
0106 return status;
0107
0108 *addr = alloc_addr;
0109 return EFI_SUCCESS;
0110 }
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 void efi_free(unsigned long size, unsigned long addr)
0124 {
0125 unsigned long nr_pages;
0126
0127 if (!size)
0128 return;
0129
0130 nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
0131 efi_bs_call(free_pages, addr, nr_pages);
0132 }