aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firmware/efi/fake_mem.c229
1 files changed, 134 insertions, 95 deletions
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 939eec47139f..446c669431c0 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -54,43 +54,151 @@ static int __init cmp_fake_mem(const void *x1, const void *x2)
54 return 0; 54 return 0;
55} 55}
56 56
57/**
58 * efi_fake_memmap_split_count - Count number of additional EFI memmap entries
59 * @md: EFI memory descriptor to split
60 * @range: Address range (start, end) to split around
61 *
62 * Returns the number of additional EFI memmap entries required to
63 * accomodate @range.
64 */
65static int efi_fake_memmap_split_count(efi_memory_desc_t *md, struct range *range)
66{
67 u64 m_start, m_end;
68 u64 start, end;
69 int count = 0;
70
71 start = md->phys_addr;
72 end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
73
74 /* modifying range */
75 m_start = range->start;
76 m_end = range->end;
77
78 if (m_start <= start) {
79 /* split into 2 parts */
80 if (start < m_end && m_end < end)
81 count++;
82 }
83
84 if (start < m_start && m_start < end) {
85 /* split into 3 parts */
86 if (m_end < end)
87 count += 2;
88 /* split into 2 parts */
89 if (end <= m_end)
90 count++;
91 }
92
93 return count;
94}
95
96/**
97 * efi_fake_memmap_insert - Insert a fake memory region in an EFI memmap
98 * @old_memmap: The existing EFI memory map structure
99 * @buf: Address of buffer to store new map
100 * @mem: Fake memory map entry to insert
101 *
102 * It is suggested that you call efi_fake_memmap_split_count() first
103 * to see how large @buf needs to be.
104 */
105static void efi_fake_memmap_insert(struct efi_memory_map *old_memmap,
106 void *buf, struct fake_mem *mem)
107{
108 u64 m_start, m_end, m_attr;
109 efi_memory_desc_t *md;
110 u64 start, end;
111 void *old, *new;
112
113 /* modifying range */
114 m_start = mem->range.start;
115 m_end = mem->range.end;
116 m_attr = mem->attribute;
117
118 for (old = old_memmap->map, new = buf;
119 old < old_memmap->map_end;
120 old += old_memmap->desc_size, new += old_memmap->desc_size) {
121
122 /* copy original EFI memory descriptor */
123 memcpy(new, old, old_memmap->desc_size);
124 md = new;
125 start = md->phys_addr;
126 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
127
128 if (m_start <= start && end <= m_end)
129 md->attribute |= m_attr;
130
131 if (m_start <= start &&
132 (start < m_end && m_end < end)) {
133 /* first part */
134 md->attribute |= m_attr;
135 md->num_pages = (m_end - md->phys_addr + 1) >>
136 EFI_PAGE_SHIFT;
137 /* latter part */
138 new += old_memmap->desc_size;
139 memcpy(new, old, old_memmap->desc_size);
140 md = new;
141 md->phys_addr = m_end + 1;
142 md->num_pages = (end - md->phys_addr + 1) >>
143 EFI_PAGE_SHIFT;
144 }
145
146 if ((start < m_start && m_start < end) && m_end < end) {
147 /* first part */
148 md->num_pages = (m_start - md->phys_addr) >>
149 EFI_PAGE_SHIFT;
150 /* middle part */
151 new += old_memmap->desc_size;
152 memcpy(new, old, old_memmap->desc_size);
153 md = new;
154 md->attribute |= m_attr;
155 md->phys_addr = m_start;
156 md->num_pages = (m_end - m_start + 1) >>
157 EFI_PAGE_SHIFT;
158 /* last part */
159 new += old_memmap->desc_size;
160 memcpy(new, old, old_memmap->desc_size);
161 md = new;
162 md->phys_addr = m_end + 1;
163 md->num_pages = (end - m_end) >>
164 EFI_PAGE_SHIFT;
165 }
166
167 if ((start < m_start && m_start < end) &&
168 (end <= m_end)) {
169 /* first part */
170 md->num_pages = (m_start - md->phys_addr) >>
171 EFI_PAGE_SHIFT;
172 /* latter part */
173 new += old_memmap->desc_size;
174 memcpy(new, old, old_memmap->desc_size);
175 md = new;
176 md->phys_addr = m_start;
177 md->num_pages = (end - md->phys_addr + 1) >>
178 EFI_PAGE_SHIFT;
179 md->attribute |= m_attr;
180 }
181 }
182}
183
57void __init efi_fake_memmap(void) 184void __init efi_fake_memmap(void)
58{ 185{
59 u64 start, end, m_start, m_end, m_attr;
60 struct efi_memory_map_data data; 186 struct efi_memory_map_data data;
61 int new_nr_map = efi.memmap.nr_map; 187 int new_nr_map = efi.memmap.nr_map;
62 efi_memory_desc_t *md; 188 efi_memory_desc_t *md;
63 phys_addr_t new_memmap_phy; 189 phys_addr_t new_memmap_phy;
64 void *new_memmap; 190 void *new_memmap;
65 void *old, *new;
66 int i; 191 int i;
67 192
68 if (!nr_fake_mem) 193 if (!nr_fake_mem)
69 return; 194 return;
70 195
71 /* count up the number of EFI memory descriptor */ 196 /* count up the number of EFI memory descriptor */
72 for_each_efi_memory_desc(md) { 197 for (i = 0; i < nr_fake_mem; i++) {
73 start = md->phys_addr; 198 for_each_efi_memory_desc(md) {
74 end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; 199 struct range *r = &fake_mems[i].range;
75 200
76 for (i = 0; i < nr_fake_mem; i++) { 201 new_nr_map += efi_fake_memmap_split_count(md, r);
77 /* modifying range */
78 m_start = fake_mems[i].range.start;
79 m_end = fake_mems[i].range.end;
80
81 if (m_start <= start) {
82 /* split into 2 parts */
83 if (start < m_end && m_end < end)
84 new_nr_map++;
85 }
86 if (start < m_start && m_start < end) {
87 /* split into 3 parts */
88 if (m_end < end)
89 new_nr_map += 2;
90 /* split into 2 parts */
91 if (end <= m_end)
92 new_nr_map++;
93 }
94 } 202 }
95 } 203 }
96 204
@@ -108,77 +216,8 @@ void __init efi_fake_memmap(void)
108 return; 216 return;
109 } 217 }
110 218
111 for (old = efi.memmap.map, new = new_memmap; 219 for (i = 0; i < nr_fake_mem; i++)
112 old < efi.memmap.map_end; 220 efi_fake_memmap_insert(&efi.memmap, new_memmap, &fake_mems[i]);
113 old += efi.memmap.desc_size, new += efi.memmap.desc_size) {
114
115 /* copy original EFI memory descriptor */
116 memcpy(new, old, efi.memmap.desc_size);
117 md = new;
118 start = md->phys_addr;
119 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
120
121 for (i = 0; i < nr_fake_mem; i++) {
122 /* modifying range */
123 m_start = fake_mems[i].range.start;
124 m_end = fake_mems[i].range.end;
125 m_attr = fake_mems[i].attribute;
126
127 if (m_start <= start && end <= m_end)
128 md->attribute |= m_attr;
129
130 if (m_start <= start &&
131 (start < m_end && m_end < end)) {
132 /* first part */
133 md->attribute |= m_attr;
134 md->num_pages = (m_end - md->phys_addr + 1) >>
135 EFI_PAGE_SHIFT;
136 /* latter part */
137 new += efi.memmap.desc_size;
138 memcpy(new, old, efi.memmap.desc_size);
139 md = new;
140 md->phys_addr = m_end + 1;
141 md->num_pages = (end - md->phys_addr + 1) >>
142 EFI_PAGE_SHIFT;
143 }
144
145 if ((start < m_start && m_start < end) && m_end < end) {
146 /* first part */
147 md->num_pages = (m_start - md->phys_addr) >>
148 EFI_PAGE_SHIFT;
149 /* middle part */
150 new += efi.memmap.desc_size;
151 memcpy(new, old, efi.memmap.desc_size);
152 md = new;
153 md->attribute |= m_attr;
154 md->phys_addr = m_start;
155 md->num_pages = (m_end - m_start + 1) >>
156 EFI_PAGE_SHIFT;
157 /* last part */
158 new += efi.memmap.desc_size;
159 memcpy(new, old, efi.memmap.desc_size);
160 md = new;
161 md->phys_addr = m_end + 1;
162 md->num_pages = (end - m_end) >>
163 EFI_PAGE_SHIFT;
164 }
165
166 if ((start < m_start && m_start < end) &&
167 (end <= m_end)) {
168 /* first part */
169 md->num_pages = (m_start - md->phys_addr) >>
170 EFI_PAGE_SHIFT;
171 /* latter part */
172 new += efi.memmap.desc_size;
173 memcpy(new, old, efi.memmap.desc_size);
174 md = new;
175 md->phys_addr = m_start;
176 md->num_pages = (end - md->phys_addr + 1) >>
177 EFI_PAGE_SHIFT;
178 md->attribute |= m_attr;
179 }
180 }
181 }
182 221
183 /* swap into new EFI memmap */ 222 /* swap into new EFI memmap */
184 early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map); 223 early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map);