1 /*
2 * Copyright (c) 2011 - 2022, Intel Corporation.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Intel Corporation nor the names of its
15 * contributors may be used to endorse or promote products
16 * derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <efi.h>
34 #include <efilib.h>
35 #include "efilinux.h"
36 #include "stdlib.h"
37 #include "boot.h"
38
39 EFI_STATUS
emalloc_reserved_aligned(EFI_PHYSICAL_ADDRESS * addr,UINTN size,UINTN align,EFI_PHYSICAL_ADDRESS minaddr,EFI_PHYSICAL_ADDRESS maxaddr)40 emalloc_reserved_aligned(EFI_PHYSICAL_ADDRESS *addr, UINTN size, UINTN align,
41 EFI_PHYSICAL_ADDRESS minaddr, EFI_PHYSICAL_ADDRESS maxaddr)
42 {
43 struct efi_memmap_info mmap_info;
44 UINTN msize, desc_sz, desc_addr, pages;
45 EFI_MEMORY_DESCRIPTOR *mbuf;
46 EFI_STATUS err;
47
48 pages = EFI_SIZE_TO_PAGES(size);
49
50 /* Memory map may change so we request it again */
51 err = get_efi_memmap(&mmap_info, 0);
52 if (err != EFI_SUCCESS)
53 goto fail;
54
55 msize = mmap_info.map_size;
56 desc_sz = mmap_info.desc_size;
57 mbuf = mmap_info.mmap;
58
59 /* ACRN requests for lowest possible address that's greater than minaddr */
60 /* TODO: in the future we may want to support both preferences */
61 for (desc_addr = (UINTN)mbuf; desc_addr <= (UINTN)mbuf + msize - desc_sz; desc_addr += desc_sz) {
62 EFI_MEMORY_DESCRIPTOR *desc;
63 EFI_PHYSICAL_ADDRESS start, end;
64
65 desc = (EFI_MEMORY_DESCRIPTOR*)desc_addr;
66 if (desc->Type != EfiConventionalMemory)
67 continue;
68
69 start = desc->PhysicalStart;
70 end = start + (desc->NumberOfPages << EFI_PAGE_SHIFT);
71
72 /* 1MB low memory is allocated only if required/requested */
73 if ((end <= MEM_ADDR_1MB) && (maxaddr > MEM_ADDR_1MB))
74 continue;
75
76 /* starting allocation from 1M above unless requested */
77 if ((start < MEM_ADDR_1MB) && (maxaddr > MEM_ADDR_1MB)) {
78 start = MEM_ADDR_1MB;
79 }
80
81 /* zero page won't be allocated */
82 if (start < 4096) {
83 start = 4096;
84 }
85
86 if (start < minaddr) {
87 start = minaddr;
88 }
89 start = (start + align - 1) & ~(align - 1);
90
91 /* Since this routine is called during booting, memory block is large
92 * enought, the reduction of memory size for memory alignment won't
93 * impact allocation. It is true in most cases. if it is not true, loop
94 * again
95 */
96 if ((start + size <= end) && (start + size <= maxaddr)) {
97 err = allocate_pages(AllocateAddress, EfiReservedMemoryType, pages, &start);
98 if (err == EFI_SUCCESS) {
99 *addr = start;
100 break;
101 }
102 }
103 }
104 if (desc_addr > (UINTN)mbuf + msize - desc_sz) {
105 err = EFI_OUT_OF_RESOURCES;
106 }
107
108 free_pool(mbuf);
109
110 fail:
111 return err;
112 }
113
dump_e820(void)114 EFI_STATUS dump_e820(void)
115 {
116 UINTN map_size, map_key, desc_size;
117 EFI_MEMORY_DESCRIPTOR *map_buf;
118 UINTN d, map_end;
119 UINTN i;
120 UINT32 desc_version;
121 EFI_STATUS err;
122
123 err = memory_map(&map_buf, &map_size, &map_key,
124 &desc_size, &desc_version);
125 if (err != EFI_SUCCESS)
126 goto fail;
127
128 d = (UINTN)map_buf;
129 map_end = (UINTN)map_buf + map_size;
130
131 for (i = 0; d < map_end; d += desc_size, i++) {
132 EFI_MEMORY_DESCRIPTOR *desc;
133 EFI_PHYSICAL_ADDRESS start, end;
134
135 desc = (EFI_MEMORY_DESCRIPTOR *)d;
136 if (desc->Type != EfiConventionalMemory)
137 continue;
138
139 start = desc->PhysicalStart;
140 end = start + (desc->NumberOfPages << EFI_PAGE_SHIFT);
141
142 Print(L"[%d]start:%lx, end:%lx, type:%d\n", i, start, end, desc->Type);
143 }
144
145 free_pool(map_buf);
146 fail:
147 return err;
148 }
149
150