diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig | 7 | ||||
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 10 | ||||
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 1022 | ||||
-rw-r--r-- | arch/x86/boot/compressed/eboot.h | 61 | ||||
-rw-r--r-- | arch/x86/boot/compressed/efi_stub_32.S | 86 | ||||
-rw-r--r-- | arch/x86/boot/compressed/efi_stub_64.S | 1 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_32.S | 22 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_64.S | 20 | ||||
-rw-r--r-- | arch/x86/boot/compressed/string.c | 9 | ||||
-rw-r--r-- | arch/x86/boot/header.S | 158 | ||||
-rw-r--r-- | arch/x86/boot/string.c | 35 | ||||
-rw-r--r-- | arch/x86/boot/tools/build.c | 39 | ||||
-rw-r--r-- | arch/x86/include/asm/bootparam.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/efi.h | 4 | ||||
-rw-r--r-- | arch/x86/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 7 |
16 files changed, 1478 insertions, 7 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1a31254ceb83..2513da0e6b67 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -1489,6 +1489,13 @@ config EFI | |||
1489 | resultant kernel should continue to boot on existing non-EFI | 1489 | resultant kernel should continue to boot on existing non-EFI |
1490 | platforms. | 1490 | platforms. |
1491 | 1491 | ||
1492 | config EFI_STUB | ||
1493 | bool "EFI stub support" | ||
1494 | depends on EFI | ||
1495 | ---help--- | ||
1496 | This kernel feature allows a bzImage to be loaded directly | ||
1497 | by EFI firmware without the use of a bootloader. | ||
1498 | |||
1492 | config SECCOMP | 1499 | config SECCOMP |
1493 | def_bool y | 1500 | def_bool y |
1494 | prompt "Enable seccomp to safely compute untrusted bytecode" | 1501 | prompt "Enable seccomp to safely compute untrusted bytecode" |
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 09664efb9cee..b123b9a8f5b3 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -23,7 +23,15 @@ LDFLAGS_vmlinux := -T | |||
23 | 23 | ||
24 | hostprogs-y := mkpiggy | 24 | hostprogs-y := mkpiggy |
25 | 25 | ||
26 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o $(obj)/piggy.o FORCE | 26 | VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ |
27 | $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ | ||
28 | $(obj)/piggy.o | ||
29 | |||
30 | ifeq ($(CONFIG_EFI_STUB), y) | ||
31 | VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o | ||
32 | endif | ||
33 | |||
34 | $(obj)/vmlinux: $(VMLINUX_OBJS) FORCE | ||
27 | $(call if_changed,ld) | 35 | $(call if_changed,ld) |
28 | @: | 36 | @: |
29 | 37 | ||
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c new file mode 100644 index 000000000000..fec216f4fbc3 --- /dev/null +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -0,0 +1,1022 @@ | |||
1 | /* ----------------------------------------------------------------------- | ||
2 | * | ||
3 | * Copyright 2011 Intel Corporation; author Matt Fleming | ||
4 | * | ||
5 | * This file is part of the Linux kernel, and is made available under | ||
6 | * the terms of the GNU General Public License version 2. | ||
7 | * | ||
8 | * ----------------------------------------------------------------------- */ | ||
9 | |||
10 | #include <linux/efi.h> | ||
11 | #include <asm/efi.h> | ||
12 | #include <asm/setup.h> | ||
13 | #include <asm/desc.h> | ||
14 | |||
15 | #include "eboot.h" | ||
16 | |||
17 | static efi_system_table_t *sys_table; | ||
18 | |||
19 | static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size, | ||
20 | unsigned long *desc_size) | ||
21 | { | ||
22 | efi_memory_desc_t *m = NULL; | ||
23 | efi_status_t status; | ||
24 | unsigned long key; | ||
25 | u32 desc_version; | ||
26 | |||
27 | *map_size = sizeof(*m) * 32; | ||
28 | again: | ||
29 | /* | ||
30 | * Add an additional efi_memory_desc_t because we're doing an | ||
31 | * allocation which may be in a new descriptor region. | ||
32 | */ | ||
33 | *map_size += sizeof(*m); | ||
34 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
35 | EFI_LOADER_DATA, *map_size, (void **)&m); | ||
36 | if (status != EFI_SUCCESS) | ||
37 | goto fail; | ||
38 | |||
39 | status = efi_call_phys5(sys_table->boottime->get_memory_map, map_size, | ||
40 | m, &key, desc_size, &desc_version); | ||
41 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
42 | efi_call_phys1(sys_table->boottime->free_pool, m); | ||
43 | goto again; | ||
44 | } | ||
45 | |||
46 | if (status != EFI_SUCCESS) | ||
47 | efi_call_phys1(sys_table->boottime->free_pool, m); | ||
48 | |||
49 | fail: | ||
50 | *map = m; | ||
51 | return status; | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Allocate at the highest possible address that is not above 'max'. | ||
56 | */ | ||
57 | static efi_status_t high_alloc(unsigned long size, unsigned long align, | ||
58 | unsigned long *addr, unsigned long max) | ||
59 | { | ||
60 | unsigned long map_size, desc_size; | ||
61 | efi_memory_desc_t *map; | ||
62 | efi_status_t status; | ||
63 | unsigned long nr_pages; | ||
64 | u64 max_addr = 0; | ||
65 | int i; | ||
66 | |||
67 | status = __get_map(&map, &map_size, &desc_size); | ||
68 | if (status != EFI_SUCCESS) | ||
69 | goto fail; | ||
70 | |||
71 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
72 | again: | ||
73 | for (i = 0; i < map_size / desc_size; i++) { | ||
74 | efi_memory_desc_t *desc; | ||
75 | unsigned long m = (unsigned long)map; | ||
76 | u64 start, end; | ||
77 | |||
78 | desc = (efi_memory_desc_t *)(m + (i * desc_size)); | ||
79 | if (desc->type != EFI_CONVENTIONAL_MEMORY) | ||
80 | continue; | ||
81 | |||
82 | if (desc->num_pages < nr_pages) | ||
83 | continue; | ||
84 | |||
85 | start = desc->phys_addr; | ||
86 | end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); | ||
87 | |||
88 | if ((start + size) > end || (start + size) > max) | ||
89 | continue; | ||
90 | |||
91 | if (end - size > max) | ||
92 | end = max; | ||
93 | |||
94 | if (round_down(end - size, align) < start) | ||
95 | continue; | ||
96 | |||
97 | start = round_down(end - size, align); | ||
98 | |||
99 | /* | ||
100 | * Don't allocate at 0x0. It will confuse code that | ||
101 | * checks pointers against NULL. | ||
102 | */ | ||
103 | if (start == 0x0) | ||
104 | continue; | ||
105 | |||
106 | if (start > max_addr) | ||
107 | max_addr = start; | ||
108 | } | ||
109 | |||
110 | if (!max_addr) | ||
111 | status = EFI_NOT_FOUND; | ||
112 | else { | ||
113 | status = efi_call_phys4(sys_table->boottime->allocate_pages, | ||
114 | EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, | ||
115 | nr_pages, &max_addr); | ||
116 | if (status != EFI_SUCCESS) { | ||
117 | max = max_addr; | ||
118 | max_addr = 0; | ||
119 | goto again; | ||
120 | } | ||
121 | |||
122 | *addr = max_addr; | ||
123 | } | ||
124 | |||
125 | free_pool: | ||
126 | efi_call_phys1(sys_table->boottime->free_pool, map); | ||
127 | |||
128 | fail: | ||
129 | return status; | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * Allocate at the lowest possible address. | ||
134 | */ | ||
135 | static efi_status_t low_alloc(unsigned long size, unsigned long align, | ||
136 | unsigned long *addr) | ||
137 | { | ||
138 | unsigned long map_size, desc_size; | ||
139 | efi_memory_desc_t *map; | ||
140 | efi_status_t status; | ||
141 | unsigned long nr_pages; | ||
142 | int i; | ||
143 | |||
144 | status = __get_map(&map, &map_size, &desc_size); | ||
145 | if (status != EFI_SUCCESS) | ||
146 | goto fail; | ||
147 | |||
148 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
149 | for (i = 0; i < map_size / desc_size; i++) { | ||
150 | efi_memory_desc_t *desc; | ||
151 | unsigned long m = (unsigned long)map; | ||
152 | u64 start, end; | ||
153 | |||
154 | desc = (efi_memory_desc_t *)(m + (i * desc_size)); | ||
155 | |||
156 | if (desc->type != EFI_CONVENTIONAL_MEMORY) | ||
157 | continue; | ||
158 | |||
159 | if (desc->num_pages < nr_pages) | ||
160 | continue; | ||
161 | |||
162 | start = desc->phys_addr; | ||
163 | end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); | ||
164 | |||
165 | /* | ||
166 | * Don't allocate at 0x0. It will confuse code that | ||
167 | * checks pointers against NULL. Skip the first 8 | ||
168 | * bytes so we start at a nice even number. | ||
169 | */ | ||
170 | if (start == 0x0) | ||
171 | start += 8; | ||
172 | |||
173 | start = round_up(start, align); | ||
174 | if ((start + size) > end) | ||
175 | continue; | ||
176 | |||
177 | status = efi_call_phys4(sys_table->boottime->allocate_pages, | ||
178 | EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, | ||
179 | nr_pages, &start); | ||
180 | if (status == EFI_SUCCESS) { | ||
181 | *addr = start; | ||
182 | break; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | if (i == map_size / desc_size) | ||
187 | status = EFI_NOT_FOUND; | ||
188 | |||
189 | free_pool: | ||
190 | efi_call_phys1(sys_table->boottime->free_pool, map); | ||
191 | fail: | ||
192 | return status; | ||
193 | } | ||
194 | |||
195 | static void low_free(unsigned long size, unsigned long addr) | ||
196 | { | ||
197 | unsigned long nr_pages; | ||
198 | |||
199 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
200 | efi_call_phys2(sys_table->boottime->free_pages, addr, size); | ||
201 | } | ||
202 | |||
203 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) | ||
204 | { | ||
205 | u8 first, len; | ||
206 | |||
207 | first = 0; | ||
208 | len = 0; | ||
209 | |||
210 | if (mask) { | ||
211 | while (!(mask & 0x1)) { | ||
212 | mask = mask >> 1; | ||
213 | first++; | ||
214 | } | ||
215 | |||
216 | while (mask & 0x1) { | ||
217 | mask = mask >> 1; | ||
218 | len++; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | *pos = first; | ||
223 | *size = len; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * See if we have Graphics Output Protocol | ||
228 | */ | ||
229 | static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, | ||
230 | unsigned long size) | ||
231 | { | ||
232 | struct efi_graphics_output_protocol *gop, *first_gop; | ||
233 | struct efi_pixel_bitmask pixel_info; | ||
234 | unsigned long nr_gops; | ||
235 | efi_status_t status; | ||
236 | void **gop_handle; | ||
237 | u16 width, height; | ||
238 | u32 fb_base, fb_size; | ||
239 | u32 pixels_per_scan_line; | ||
240 | int pixel_format; | ||
241 | int i; | ||
242 | |||
243 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
244 | EFI_LOADER_DATA, size, &gop_handle); | ||
245 | if (status != EFI_SUCCESS) | ||
246 | return status; | ||
247 | |||
248 | status = efi_call_phys5(sys_table->boottime->locate_handle, | ||
249 | EFI_LOCATE_BY_PROTOCOL, proto, | ||
250 | NULL, &size, gop_handle); | ||
251 | if (status != EFI_SUCCESS) | ||
252 | goto free_handle; | ||
253 | |||
254 | first_gop = NULL; | ||
255 | |||
256 | nr_gops = size / sizeof(void *); | ||
257 | for (i = 0; i < nr_gops; i++) { | ||
258 | struct efi_graphics_output_mode_info *info; | ||
259 | efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; | ||
260 | void *pciio; | ||
261 | void *h = gop_handle[i]; | ||
262 | |||
263 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | ||
264 | h, proto, &gop); | ||
265 | if (status != EFI_SUCCESS) | ||
266 | continue; | ||
267 | |||
268 | efi_call_phys3(sys_table->boottime->handle_protocol, | ||
269 | h, &pciio_proto, &pciio); | ||
270 | |||
271 | status = efi_call_phys4(gop->query_mode, gop, | ||
272 | gop->mode->mode, &size, &info); | ||
273 | if (status == EFI_SUCCESS && (!first_gop || pciio)) { | ||
274 | /* | ||
275 | * Apple provide GOPs that are not backed by | ||
276 | * real hardware (they're used to handle | ||
277 | * multiple displays). The workaround is to | ||
278 | * search for a GOP implementing the PCIIO | ||
279 | * protocol, and if one isn't found, to just | ||
280 | * fallback to the first GOP. | ||
281 | */ | ||
282 | width = info->horizontal_resolution; | ||
283 | height = info->vertical_resolution; | ||
284 | fb_base = gop->mode->frame_buffer_base; | ||
285 | fb_size = gop->mode->frame_buffer_size; | ||
286 | pixel_format = info->pixel_format; | ||
287 | pixel_info = info->pixel_information; | ||
288 | pixels_per_scan_line = info->pixels_per_scan_line; | ||
289 | |||
290 | /* | ||
291 | * Once we've found a GOP supporting PCIIO, | ||
292 | * don't bother looking any further. | ||
293 | */ | ||
294 | if (pciio) | ||
295 | break; | ||
296 | |||
297 | first_gop = gop; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* Did we find any GOPs? */ | ||
302 | if (!first_gop) | ||
303 | goto free_handle; | ||
304 | |||
305 | /* EFI framebuffer */ | ||
306 | si->orig_video_isVGA = VIDEO_TYPE_EFI; | ||
307 | |||
308 | si->lfb_width = width; | ||
309 | si->lfb_height = height; | ||
310 | si->lfb_base = fb_base; | ||
311 | si->lfb_size = fb_size; | ||
312 | si->pages = 1; | ||
313 | |||
314 | if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { | ||
315 | si->lfb_depth = 32; | ||
316 | si->lfb_linelength = pixels_per_scan_line * 4; | ||
317 | si->red_size = 8; | ||
318 | si->red_pos = 0; | ||
319 | si->green_size = 8; | ||
320 | si->green_pos = 8; | ||
321 | si->blue_size = 8; | ||
322 | si->blue_pos = 16; | ||
323 | si->rsvd_size = 8; | ||
324 | si->rsvd_pos = 24; | ||
325 | } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { | ||
326 | si->lfb_depth = 32; | ||
327 | si->lfb_linelength = pixels_per_scan_line * 4; | ||
328 | si->red_size = 8; | ||
329 | si->red_pos = 16; | ||
330 | si->green_size = 8; | ||
331 | si->green_pos = 8; | ||
332 | si->blue_size = 8; | ||
333 | si->blue_pos = 0; | ||
334 | si->rsvd_size = 8; | ||
335 | si->rsvd_pos = 24; | ||
336 | } else if (pixel_format == PIXEL_BIT_MASK) { | ||
337 | find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size); | ||
338 | find_bits(pixel_info.green_mask, &si->green_pos, | ||
339 | &si->green_size); | ||
340 | find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size); | ||
341 | find_bits(pixel_info.reserved_mask, &si->rsvd_pos, | ||
342 | &si->rsvd_size); | ||
343 | si->lfb_depth = si->red_size + si->green_size + | ||
344 | si->blue_size + si->rsvd_size; | ||
345 | si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; | ||
346 | } else { | ||
347 | si->lfb_depth = 4; | ||
348 | si->lfb_linelength = si->lfb_width / 2; | ||
349 | si->red_size = 0; | ||
350 | si->red_pos = 0; | ||
351 | si->green_size = 0; | ||
352 | si->green_pos = 0; | ||
353 | si->blue_size = 0; | ||
354 | si->blue_pos = 0; | ||
355 | si->rsvd_size = 0; | ||
356 | si->rsvd_pos = 0; | ||
357 | } | ||
358 | |||
359 | free_handle: | ||
360 | efi_call_phys1(sys_table->boottime->free_pool, gop_handle); | ||
361 | return status; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * See if we have Universal Graphics Adapter (UGA) protocol | ||
366 | */ | ||
367 | static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, | ||
368 | unsigned long size) | ||
369 | { | ||
370 | struct efi_uga_draw_protocol *uga, *first_uga; | ||
371 | unsigned long nr_ugas; | ||
372 | efi_status_t status; | ||
373 | u32 width, height; | ||
374 | void **uga_handle = NULL; | ||
375 | int i; | ||
376 | |||
377 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
378 | EFI_LOADER_DATA, size, &uga_handle); | ||
379 | if (status != EFI_SUCCESS) | ||
380 | return status; | ||
381 | |||
382 | status = efi_call_phys5(sys_table->boottime->locate_handle, | ||
383 | EFI_LOCATE_BY_PROTOCOL, uga_proto, | ||
384 | NULL, &size, uga_handle); | ||
385 | if (status != EFI_SUCCESS) | ||
386 | goto free_handle; | ||
387 | |||
388 | first_uga = NULL; | ||
389 | |||
390 | nr_ugas = size / sizeof(void *); | ||
391 | for (i = 0; i < nr_ugas; i++) { | ||
392 | efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; | ||
393 | void *handle = uga_handle[i]; | ||
394 | u32 w, h, depth, refresh; | ||
395 | void *pciio; | ||
396 | |||
397 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | ||
398 | handle, uga_proto, &uga); | ||
399 | if (status != EFI_SUCCESS) | ||
400 | continue; | ||
401 | |||
402 | efi_call_phys3(sys_table->boottime->handle_protocol, | ||
403 | handle, &pciio_proto, &pciio); | ||
404 | |||
405 | status = efi_call_phys5(uga->get_mode, uga, &w, &h, | ||
406 | &depth, &refresh); | ||
407 | if (status == EFI_SUCCESS && (!first_uga || pciio)) { | ||
408 | width = w; | ||
409 | height = h; | ||
410 | |||
411 | /* | ||
412 | * Once we've found a UGA supporting PCIIO, | ||
413 | * don't bother looking any further. | ||
414 | */ | ||
415 | if (pciio) | ||
416 | break; | ||
417 | |||
418 | first_uga = uga; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | if (!first_uga) | ||
423 | goto free_handle; | ||
424 | |||
425 | /* EFI framebuffer */ | ||
426 | si->orig_video_isVGA = VIDEO_TYPE_EFI; | ||
427 | |||
428 | si->lfb_depth = 32; | ||
429 | si->lfb_width = width; | ||
430 | si->lfb_height = height; | ||
431 | |||
432 | si->red_size = 8; | ||
433 | si->red_pos = 16; | ||
434 | si->green_size = 8; | ||
435 | si->green_pos = 8; | ||
436 | si->blue_size = 8; | ||
437 | si->blue_pos = 0; | ||
438 | si->rsvd_size = 8; | ||
439 | si->rsvd_pos = 24; | ||
440 | |||
441 | |||
442 | free_handle: | ||
443 | efi_call_phys1(sys_table->boottime->free_pool, uga_handle); | ||
444 | return status; | ||
445 | } | ||
446 | |||
447 | void setup_graphics(struct boot_params *boot_params) | ||
448 | { | ||
449 | efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; | ||
450 | struct screen_info *si; | ||
451 | efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; | ||
452 | efi_status_t status; | ||
453 | unsigned long size; | ||
454 | void **gop_handle = NULL; | ||
455 | void **uga_handle = NULL; | ||
456 | |||
457 | si = &boot_params->screen_info; | ||
458 | memset(si, 0, sizeof(*si)); | ||
459 | |||
460 | size = 0; | ||
461 | status = efi_call_phys5(sys_table->boottime->locate_handle, | ||
462 | EFI_LOCATE_BY_PROTOCOL, &graphics_proto, | ||
463 | NULL, &size, gop_handle); | ||
464 | if (status == EFI_BUFFER_TOO_SMALL) | ||
465 | status = setup_gop(si, &graphics_proto, size); | ||
466 | |||
467 | if (status != EFI_SUCCESS) { | ||
468 | size = 0; | ||
469 | status = efi_call_phys5(sys_table->boottime->locate_handle, | ||
470 | EFI_LOCATE_BY_PROTOCOL, &uga_proto, | ||
471 | NULL, &size, uga_handle); | ||
472 | if (status == EFI_BUFFER_TOO_SMALL) | ||
473 | setup_uga(si, &uga_proto, size); | ||
474 | } | ||
475 | } | ||
476 | |||
477 | struct initrd { | ||
478 | efi_file_handle_t *handle; | ||
479 | u64 size; | ||
480 | }; | ||
481 | |||
482 | /* | ||
483 | * Check the cmdline for a LILO-style initrd= arguments. | ||
484 | * | ||
485 | * We only support loading an initrd from the same filesystem as the | ||
486 | * kernel image. | ||
487 | */ | ||
488 | static efi_status_t handle_ramdisks(efi_loaded_image_t *image, | ||
489 | struct setup_header *hdr) | ||
490 | { | ||
491 | struct initrd *initrds; | ||
492 | unsigned long initrd_addr; | ||
493 | efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; | ||
494 | u64 initrd_total; | ||
495 | efi_file_io_interface_t *io; | ||
496 | efi_file_handle_t *fh; | ||
497 | efi_status_t status; | ||
498 | int nr_initrds; | ||
499 | char *str; | ||
500 | int i, j, k; | ||
501 | |||
502 | initrd_addr = 0; | ||
503 | initrd_total = 0; | ||
504 | |||
505 | str = (char *)(unsigned long)hdr->cmd_line_ptr; | ||
506 | |||
507 | j = 0; /* See close_handles */ | ||
508 | |||
509 | if (!str || !*str) | ||
510 | return EFI_SUCCESS; | ||
511 | |||
512 | for (nr_initrds = 0; *str; nr_initrds++) { | ||
513 | str = strstr(str, "initrd="); | ||
514 | if (!str) | ||
515 | break; | ||
516 | |||
517 | str += 7; | ||
518 | |||
519 | /* Skip any leading slashes */ | ||
520 | while (*str == '/' || *str == '\\') | ||
521 | str++; | ||
522 | |||
523 | while (*str && *str != ' ' && *str != '\n') | ||
524 | str++; | ||
525 | } | ||
526 | |||
527 | if (!nr_initrds) | ||
528 | return EFI_SUCCESS; | ||
529 | |||
530 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
531 | EFI_LOADER_DATA, | ||
532 | nr_initrds * sizeof(*initrds), | ||
533 | &initrds); | ||
534 | if (status != EFI_SUCCESS) | ||
535 | goto fail; | ||
536 | |||
537 | str = (char *)(unsigned long)hdr->cmd_line_ptr; | ||
538 | for (i = 0; i < nr_initrds; i++) { | ||
539 | struct initrd *initrd; | ||
540 | efi_file_handle_t *h; | ||
541 | efi_file_info_t *info; | ||
542 | efi_char16_t filename[256]; | ||
543 | unsigned long info_sz; | ||
544 | efi_guid_t info_guid = EFI_FILE_INFO_ID; | ||
545 | efi_char16_t *p; | ||
546 | u64 file_sz; | ||
547 | |||
548 | str = strstr(str, "initrd="); | ||
549 | if (!str) | ||
550 | break; | ||
551 | |||
552 | str += 7; | ||
553 | |||
554 | initrd = &initrds[i]; | ||
555 | p = filename; | ||
556 | |||
557 | /* Skip any leading slashes */ | ||
558 | while (*str == '/' || *str == '\\') | ||
559 | str++; | ||
560 | |||
561 | while (*str && *str != ' ' && *str != '\n') { | ||
562 | if (p >= filename + sizeof(filename)) | ||
563 | break; | ||
564 | |||
565 | *p++ = *str++; | ||
566 | } | ||
567 | |||
568 | *p = '\0'; | ||
569 | |||
570 | /* Only open the volume once. */ | ||
571 | if (!i) { | ||
572 | efi_boot_services_t *boottime; | ||
573 | |||
574 | boottime = sys_table->boottime; | ||
575 | |||
576 | status = efi_call_phys3(boottime->handle_protocol, | ||
577 | image->device_handle, &fs_proto, &io); | ||
578 | if (status != EFI_SUCCESS) | ||
579 | goto free_initrds; | ||
580 | |||
581 | status = efi_call_phys2(io->open_volume, io, &fh); | ||
582 | if (status != EFI_SUCCESS) | ||
583 | goto free_initrds; | ||
584 | } | ||
585 | |||
586 | status = efi_call_phys5(fh->open, fh, &h, filename, | ||
587 | EFI_FILE_MODE_READ, (u64)0); | ||
588 | if (status != EFI_SUCCESS) | ||
589 | goto close_handles; | ||
590 | |||
591 | initrd->handle = h; | ||
592 | |||
593 | info_sz = 0; | ||
594 | status = efi_call_phys4(h->get_info, h, &info_guid, | ||
595 | &info_sz, NULL); | ||
596 | if (status != EFI_BUFFER_TOO_SMALL) | ||
597 | goto close_handles; | ||
598 | |||
599 | grow: | ||
600 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
601 | EFI_LOADER_DATA, info_sz, &info); | ||
602 | if (status != EFI_SUCCESS) | ||
603 | goto close_handles; | ||
604 | |||
605 | status = efi_call_phys4(h->get_info, h, &info_guid, | ||
606 | &info_sz, info); | ||
607 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
608 | efi_call_phys1(sys_table->boottime->free_pool, info); | ||
609 | goto grow; | ||
610 | } | ||
611 | |||
612 | file_sz = info->file_size; | ||
613 | efi_call_phys1(sys_table->boottime->free_pool, info); | ||
614 | |||
615 | if (status != EFI_SUCCESS) | ||
616 | goto close_handles; | ||
617 | |||
618 | initrd->size = file_sz; | ||
619 | initrd_total += file_sz; | ||
620 | } | ||
621 | |||
622 | if (initrd_total) { | ||
623 | unsigned long addr; | ||
624 | |||
625 | /* | ||
626 | * Multiple initrd's need to be at consecutive | ||
627 | * addresses in memory, so allocate enough memory for | ||
628 | * all the initrd's. | ||
629 | */ | ||
630 | status = high_alloc(initrd_total, 0x1000, | ||
631 | &initrd_addr, hdr->initrd_addr_max); | ||
632 | if (status != EFI_SUCCESS) | ||
633 | goto close_handles; | ||
634 | |||
635 | /* We've run out of free low memory. */ | ||
636 | if (initrd_addr > hdr->initrd_addr_max) { | ||
637 | status = EFI_INVALID_PARAMETER; | ||
638 | goto free_initrd_total; | ||
639 | } | ||
640 | |||
641 | addr = initrd_addr; | ||
642 | for (j = 0; j < nr_initrds; j++) { | ||
643 | u64 size; | ||
644 | |||
645 | size = initrds[j].size; | ||
646 | while (size) { | ||
647 | u64 chunksize; | ||
648 | if (size > EFI_READ_CHUNK_SIZE) | ||
649 | chunksize = EFI_READ_CHUNK_SIZE; | ||
650 | else | ||
651 | chunksize = size; | ||
652 | status = efi_call_phys3(fh->read, | ||
653 | initrds[j].handle, | ||
654 | &chunksize, addr); | ||
655 | if (status != EFI_SUCCESS) | ||
656 | goto free_initrd_total; | ||
657 | addr += chunksize; | ||
658 | size -= chunksize; | ||
659 | } | ||
660 | |||
661 | efi_call_phys1(fh->close, initrds[j].handle); | ||
662 | } | ||
663 | |||
664 | } | ||
665 | |||
666 | efi_call_phys1(sys_table->boottime->free_pool, initrds); | ||
667 | |||
668 | hdr->ramdisk_image = initrd_addr; | ||
669 | hdr->ramdisk_size = initrd_total; | ||
670 | |||
671 | return status; | ||
672 | |||
673 | free_initrd_total: | ||
674 | low_free(initrd_total, initrd_addr); | ||
675 | |||
676 | close_handles: | ||
677 | for (k = j; k < nr_initrds; k++) | ||
678 | efi_call_phys1(fh->close, initrds[k].handle); | ||
679 | free_initrds: | ||
680 | efi_call_phys1(sys_table->boottime->free_pool, initrds); | ||
681 | fail: | ||
682 | hdr->ramdisk_image = 0; | ||
683 | hdr->ramdisk_size = 0; | ||
684 | |||
685 | return status; | ||
686 | } | ||
687 | |||
688 | /* | ||
689 | * Because the x86 boot code expects to be passed a boot_params we | ||
690 | * need to create one ourselves (usually the bootloader would create | ||
691 | * one for us). | ||
692 | */ | ||
693 | static efi_status_t make_boot_params(struct boot_params *boot_params, | ||
694 | efi_loaded_image_t *image, | ||
695 | void *handle) | ||
696 | { | ||
697 | struct efi_info *efi = &boot_params->efi_info; | ||
698 | struct apm_bios_info *bi = &boot_params->apm_bios_info; | ||
699 | struct sys_desc_table *sdt = &boot_params->sys_desc_table; | ||
700 | struct e820entry *e820_map = &boot_params->e820_map[0]; | ||
701 | struct e820entry *prev = NULL; | ||
702 | struct setup_header *hdr = &boot_params->hdr; | ||
703 | unsigned long size, key, desc_size, _size; | ||
704 | efi_memory_desc_t *mem_map; | ||
705 | void *options = image->load_options; | ||
706 | u32 load_options_size = image->load_options_size / 2; /* ASCII */ | ||
707 | int options_size = 0; | ||
708 | efi_status_t status; | ||
709 | __u32 desc_version; | ||
710 | unsigned long cmdline; | ||
711 | u8 nr_entries; | ||
712 | u16 *s2; | ||
713 | u8 *s1; | ||
714 | int i; | ||
715 | |||
716 | hdr->type_of_loader = 0x21; | ||
717 | |||
718 | /* Convert unicode cmdline to ascii */ | ||
719 | cmdline = 0; | ||
720 | s2 = (u16 *)options; | ||
721 | |||
722 | if (s2) { | ||
723 | while (*s2 && *s2 != '\n' && options_size < load_options_size) { | ||
724 | s2++; | ||
725 | options_size++; | ||
726 | } | ||
727 | |||
728 | if (options_size) { | ||
729 | if (options_size > hdr->cmdline_size) | ||
730 | options_size = hdr->cmdline_size; | ||
731 | |||
732 | options_size++; /* NUL termination */ | ||
733 | |||
734 | status = low_alloc(options_size, 1, &cmdline); | ||
735 | if (status != EFI_SUCCESS) | ||
736 | goto fail; | ||
737 | |||
738 | s1 = (u8 *)(unsigned long)cmdline; | ||
739 | s2 = (u16 *)options; | ||
740 | |||
741 | for (i = 0; i < options_size - 1; i++) | ||
742 | *s1++ = *s2++; | ||
743 | |||
744 | *s1 = '\0'; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | hdr->cmd_line_ptr = cmdline; | ||
749 | |||
750 | hdr->ramdisk_image = 0; | ||
751 | hdr->ramdisk_size = 0; | ||
752 | |||
753 | status = handle_ramdisks(image, hdr); | ||
754 | if (status != EFI_SUCCESS) | ||
755 | goto free_cmdline; | ||
756 | |||
757 | setup_graphics(boot_params); | ||
758 | |||
759 | /* Clear APM BIOS info */ | ||
760 | memset(bi, 0, sizeof(*bi)); | ||
761 | |||
762 | memset(sdt, 0, sizeof(*sdt)); | ||
763 | |||
764 | memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); | ||
765 | |||
766 | size = sizeof(*mem_map) * 32; | ||
767 | |||
768 | again: | ||
769 | size += sizeof(*mem_map); | ||
770 | _size = size; | ||
771 | status = low_alloc(size, 1, (unsigned long *)&mem_map); | ||
772 | if (status != EFI_SUCCESS) | ||
773 | goto free_cmdline; | ||
774 | |||
775 | status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, | ||
776 | mem_map, &key, &desc_size, &desc_version); | ||
777 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
778 | low_free(_size, (unsigned long)mem_map); | ||
779 | goto again; | ||
780 | } | ||
781 | |||
782 | if (status != EFI_SUCCESS) | ||
783 | goto free_mem_map; | ||
784 | |||
785 | efi->efi_systab = (unsigned long)sys_table; | ||
786 | efi->efi_memdesc_size = desc_size; | ||
787 | efi->efi_memdesc_version = desc_version; | ||
788 | efi->efi_memmap = (unsigned long)mem_map; | ||
789 | efi->efi_memmap_size = size; | ||
790 | |||
791 | #ifdef CONFIG_X86_64 | ||
792 | efi->efi_systab_hi = (unsigned long)sys_table >> 32; | ||
793 | efi->efi_memmap_hi = (unsigned long)mem_map >> 32; | ||
794 | #endif | ||
795 | |||
796 | /* Might as well exit boot services now */ | ||
797 | status = efi_call_phys2(sys_table->boottime->exit_boot_services, | ||
798 | handle, key); | ||
799 | if (status != EFI_SUCCESS) | ||
800 | goto free_mem_map; | ||
801 | |||
802 | /* Historic? */ | ||
803 | boot_params->alt_mem_k = 32 * 1024; | ||
804 | |||
805 | /* | ||
806 | * Convert the EFI memory map to E820. | ||
807 | */ | ||
808 | nr_entries = 0; | ||
809 | for (i = 0; i < size / desc_size; i++) { | ||
810 | efi_memory_desc_t *d; | ||
811 | unsigned int e820_type = 0; | ||
812 | unsigned long m = (unsigned long)mem_map; | ||
813 | |||
814 | d = (efi_memory_desc_t *)(m + (i * desc_size)); | ||
815 | switch (d->type) { | ||
816 | case EFI_RESERVED_TYPE: | ||
817 | case EFI_RUNTIME_SERVICES_CODE: | ||
818 | case EFI_RUNTIME_SERVICES_DATA: | ||
819 | case EFI_MEMORY_MAPPED_IO: | ||
820 | case EFI_MEMORY_MAPPED_IO_PORT_SPACE: | ||
821 | case EFI_PAL_CODE: | ||
822 | e820_type = E820_RESERVED; | ||
823 | break; | ||
824 | |||
825 | case EFI_UNUSABLE_MEMORY: | ||
826 | e820_type = E820_UNUSABLE; | ||
827 | break; | ||
828 | |||
829 | case EFI_ACPI_RECLAIM_MEMORY: | ||
830 | e820_type = E820_ACPI; | ||
831 | break; | ||
832 | |||
833 | case EFI_LOADER_CODE: | ||
834 | case EFI_LOADER_DATA: | ||
835 | case EFI_BOOT_SERVICES_CODE: | ||
836 | case EFI_BOOT_SERVICES_DATA: | ||
837 | case EFI_CONVENTIONAL_MEMORY: | ||
838 | e820_type = E820_RAM; | ||
839 | break; | ||
840 | |||
841 | case EFI_ACPI_MEMORY_NVS: | ||
842 | e820_type = E820_NVS; | ||
843 | break; | ||
844 | |||
845 | default: | ||
846 | continue; | ||
847 | } | ||
848 | |||
849 | /* Merge adjacent mappings */ | ||
850 | if (prev && prev->type == e820_type && | ||
851 | (prev->addr + prev->size) == d->phys_addr) | ||
852 | prev->size += d->num_pages << 12; | ||
853 | else { | ||
854 | e820_map->addr = d->phys_addr; | ||
855 | e820_map->size = d->num_pages << 12; | ||
856 | e820_map->type = e820_type; | ||
857 | prev = e820_map++; | ||
858 | nr_entries++; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | boot_params->e820_entries = nr_entries; | ||
863 | |||
864 | return EFI_SUCCESS; | ||
865 | |||
866 | free_mem_map: | ||
867 | low_free(_size, (unsigned long)mem_map); | ||
868 | free_cmdline: | ||
869 | if (options_size) | ||
870 | low_free(options_size, hdr->cmd_line_ptr); | ||
871 | fail: | ||
872 | return status; | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * On success we return a pointer to a boot_params structure, and NULL | ||
877 | * on failure. | ||
878 | */ | ||
879 | struct boot_params *efi_main(void *handle, efi_system_table_t *_table) | ||
880 | { | ||
881 | struct boot_params *boot_params; | ||
882 | unsigned long start, nr_pages; | ||
883 | struct desc_ptr *gdt, *idt; | ||
884 | efi_loaded_image_t *image; | ||
885 | struct setup_header *hdr; | ||
886 | efi_status_t status; | ||
887 | efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; | ||
888 | struct desc_struct *desc; | ||
889 | |||
890 | sys_table = _table; | ||
891 | |||
892 | /* Check if we were booted by the EFI firmware */ | ||
893 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | ||
894 | goto fail; | ||
895 | |||
896 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | ||
897 | handle, &proto, (void *)&image); | ||
898 | if (status != EFI_SUCCESS) | ||
899 | goto fail; | ||
900 | |||
901 | status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); | ||
902 | if (status != EFI_SUCCESS) | ||
903 | goto fail; | ||
904 | |||
905 | memset(boot_params, 0x0, 0x4000); | ||
906 | |||
907 | /* Copy first two sectors to boot_params */ | ||
908 | memcpy(boot_params, image->image_base, 1024); | ||
909 | |||
910 | hdr = &boot_params->hdr; | ||
911 | |||
912 | /* | ||
913 | * The EFI firmware loader could have placed the kernel image | ||
914 | * anywhere in memory, but the kernel has various restrictions | ||
915 | * on the max physical address it can run at. Attempt to move | ||
916 | * the kernel to boot_params.pref_address, or as low as | ||
917 | * possible. | ||
918 | */ | ||
919 | start = hdr->pref_address; | ||
920 | nr_pages = round_up(hdr->init_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
921 | |||
922 | status = efi_call_phys4(sys_table->boottime->allocate_pages, | ||
923 | EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, | ||
924 | nr_pages, &start); | ||
925 | if (status != EFI_SUCCESS) { | ||
926 | status = low_alloc(hdr->init_size, hdr->kernel_alignment, | ||
927 | &start); | ||
928 | if (status != EFI_SUCCESS) | ||
929 | goto fail; | ||
930 | } | ||
931 | |||
932 | hdr->code32_start = (__u32)start; | ||
933 | hdr->pref_address = (__u64)(unsigned long)image->image_base; | ||
934 | |||
935 | memcpy((void *)start, image->image_base, image->image_size); | ||
936 | |||
937 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
938 | EFI_LOADER_DATA, sizeof(*gdt), | ||
939 | (void **)&gdt); | ||
940 | if (status != EFI_SUCCESS) | ||
941 | goto fail; | ||
942 | |||
943 | gdt->size = 0x800; | ||
944 | status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address); | ||
945 | if (status != EFI_SUCCESS) | ||
946 | goto fail; | ||
947 | |||
948 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
949 | EFI_LOADER_DATA, sizeof(*idt), | ||
950 | (void **)&idt); | ||
951 | if (status != EFI_SUCCESS) | ||
952 | goto fail; | ||
953 | |||
954 | idt->size = 0; | ||
955 | idt->address = 0; | ||
956 | |||
957 | status = make_boot_params(boot_params, image, handle); | ||
958 | if (status != EFI_SUCCESS) | ||
959 | goto fail; | ||
960 | |||
961 | memset((char *)gdt->address, 0x0, gdt->size); | ||
962 | desc = (struct desc_struct *)gdt->address; | ||
963 | |||
964 | /* The first GDT is a dummy and the second is unused. */ | ||
965 | desc += 2; | ||
966 | |||
967 | desc->limit0 = 0xffff; | ||
968 | desc->base0 = 0x0000; | ||
969 | desc->base1 = 0x0000; | ||
970 | desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ; | ||
971 | desc->s = DESC_TYPE_CODE_DATA; | ||
972 | desc->dpl = 0; | ||
973 | desc->p = 1; | ||
974 | desc->limit = 0xf; | ||
975 | desc->avl = 0; | ||
976 | desc->l = 0; | ||
977 | desc->d = SEG_OP_SIZE_32BIT; | ||
978 | desc->g = SEG_GRANULARITY_4KB; | ||
979 | desc->base2 = 0x00; | ||
980 | |||
981 | desc++; | ||
982 | desc->limit0 = 0xffff; | ||
983 | desc->base0 = 0x0000; | ||
984 | desc->base1 = 0x0000; | ||
985 | desc->type = SEG_TYPE_DATA | SEG_TYPE_READ_WRITE; | ||
986 | desc->s = DESC_TYPE_CODE_DATA; | ||
987 | desc->dpl = 0; | ||
988 | desc->p = 1; | ||
989 | desc->limit = 0xf; | ||
990 | desc->avl = 0; | ||
991 | desc->l = 0; | ||
992 | desc->d = SEG_OP_SIZE_32BIT; | ||
993 | desc->g = SEG_GRANULARITY_4KB; | ||
994 | desc->base2 = 0x00; | ||
995 | |||
996 | #ifdef CONFIG_X86_64 | ||
997 | /* Task segment value */ | ||
998 | desc++; | ||
999 | desc->limit0 = 0x0000; | ||
1000 | desc->base0 = 0x0000; | ||
1001 | desc->base1 = 0x0000; | ||
1002 | desc->type = SEG_TYPE_TSS; | ||
1003 | desc->s = 0; | ||
1004 | desc->dpl = 0; | ||
1005 | desc->p = 1; | ||
1006 | desc->limit = 0x0; | ||
1007 | desc->avl = 0; | ||
1008 | desc->l = 0; | ||
1009 | desc->d = 0; | ||
1010 | desc->g = SEG_GRANULARITY_4KB; | ||
1011 | desc->base2 = 0x00; | ||
1012 | #endif /* CONFIG_X86_64 */ | ||
1013 | |||
1014 | asm volatile ("lidt %0" : : "m" (*idt)); | ||
1015 | asm volatile ("lgdt %0" : : "m" (*gdt)); | ||
1016 | |||
1017 | asm volatile("cli"); | ||
1018 | |||
1019 | return boot_params; | ||
1020 | fail: | ||
1021 | return NULL; | ||
1022 | } | ||
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h new file mode 100644 index 000000000000..39251663e65b --- /dev/null +++ b/arch/x86/boot/compressed/eboot.h | |||
@@ -0,0 +1,61 @@ | |||
1 | #ifndef BOOT_COMPRESSED_EBOOT_H | ||
2 | #define BOOT_COMPRESSED_EBOOT_H | ||
3 | |||
4 | #define SEG_TYPE_DATA (0 << 3) | ||
5 | #define SEG_TYPE_READ_WRITE (1 << 1) | ||
6 | #define SEG_TYPE_CODE (1 << 3) | ||
7 | #define SEG_TYPE_EXEC_READ (1 << 1) | ||
8 | #define SEG_TYPE_TSS ((1 << 3) | (1 << 0)) | ||
9 | #define SEG_OP_SIZE_32BIT (1 << 0) | ||
10 | #define SEG_GRANULARITY_4KB (1 << 0) | ||
11 | |||
12 | #define DESC_TYPE_CODE_DATA (1 << 0) | ||
13 | |||
14 | #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) | ||
15 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) | ||
16 | |||
17 | #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 | ||
18 | #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 | ||
19 | #define PIXEL_BIT_MASK 2 | ||
20 | #define PIXEL_BLT_ONLY 3 | ||
21 | #define PIXEL_FORMAT_MAX 4 | ||
22 | |||
23 | struct efi_pixel_bitmask { | ||
24 | u32 red_mask; | ||
25 | u32 green_mask; | ||
26 | u32 blue_mask; | ||
27 | u32 reserved_mask; | ||
28 | }; | ||
29 | |||
30 | struct efi_graphics_output_mode_info { | ||
31 | u32 version; | ||
32 | u32 horizontal_resolution; | ||
33 | u32 vertical_resolution; | ||
34 | int pixel_format; | ||
35 | struct efi_pixel_bitmask pixel_information; | ||
36 | u32 pixels_per_scan_line; | ||
37 | } __packed; | ||
38 | |||
39 | struct efi_graphics_output_protocol_mode { | ||
40 | u32 max_mode; | ||
41 | u32 mode; | ||
42 | unsigned long info; | ||
43 | unsigned long size_of_info; | ||
44 | u64 frame_buffer_base; | ||
45 | unsigned long frame_buffer_size; | ||
46 | } __packed; | ||
47 | |||
48 | struct efi_graphics_output_protocol { | ||
49 | void *query_mode; | ||
50 | unsigned long set_mode; | ||
51 | unsigned long blt; | ||
52 | struct efi_graphics_output_protocol_mode *mode; | ||
53 | }; | ||
54 | |||
55 | struct efi_uga_draw_protocol { | ||
56 | void *get_mode; | ||
57 | void *set_mode; | ||
58 | void *blt; | ||
59 | }; | ||
60 | |||
61 | #endif /* BOOT_COMPRESSED_EBOOT_H */ | ||
diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S new file mode 100644 index 000000000000..a53440e81d52 --- /dev/null +++ b/arch/x86/boot/compressed/efi_stub_32.S | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * EFI call stub for IA32. | ||
3 | * | ||
4 | * This stub allows us to make EFI calls in physical mode with interrupts | ||
5 | * turned off. Note that this implementation is different from the one in | ||
6 | * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical | ||
7 | * mode at this point. | ||
8 | */ | ||
9 | |||
10 | #include <linux/linkage.h> | ||
11 | #include <asm/page_types.h> | ||
12 | |||
13 | /* | ||
14 | * efi_call_phys(void *, ...) is a function with variable parameters. | ||
15 | * All the callers of this function assure that all the parameters are 4-bytes. | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save. | ||
20 | * So we'd better save all of them at the beginning of this function and restore | ||
21 | * at the end no matter how many we use, because we can not assure EFI runtime | ||
22 | * service functions will comply with gcc calling convention, too. | ||
23 | */ | ||
24 | |||
25 | .text | ||
26 | ENTRY(efi_call_phys) | ||
27 | /* | ||
28 | * 0. The function can only be called in Linux kernel. So CS has been | ||
29 | * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found | ||
30 | * the values of these registers are the same. And, the corresponding | ||
31 | * GDT entries are identical. So I will do nothing about segment reg | ||
32 | * and GDT, but change GDT base register in prelog and epilog. | ||
33 | */ | ||
34 | |||
35 | /* | ||
36 | * 1. Because we haven't been relocated by this point we need to | ||
37 | * use relative addressing. | ||
38 | */ | ||
39 | call 1f | ||
40 | 1: popl %edx | ||
41 | subl $1b, %edx | ||
42 | |||
43 | /* | ||
44 | * 2. Now on the top of stack is the return | ||
45 | * address in the caller of efi_call_phys(), then parameter 1, | ||
46 | * parameter 2, ..., param n. To make things easy, we save the return | ||
47 | * address of efi_call_phys in a global variable. | ||
48 | */ | ||
49 | popl %ecx | ||
50 | movl %ecx, saved_return_addr(%edx) | ||
51 | /* get the function pointer into ECX*/ | ||
52 | popl %ecx | ||
53 | movl %ecx, efi_rt_function_ptr(%edx) | ||
54 | |||
55 | /* | ||
56 | * 3. Call the physical function. | ||
57 | */ | ||
58 | call *%ecx | ||
59 | |||
60 | /* | ||
61 | * 4. Balance the stack. And because EAX contain the return value, | ||
62 | * we'd better not clobber it. We need to calculate our address | ||
63 | * again because %ecx and %edx are not preserved across EFI function | ||
64 | * calls. | ||
65 | */ | ||
66 | call 1f | ||
67 | 1: popl %edx | ||
68 | subl $1b, %edx | ||
69 | |||
70 | movl efi_rt_function_ptr(%edx), %ecx | ||
71 | pushl %ecx | ||
72 | |||
73 | /* | ||
74 | * 10. Push the saved return address onto the stack and return. | ||
75 | */ | ||
76 | movl saved_return_addr(%edx), %ecx | ||
77 | pushl %ecx | ||
78 | ret | ||
79 | ENDPROC(efi_call_phys) | ||
80 | .previous | ||
81 | |||
82 | .data | ||
83 | saved_return_addr: | ||
84 | .long 0 | ||
85 | efi_rt_function_ptr: | ||
86 | .long 0 | ||
diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S new file mode 100644 index 000000000000..cedc60de86eb --- /dev/null +++ b/arch/x86/boot/compressed/efi_stub_64.S | |||
@@ -0,0 +1 @@ | |||
#include "../../platform/efi/efi_stub_64.S" | |||
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index 67a655a39ce4..a0559930a180 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S | |||
@@ -32,6 +32,28 @@ | |||
32 | 32 | ||
33 | __HEAD | 33 | __HEAD |
34 | ENTRY(startup_32) | 34 | ENTRY(startup_32) |
35 | #ifdef CONFIG_EFI_STUB | ||
36 | /* | ||
37 | * We don't need the return address, so set up the stack so | ||
38 | * efi_main() can find its arugments. | ||
39 | */ | ||
40 | add $0x4, %esp | ||
41 | |||
42 | call efi_main | ||
43 | cmpl $0, %eax | ||
44 | je preferred_addr | ||
45 | movl %eax, %esi | ||
46 | call 1f | ||
47 | 1: | ||
48 | popl %eax | ||
49 | subl $1b, %eax | ||
50 | subl BP_pref_address(%esi), %eax | ||
51 | add BP_code32_start(%esi), %eax | ||
52 | leal preferred_addr(%eax), %eax | ||
53 | jmp *%eax | ||
54 | |||
55 | preferred_addr: | ||
56 | #endif | ||
35 | cld | 57 | cld |
36 | /* | 58 | /* |
37 | * Test KEEP_SEGMENTS flag to see if the bootloader is asking | 59 | * Test KEEP_SEGMENTS flag to see if the bootloader is asking |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 35af09d13dc1..558d76ce23bc 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
@@ -199,6 +199,26 @@ ENTRY(startup_64) | |||
199 | * an identity mapped page table being provied that maps our | 199 | * an identity mapped page table being provied that maps our |
200 | * entire text+data+bss and hopefully all of memory. | 200 | * entire text+data+bss and hopefully all of memory. |
201 | */ | 201 | */ |
202 | #ifdef CONFIG_EFI_STUB | ||
203 | pushq %rsi | ||
204 | mov %rcx, %rdi | ||
205 | mov %rdx, %rsi | ||
206 | call efi_main | ||
207 | popq %rsi | ||
208 | cmpq $0,%rax | ||
209 | je preferred_addr | ||
210 | movq %rax,%rsi | ||
211 | call 1f | ||
212 | 1: | ||
213 | popq %rax | ||
214 | subq $1b, %rax | ||
215 | subq BP_pref_address(%rsi), %rax | ||
216 | add BP_code32_start(%esi), %eax | ||
217 | leaq preferred_addr(%rax), %rax | ||
218 | jmp *%rax | ||
219 | |||
220 | preferred_addr: | ||
221 | #endif | ||
202 | 222 | ||
203 | /* Setup data segments. */ | 223 | /* Setup data segments. */ |
204 | xorl %eax, %eax | 224 | xorl %eax, %eax |
diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index 19b3e693cd72..ffb9c5c9d748 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c | |||
@@ -1,2 +1,11 @@ | |||
1 | #include "misc.h" | 1 | #include "misc.h" |
2 | |||
3 | int memcmp(const void *s1, const void *s2, size_t len) | ||
4 | { | ||
5 | u8 diff; | ||
6 | asm("repe; cmpsb; setnz %0" | ||
7 | : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); | ||
8 | return diff; | ||
9 | } | ||
10 | |||
2 | #include "../string.c" | 11 | #include "../string.c" |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index bdb4d458ec8c..f1bbeeb09148 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -45,6 +45,11 @@ SYSSEG = 0x1000 /* historical load address >> 4 */ | |||
45 | 45 | ||
46 | .global bootsect_start | 46 | .global bootsect_start |
47 | bootsect_start: | 47 | bootsect_start: |
48 | #ifdef CONFIG_EFI_STUB | ||
49 | # "MZ", MS-DOS header | ||
50 | .byte 0x4d | ||
51 | .byte 0x5a | ||
52 | #endif | ||
48 | 53 | ||
49 | # Normalize the start address | 54 | # Normalize the start address |
50 | ljmp $BOOTSEG, $start2 | 55 | ljmp $BOOTSEG, $start2 |
@@ -79,6 +84,14 @@ bs_die: | |||
79 | # invoke the BIOS reset code... | 84 | # invoke the BIOS reset code... |
80 | ljmp $0xf000,$0xfff0 | 85 | ljmp $0xf000,$0xfff0 |
81 | 86 | ||
87 | #ifdef CONFIG_EFI_STUB | ||
88 | .org 0x3c | ||
89 | # | ||
90 | # Offset to the PE header. | ||
91 | # | ||
92 | .long pe_header | ||
93 | #endif /* CONFIG_EFI_STUB */ | ||
94 | |||
82 | .section ".bsdata", "a" | 95 | .section ".bsdata", "a" |
83 | bugger_off_msg: | 96 | bugger_off_msg: |
84 | .ascii "Direct booting from floppy is no longer supported.\r\n" | 97 | .ascii "Direct booting from floppy is no longer supported.\r\n" |
@@ -87,6 +100,141 @@ bugger_off_msg: | |||
87 | .ascii "Remove disk and press any key to reboot . . .\r\n" | 100 | .ascii "Remove disk and press any key to reboot . . .\r\n" |
88 | .byte 0 | 101 | .byte 0 |
89 | 102 | ||
103 | #ifdef CONFIG_EFI_STUB | ||
104 | pe_header: | ||
105 | .ascii "PE" | ||
106 | .word 0 | ||
107 | |||
108 | coff_header: | ||
109 | #ifdef CONFIG_X86_32 | ||
110 | .word 0x14c # i386 | ||
111 | #else | ||
112 | .word 0x8664 # x86-64 | ||
113 | #endif | ||
114 | .word 2 # nr_sections | ||
115 | .long 0 # TimeDateStamp | ||
116 | .long 0 # PointerToSymbolTable | ||
117 | .long 1 # NumberOfSymbols | ||
118 | .word section_table - optional_header # SizeOfOptionalHeader | ||
119 | #ifdef CONFIG_X86_32 | ||
120 | .word 0x306 # Characteristics. | ||
121 | # IMAGE_FILE_32BIT_MACHINE | | ||
122 | # IMAGE_FILE_DEBUG_STRIPPED | | ||
123 | # IMAGE_FILE_EXECUTABLE_IMAGE | | ||
124 | # IMAGE_FILE_LINE_NUMS_STRIPPED | ||
125 | #else | ||
126 | .word 0x206 # Characteristics | ||
127 | # IMAGE_FILE_DEBUG_STRIPPED | | ||
128 | # IMAGE_FILE_EXECUTABLE_IMAGE | | ||
129 | # IMAGE_FILE_LINE_NUMS_STRIPPED | ||
130 | #endif | ||
131 | |||
132 | optional_header: | ||
133 | #ifdef CONFIG_X86_32 | ||
134 | .word 0x10b # PE32 format | ||
135 | #else | ||
136 | .word 0x20b # PE32+ format | ||
137 | #endif | ||
138 | .byte 0x02 # MajorLinkerVersion | ||
139 | .byte 0x14 # MinorLinkerVersion | ||
140 | |||
141 | # Filled in by build.c | ||
142 | .long 0 # SizeOfCode | ||
143 | |||
144 | .long 0 # SizeOfInitializedData | ||
145 | .long 0 # SizeOfUninitializedData | ||
146 | |||
147 | # Filled in by build.c | ||
148 | .long 0x0000 # AddressOfEntryPoint | ||
149 | |||
150 | .long 0x0000 # BaseOfCode | ||
151 | #ifdef CONFIG_X86_32 | ||
152 | .long 0 # data | ||
153 | #endif | ||
154 | |||
155 | extra_header_fields: | ||
156 | #ifdef CONFIG_X86_32 | ||
157 | .long 0 # ImageBase | ||
158 | #else | ||
159 | .quad 0 # ImageBase | ||
160 | #endif | ||
161 | .long 0x1000 # SectionAlignment | ||
162 | .long 0x200 # FileAlignment | ||
163 | .word 0 # MajorOperatingSystemVersion | ||
164 | .word 0 # MinorOperatingSystemVersion | ||
165 | .word 0 # MajorImageVersion | ||
166 | .word 0 # MinorImageVersion | ||
167 | .word 0 # MajorSubsystemVersion | ||
168 | .word 0 # MinorSubsystemVersion | ||
169 | .long 0 # Win32VersionValue | ||
170 | |||
171 | # | ||
172 | # The size of the bzImage is written in tools/build.c | ||
173 | # | ||
174 | .long 0 # SizeOfImage | ||
175 | |||
176 | .long 0x200 # SizeOfHeaders | ||
177 | .long 0 # CheckSum | ||
178 | .word 0xa # Subsystem (EFI application) | ||
179 | .word 0 # DllCharacteristics | ||
180 | #ifdef CONFIG_X86_32 | ||
181 | .long 0 # SizeOfStackReserve | ||
182 | .long 0 # SizeOfStackCommit | ||
183 | .long 0 # SizeOfHeapReserve | ||
184 | .long 0 # SizeOfHeapCommit | ||
185 | #else | ||
186 | .quad 0 # SizeOfStackReserve | ||
187 | .quad 0 # SizeOfStackCommit | ||
188 | .quad 0 # SizeOfHeapReserve | ||
189 | .quad 0 # SizeOfHeapCommit | ||
190 | #endif | ||
191 | .long 0 # LoaderFlags | ||
192 | .long 0x1 # NumberOfRvaAndSizes | ||
193 | |||
194 | .quad 0 # ExportTable | ||
195 | .quad 0 # ImportTable | ||
196 | .quad 0 # ResourceTable | ||
197 | .quad 0 # ExceptionTable | ||
198 | .quad 0 # CertificationTable | ||
199 | .quad 0 # BaseRelocationTable | ||
200 | |||
201 | # Section table | ||
202 | section_table: | ||
203 | .ascii ".text" | ||
204 | .byte 0 | ||
205 | .byte 0 | ||
206 | .byte 0 | ||
207 | .long 0 | ||
208 | .long 0x0 # startup_{32,64} | ||
209 | .long 0 # Size of initialized data | ||
210 | # on disk | ||
211 | .long 0x0 # startup_{32,64} | ||
212 | .long 0 # PointerToRelocations | ||
213 | .long 0 # PointerToLineNumbers | ||
214 | .word 0 # NumberOfRelocations | ||
215 | .word 0 # NumberOfLineNumbers | ||
216 | .long 0x60500020 # Characteristics (section flags) | ||
217 | |||
218 | # | ||
219 | # The EFI application loader requires a relocation section | ||
220 | # because EFI applications are relocatable and not having | ||
221 | # this section seems to confuse it. But since we don't need | ||
222 | # the loader to fixup any relocs for us just fill it with a | ||
223 | # single dummy reloc. | ||
224 | # | ||
225 | .ascii ".reloc" | ||
226 | .byte 0 | ||
227 | .byte 0 | ||
228 | .long reloc_end - reloc_start | ||
229 | .long reloc_start | ||
230 | .long reloc_end - reloc_start # SizeOfRawData | ||
231 | .long reloc_start # PointerToRawData | ||
232 | .long 0 # PointerToRelocations | ||
233 | .long 0 # PointerToLineNumbers | ||
234 | .word 0 # NumberOfRelocations | ||
235 | .word 0 # NumberOfLineNumbers | ||
236 | .long 0x42100040 # Characteristics (section flags) | ||
237 | #endif /* CONFIG_EFI_STUB */ | ||
90 | 238 | ||
91 | # Kernel attributes; used by setup. This is part 1 of the | 239 | # Kernel attributes; used by setup. This is part 1 of the |
92 | # header, from the old boot sector. | 240 | # header, from the old boot sector. |
@@ -318,3 +466,13 @@ die: | |||
318 | setup_corrupt: | 466 | setup_corrupt: |
319 | .byte 7 | 467 | .byte 7 |
320 | .string "No setup signature found...\n" | 468 | .string "No setup signature found...\n" |
469 | |||
470 | .data | ||
471 | dummy: .long 0 | ||
472 | |||
473 | .section .reloc | ||
474 | reloc_start: | ||
475 | .long dummy - reloc_start | ||
476 | .long 10 | ||
477 | .word 0 | ||
478 | reloc_end: | ||
diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c index 3cbc4058dd26..574dedfe2890 100644 --- a/arch/x86/boot/string.c +++ b/arch/x86/boot/string.c | |||
@@ -111,3 +111,38 @@ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int bas | |||
111 | 111 | ||
112 | return result; | 112 | return result; |
113 | } | 113 | } |
114 | |||
115 | /** | ||
116 | * strlen - Find the length of a string | ||
117 | * @s: The string to be sized | ||
118 | */ | ||
119 | size_t strlen(const char *s) | ||
120 | { | ||
121 | const char *sc; | ||
122 | |||
123 | for (sc = s; *sc != '\0'; ++sc) | ||
124 | /* nothing */; | ||
125 | return sc - s; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * strstr - Find the first substring in a %NUL terminated string | ||
130 | * @s1: The string to be searched | ||
131 | * @s2: The string to search for | ||
132 | */ | ||
133 | char *strstr(const char *s1, const char *s2) | ||
134 | { | ||
135 | size_t l1, l2; | ||
136 | |||
137 | l2 = strlen(s2); | ||
138 | if (!l2) | ||
139 | return (char *)s1; | ||
140 | l1 = strlen(s1); | ||
141 | while (l1 >= l2) { | ||
142 | l1--; | ||
143 | if (!memcmp(s1, s2, l2)) | ||
144 | return (char *)s1; | ||
145 | s1++; | ||
146 | } | ||
147 | return NULL; | ||
148 | } | ||
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index fdc60a0b3c20..4e9bd6bcafa6 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c | |||
@@ -135,6 +135,9 @@ static void usage(void) | |||
135 | 135 | ||
136 | int main(int argc, char ** argv) | 136 | int main(int argc, char ** argv) |
137 | { | 137 | { |
138 | #ifdef CONFIG_EFI_STUB | ||
139 | unsigned int file_sz, pe_header; | ||
140 | #endif | ||
138 | unsigned int i, sz, setup_sectors; | 141 | unsigned int i, sz, setup_sectors; |
139 | int c; | 142 | int c; |
140 | u32 sys_size; | 143 | u32 sys_size; |
@@ -194,6 +197,42 @@ int main(int argc, char ** argv) | |||
194 | buf[0x1f6] = sys_size >> 16; | 197 | buf[0x1f6] = sys_size >> 16; |
195 | buf[0x1f7] = sys_size >> 24; | 198 | buf[0x1f7] = sys_size >> 24; |
196 | 199 | ||
200 | #ifdef CONFIG_EFI_STUB | ||
201 | file_sz = sz + i + ((sys_size * 16) - sz); | ||
202 | |||
203 | pe_header = *(unsigned int *)&buf[0x3c]; | ||
204 | |||
205 | /* Size of code */ | ||
206 | *(unsigned int *)&buf[pe_header + 0x1c] = file_sz; | ||
207 | |||
208 | /* Size of image */ | ||
209 | *(unsigned int *)&buf[pe_header + 0x50] = file_sz; | ||
210 | |||
211 | #ifdef CONFIG_X86_32 | ||
212 | /* Address of entry point */ | ||
213 | *(unsigned int *)&buf[pe_header + 0x28] = i; | ||
214 | |||
215 | /* .text size */ | ||
216 | *(unsigned int *)&buf[pe_header + 0xb0] = file_sz; | ||
217 | |||
218 | /* .text size of initialised data */ | ||
219 | *(unsigned int *)&buf[pe_header + 0xb8] = file_sz; | ||
220 | #else | ||
221 | /* | ||
222 | * Address of entry point. startup_32 is at the beginning and | ||
223 | * the 64-bit entry point (startup_64) is always 512 bytes | ||
224 | * after. | ||
225 | */ | ||
226 | *(unsigned int *)&buf[pe_header + 0x28] = i + 512; | ||
227 | |||
228 | /* .text size */ | ||
229 | *(unsigned int *)&buf[pe_header + 0xc0] = file_sz; | ||
230 | |||
231 | /* .text size of initialised data */ | ||
232 | *(unsigned int *)&buf[pe_header + 0xc8] = file_sz; | ||
233 | #endif /* CONFIG_X86_32 */ | ||
234 | #endif /* CONFIG_EFI_STUB */ | ||
235 | |||
197 | crc = partial_crc32(buf, i, crc); | 236 | crc = partial_crc32(buf, i, crc); |
198 | if (fwrite(buf, 1, i, stdout) != i) | 237 | if (fwrite(buf, 1, i, stdout) != i) |
199 | die("Writing setup failed"); | 238 | die("Writing setup failed"); |
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index e020d88ec02d..2f90c51cc49d 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h | |||
@@ -64,6 +64,8 @@ struct setup_header { | |||
64 | __u32 payload_offset; | 64 | __u32 payload_offset; |
65 | __u32 payload_length; | 65 | __u32 payload_length; |
66 | __u64 setup_data; | 66 | __u64 setup_data; |
67 | __u64 pref_address; | ||
68 | __u32 init_size; | ||
67 | } __attribute__((packed)); | 69 | } __attribute__((packed)); |
68 | 70 | ||
69 | struct sys_desc_table { | 71 | struct sys_desc_table { |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 7093e4a6a0bc..844f735fd63a 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | #ifdef CONFIG_X86_32 | 4 | #ifdef CONFIG_X86_32 |
5 | 5 | ||
6 | #define EFI_LOADER_SIGNATURE "EL32" | ||
7 | |||
6 | extern unsigned long asmlinkage efi_call_phys(void *, ...); | 8 | extern unsigned long asmlinkage efi_call_phys(void *, ...); |
7 | 9 | ||
8 | #define efi_call_phys0(f) efi_call_phys(f) | 10 | #define efi_call_phys0(f) efi_call_phys(f) |
@@ -37,6 +39,8 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); | |||
37 | 39 | ||
38 | #else /* !CONFIG_X86_32 */ | 40 | #else /* !CONFIG_X86_32 */ |
39 | 41 | ||
42 | #define EFI_LOADER_SIGNATURE "EL64" | ||
43 | |||
40 | extern u64 efi_call0(void *fp); | 44 | extern u64 efi_call0(void *fp); |
41 | extern u64 efi_call1(void *fp, u64 arg1); | 45 | extern u64 efi_call1(void *fp, u64 arg1); |
42 | extern u64 efi_call2(void *fp, u64 arg1, u64 arg2); | 46 | extern u64 efi_call2(void *fp, u64 arg1, u64 arg2); |
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index 4f13fafc5264..68de2dc962ec 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c | |||
@@ -67,4 +67,6 @@ void common(void) { | |||
67 | OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); | 67 | OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); |
68 | OFFSET(BP_version, boot_params, hdr.version); | 68 | OFFSET(BP_version, boot_params, hdr.version); |
69 | OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); | 69 | OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); |
70 | OFFSET(BP_pref_address, boot_params, hdr.pref_address); | ||
71 | OFFSET(BP_code32_start, boot_params, hdr.code32_start); | ||
70 | } | 72 | } |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index d05444ac2aea..d7d5099fe874 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -749,12 +749,7 @@ void __init setup_arch(char **cmdline_p) | |||
749 | #endif | 749 | #endif |
750 | #ifdef CONFIG_EFI | 750 | #ifdef CONFIG_EFI |
751 | if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, | 751 | if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, |
752 | #ifdef CONFIG_X86_32 | 752 | EFI_LOADER_SIGNATURE, 4)) { |
753 | "EL32", | ||
754 | #else | ||
755 | "EL64", | ||
756 | #endif | ||
757 | 4)) { | ||
758 | efi_enabled = 1; | 753 | efi_enabled = 1; |
759 | efi_memblock_x86_reserve_range(); | 754 | efi_memblock_x86_reserve_range(); |
760 | } | 755 | } |