aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot/compressed
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2011-12-12 16:27:52 -0500
committerH. Peter Anvin <hpa@linux.intel.com>2011-12-12 17:26:10 -0500
commit291f36325f9f252bd76ef5f603995f37e453fc60 (patch)
treed2730af48f276882ef3a33f96b8db21f19d593eb /arch/x86/boot/compressed
parent55839d515495e766605d7aaabd9c2758370a8d27 (diff)
x86, efi: EFI boot stub support
There is currently a large divide between kernel development and the development of EFI boot loaders. The idea behind this patch is to give the kernel developers full control over the EFI boot process. As H. Peter Anvin put it, "The 'kernel carries its own stub' approach been very successful in dealing with BIOS, and would make a lot of sense to me for EFI as well." This patch introduces an EFI boot stub that allows an x86 bzImage to be loaded and executed by EFI firmware. The bzImage appears to the firmware as an EFI application. Luckily there are enough free bits within the bzImage header so that it can masquerade as an EFI application, thereby coercing the EFI firmware into loading it and jumping to its entry point. The beauty of this masquerading approach is that both BIOS and EFI boot loaders can still load and run the same bzImage, thereby allowing a single kernel image to work in any boot environment. The EFI boot stub supports multiple initrds, but they must exist on the same partition as the bzImage. Command-line arguments for the kernel can be appended after the bzImage name when run from the EFI shell, e.g. Shell> bzImage console=ttyS0 root=/dev/sdb initrd=initrd.img v7: - Fix checkpatch warnings. v6: - Try to allocate initrd memory just below hdr->inird_addr_max. v5: - load_options_size is UTF-16, which needs dividing by 2 to convert to the corresponding ASCII size. v4: - Don't read more than image->load_options_size v3: - Fix following warnings when compiling CONFIG_EFI_STUB=n arch/x86/boot/tools/build.c: In function ‘main’: arch/x86/boot/tools/build.c:138:24: warning: unused variable ‘pe_header’ arch/x86/boot/tools/build.c:138:15: warning: unused variable ‘file_sz’ - As reported by Matthew Garrett, some Apple machines have GOPs that don't have hardware attached. We need to weed these out by searching for ones that handle the PCIIO protocol. - Don't allocate memory if no initrds are on cmdline - Don't trust image->load_options_size Maarten Lankhorst noted: - Don't strip first argument when booted from efibootmgr - Don't allocate too much memory for cmdline - Don't update cmdline_size, the kernel considers it read-only - Don't accept '\n' for initrd names v2: - File alignment was too large, was 8192 should be 512. Reported by Maarten Lankhorst on LKML. - Added UGA support for graphics - Use VIDEO_TYPE_EFI instead of hard-coded number. - Move linelength assignment until after we've assigned depth - Dynamically fill out AddressOfEntryPoint in tools/build.c - Don't use magic number for GDT/TSS stuff. Requested by Andi Kleen - The bzImage may need to be relocated as it may have been loaded at a high address address by the firmware. This was required to get my macbook booting because the firmware loaded it at 0x7cxxxxxx, which triggers this error in decompress_kernel(), if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff)) error("Destination address too large"); Cc: Mike Waychison <mikew@google.com> Cc: Matthew Garrett <mjg@redhat.com> Tested-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Matt Fleming <matt.fleming@intel.com> Link: http://lkml.kernel.org/r/1321383097.2657.9.camel@mfleming-mobl1.ger.corp.intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/boot/compressed')
-rw-r--r--arch/x86/boot/compressed/Makefile10
-rw-r--r--arch/x86/boot/compressed/eboot.c1014
-rw-r--r--arch/x86/boot/compressed/eboot.h60
-rw-r--r--arch/x86/boot/compressed/efi_stub_32.S86
-rw-r--r--arch/x86/boot/compressed/efi_stub_64.S1
-rw-r--r--arch/x86/boot/compressed/head_32.S22
-rw-r--r--arch/x86/boot/compressed/head_64.S20
-rw-r--r--arch/x86/boot/compressed/string.c9
8 files changed, 1221 insertions, 1 deletions
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
24hostprogs-y := mkpiggy 24hostprogs-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 26VMLINUX_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
30ifeq ($(CONFIG_EFI_STUB), y)
31 VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
32endif
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..4055e63d0b04
--- /dev/null
+++ b/arch/x86/boot/compressed/eboot.c
@@ -0,0 +1,1014 @@
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
17static efi_system_table_t *sys_table;
18
19static 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;
28again:
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
49fail:
50 *map = m;
51 return status;
52}
53
54/*
55 * Allocate at the highest possible address that is not above 'max'.
56 */
57static 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;
72again:
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
125free_pool:
126 efi_call_phys1(sys_table->boottime->free_pool, map);
127
128fail:
129 return status;
130}
131
132/*
133 * Allocate at the lowest possible address.
134 */
135static 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
189free_pool:
190 efi_call_phys1(sys_table->boottime->free_pool, map);
191fail:
192 return status;
193}
194
195static 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
203static 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 */
229static 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
359free_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 */
367static 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
442free_handle:
443 efi_call_phys1(sys_table->boottime->free_pool, uga_handle);
444 return status;
445}
446
447void 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
477struct 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 */
488static 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
599grow:
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 status = efi_call_phys3(fh->read, initrds[j].handle,
647 &size, addr);
648 if (status != EFI_SUCCESS)
649 goto free_initrd_total;
650
651 efi_call_phys1(fh->close, initrds[j].handle);
652
653 addr += size;
654 }
655
656 }
657
658 efi_call_phys1(sys_table->boottime->free_pool, initrds);
659
660 hdr->ramdisk_image = initrd_addr;
661 hdr->ramdisk_size = initrd_total;
662
663 return status;
664
665free_initrd_total:
666 low_free(initrd_total, initrd_addr);
667
668close_handles:
669 for (k = j; k < nr_initrds; k++)
670 efi_call_phys1(fh->close, initrds[k].handle);
671free_initrds:
672 efi_call_phys1(sys_table->boottime->free_pool, initrds);
673fail:
674 hdr->ramdisk_image = 0;
675 hdr->ramdisk_size = 0;
676
677 return status;
678}
679
680/*
681 * Because the x86 boot code expects to be passed a boot_params we
682 * need to create one ourselves (usually the bootloader would create
683 * one for us).
684 */
685static efi_status_t make_boot_params(struct boot_params *boot_params,
686 efi_loaded_image_t *image,
687 void *handle)
688{
689 struct efi_info *efi = &boot_params->efi_info;
690 struct apm_bios_info *bi = &boot_params->apm_bios_info;
691 struct sys_desc_table *sdt = &boot_params->sys_desc_table;
692 struct e820entry *e820_map = &boot_params->e820_map[0];
693 struct e820entry *prev = NULL;
694 struct setup_header *hdr = &boot_params->hdr;
695 unsigned long size, key, desc_size, _size;
696 efi_memory_desc_t *mem_map;
697 void *options = image->load_options;
698 u32 load_options_size = image->load_options_size / 2; /* ASCII */
699 int options_size = 0;
700 efi_status_t status;
701 __u32 desc_version;
702 unsigned long cmdline;
703 u8 nr_entries;
704 u16 *s2;
705 u8 *s1;
706 int i;
707
708 hdr->type_of_loader = 0x21;
709
710 /* Convert unicode cmdline to ascii */
711 cmdline = 0;
712 s2 = (u16 *)options;
713
714 if (s2) {
715 while (*s2 && *s2 != '\n' && options_size < load_options_size) {
716 s2++;
717 options_size++;
718 }
719
720 if (options_size) {
721 if (options_size > hdr->cmdline_size)
722 options_size = hdr->cmdline_size;
723
724 options_size++; /* NUL termination */
725
726 status = low_alloc(options_size, 1, &cmdline);
727 if (status != EFI_SUCCESS)
728 goto fail;
729
730 s1 = (u8 *)(unsigned long)cmdline;
731 s2 = (u16 *)options;
732
733 for (i = 0; i < options_size - 1; i++)
734 *s1++ = *s2++;
735
736 *s1 = '\0';
737 }
738 }
739
740 hdr->cmd_line_ptr = cmdline;
741
742 hdr->ramdisk_image = 0;
743 hdr->ramdisk_size = 0;
744
745 status = handle_ramdisks(image, hdr);
746 if (status != EFI_SUCCESS)
747 goto free_cmdline;
748
749 setup_graphics(boot_params);
750
751 /* Clear APM BIOS info */
752 memset(bi, 0, sizeof(*bi));
753
754 memset(sdt, 0, sizeof(*sdt));
755
756 memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32));
757
758 size = sizeof(*mem_map) * 32;
759
760again:
761 size += sizeof(*mem_map);
762 _size = size;
763 status = low_alloc(size, 1, (unsigned long *)&mem_map);
764 if (status != EFI_SUCCESS)
765 goto free_cmdline;
766
767 status = efi_call_phys5(sys_table->boottime->get_memory_map, &size,
768 mem_map, &key, &desc_size, &desc_version);
769 if (status == EFI_BUFFER_TOO_SMALL) {
770 low_free(_size, (unsigned long)mem_map);
771 goto again;
772 }
773
774 if (status != EFI_SUCCESS)
775 goto free_mem_map;
776
777 efi->efi_systab = (unsigned long)sys_table;
778 efi->efi_memdesc_size = desc_size;
779 efi->efi_memdesc_version = desc_version;
780 efi->efi_memmap = (unsigned long)mem_map;
781 efi->efi_memmap_size = size;
782
783#ifdef CONFIG_X86_64
784 efi->efi_systab_hi = (unsigned long)sys_table >> 32;
785 efi->efi_memmap_hi = (unsigned long)mem_map >> 32;
786#endif
787
788 /* Might as well exit boot services now */
789 status = efi_call_phys2(sys_table->boottime->exit_boot_services,
790 handle, key);
791 if (status != EFI_SUCCESS)
792 goto free_mem_map;
793
794 /* Historic? */
795 boot_params->alt_mem_k = 32 * 1024;
796
797 /*
798 * Convert the EFI memory map to E820.
799 */
800 nr_entries = 0;
801 for (i = 0; i < size / desc_size; i++) {
802 efi_memory_desc_t *d;
803 unsigned int e820_type = 0;
804 unsigned long m = (unsigned long)mem_map;
805
806 d = (efi_memory_desc_t *)(m + (i * desc_size));
807 switch (d->type) {
808 case EFI_RESERVED_TYPE:
809 case EFI_RUNTIME_SERVICES_CODE:
810 case EFI_RUNTIME_SERVICES_DATA:
811 case EFI_MEMORY_MAPPED_IO:
812 case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
813 case EFI_PAL_CODE:
814 e820_type = E820_RESERVED;
815 break;
816
817 case EFI_UNUSABLE_MEMORY:
818 e820_type = E820_UNUSABLE;
819 break;
820
821 case EFI_ACPI_RECLAIM_MEMORY:
822 e820_type = E820_ACPI;
823 break;
824
825 case EFI_LOADER_CODE:
826 case EFI_LOADER_DATA:
827 case EFI_BOOT_SERVICES_CODE:
828 case EFI_BOOT_SERVICES_DATA:
829 case EFI_CONVENTIONAL_MEMORY:
830 e820_type = E820_RAM;
831 break;
832
833 case EFI_ACPI_MEMORY_NVS:
834 e820_type = E820_NVS;
835 break;
836
837 default:
838 continue;
839 }
840
841 /* Merge adjacent mappings */
842 if (prev && prev->type == e820_type &&
843 (prev->addr + prev->size) == d->phys_addr)
844 prev->size += d->num_pages << 12;
845 else {
846 e820_map->addr = d->phys_addr;
847 e820_map->size = d->num_pages << 12;
848 e820_map->type = e820_type;
849 prev = e820_map++;
850 nr_entries++;
851 }
852 }
853
854 boot_params->e820_entries = nr_entries;
855
856 return EFI_SUCCESS;
857
858free_mem_map:
859 low_free(_size, (unsigned long)mem_map);
860free_cmdline:
861 if (options_size)
862 low_free(options_size, hdr->cmd_line_ptr);
863fail:
864 return status;
865}
866
867/*
868 * On success we return a pointer to a boot_params structure, and NULL
869 * on failure.
870 */
871struct boot_params *efi_main(void *handle, efi_system_table_t *_table)
872{
873 struct boot_params *boot_params;
874 unsigned long start, nr_pages;
875 struct desc_ptr *gdt, *idt;
876 efi_loaded_image_t *image;
877 struct setup_header *hdr;
878 efi_status_t status;
879 efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
880 struct desc_struct *desc;
881
882 sys_table = _table;
883
884 /* Check if we were booted by the EFI firmware */
885 if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
886 goto fail;
887
888 status = efi_call_phys3(sys_table->boottime->handle_protocol,
889 handle, &proto, (void *)&image);
890 if (status != EFI_SUCCESS)
891 goto fail;
892
893 status = low_alloc(0x4000, 1, (unsigned long *)&boot_params);
894 if (status != EFI_SUCCESS)
895 goto fail;
896
897 memset(boot_params, 0x0, 0x4000);
898
899 /* Copy first two sectors to boot_params */
900 memcpy(boot_params, image->image_base, 1024);
901
902 hdr = &boot_params->hdr;
903
904 /*
905 * The EFI firmware loader could have placed the kernel image
906 * anywhere in memory, but the kernel has various restrictions
907 * on the max physical address it can run at. Attempt to move
908 * the kernel to boot_params.pref_address, or as low as
909 * possible.
910 */
911 start = hdr->pref_address;
912 nr_pages = round_up(hdr->init_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
913
914 status = efi_call_phys4(sys_table->boottime->allocate_pages,
915 EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
916 nr_pages, &start);
917 if (status != EFI_SUCCESS) {
918 status = low_alloc(hdr->init_size, hdr->kernel_alignment,
919 &start);
920 if (status != EFI_SUCCESS)
921 goto fail;
922 }
923
924 hdr->code32_start = (__u32)start;
925 hdr->pref_address = (__u64)(unsigned long)image->image_base;
926
927 memcpy((void *)start, image->image_base, image->image_size);
928
929 status = efi_call_phys3(sys_table->boottime->allocate_pool,
930 EFI_LOADER_DATA, sizeof(*gdt),
931 (void **)&gdt);
932 if (status != EFI_SUCCESS)
933 goto fail;
934
935 gdt->size = 0x800;
936 status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address);
937 if (status != EFI_SUCCESS)
938 goto fail;
939
940 status = efi_call_phys3(sys_table->boottime->allocate_pool,
941 EFI_LOADER_DATA, sizeof(*idt),
942 (void **)&idt);
943 if (status != EFI_SUCCESS)
944 goto fail;
945
946 idt->size = 0;
947 idt->address = 0;
948
949 status = make_boot_params(boot_params, image, handle);
950 if (status != EFI_SUCCESS)
951 goto fail;
952
953 memset((char *)gdt->address, 0x0, gdt->size);
954 desc = (struct desc_struct *)gdt->address;
955
956 /* The first GDT is a dummy and the second is unused. */
957 desc += 2;
958
959 desc->limit0 = 0xffff;
960 desc->base0 = 0x0000;
961 desc->base1 = 0x0000;
962 desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ;
963 desc->s = DESC_TYPE_CODE_DATA;
964 desc->dpl = 0;
965 desc->p = 1;
966 desc->limit = 0xf;
967 desc->avl = 0;
968 desc->l = 0;
969 desc->d = SEG_OP_SIZE_32BIT;
970 desc->g = SEG_GRANULARITY_4KB;
971 desc->base2 = 0x00;
972
973 desc++;
974 desc->limit0 = 0xffff;
975 desc->base0 = 0x0000;
976 desc->base1 = 0x0000;
977 desc->type = SEG_TYPE_DATA | SEG_TYPE_READ_WRITE;
978 desc->s = DESC_TYPE_CODE_DATA;
979 desc->dpl = 0;
980 desc->p = 1;
981 desc->limit = 0xf;
982 desc->avl = 0;
983 desc->l = 0;
984 desc->d = SEG_OP_SIZE_32BIT;
985 desc->g = SEG_GRANULARITY_4KB;
986 desc->base2 = 0x00;
987
988#ifdef CONFIG_X86_64
989 /* Task segment value */
990 desc++;
991 desc->limit0 = 0x0000;
992 desc->base0 = 0x0000;
993 desc->base1 = 0x0000;
994 desc->type = SEG_TYPE_TSS;
995 desc->s = 0;
996 desc->dpl = 0;
997 desc->p = 1;
998 desc->limit = 0x0;
999 desc->avl = 0;
1000 desc->l = 0;
1001 desc->d = 0;
1002 desc->g = SEG_GRANULARITY_4KB;
1003 desc->base2 = 0x00;
1004#endif /* CONFIG_X86_64 */
1005
1006 asm volatile ("lidt %0" : : "m" (*idt));
1007 asm volatile ("lgdt %0" : : "m" (*gdt));
1008
1009 asm volatile("cli");
1010
1011 return boot_params;
1012fail:
1013 return NULL;
1014}
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
new file mode 100644
index 000000000000..f66d023e91ef
--- /dev/null
+++ b/arch/x86/boot/compressed/eboot.h
@@ -0,0 +1,60 @@
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
16#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0
17#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1
18#define PIXEL_BIT_MASK 2
19#define PIXEL_BLT_ONLY 3
20#define PIXEL_FORMAT_MAX 4
21
22struct efi_pixel_bitmask {
23 u32 red_mask;
24 u32 green_mask;
25 u32 blue_mask;
26 u32 reserved_mask;
27};
28
29struct efi_graphics_output_mode_info {
30 u32 version;
31 u32 horizontal_resolution;
32 u32 vertical_resolution;
33 int pixel_format;
34 struct efi_pixel_bitmask pixel_information;
35 u32 pixels_per_scan_line;
36} __packed;
37
38struct efi_graphics_output_protocol_mode {
39 u32 max_mode;
40 u32 mode;
41 unsigned long info;
42 unsigned long size_of_info;
43 u64 frame_buffer_base;
44 unsigned long frame_buffer_size;
45} __packed;
46
47struct efi_graphics_output_protocol {
48 void *query_mode;
49 unsigned long set_mode;
50 unsigned long blt;
51 struct efi_graphics_output_protocol_mode *mode;
52};
53
54struct efi_uga_draw_protocol {
55 void *get_mode;
56 void *set_mode;
57 void *blt;
58};
59
60#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
26ENTRY(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
401: 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
671: 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
79ENDPROC(efi_call_phys)
80.previous
81
82.data
83saved_return_addr:
84 .long 0
85efi_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
34ENTRY(startup_32) 34ENTRY(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
471:
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
55preferred_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
2121:
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
220preferred_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
3int 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"