Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Matt Fleming and committed by
H. Peter Anvin
291f3632 55839d51

+1462 -1
+7
arch/x86/Kconfig
··· 1478 1478 resultant kernel should continue to boot on existing non-EFI 1479 1479 platforms. 1480 1480 1481 + config EFI_STUB 1482 + bool "EFI stub support" 1483 + depends on EFI 1484 + ---help--- 1485 + This kernel feature allows a bzImage to be loaded directly 1486 + by EFI firmware without the use of a bootloader. 1487 + 1481 1488 config SECCOMP 1482 1489 def_bool y 1483 1490 prompt "Enable seccomp to safely compute untrusted bytecode"
+9 -1
arch/x86/boot/compressed/Makefile
··· 23 23 24 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 35 $(call if_changed,ld) 28 36 @: 29 37
+1014
arch/x86/boot/compressed/eboot.c
··· 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 + 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 + 665 + free_initrd_total: 666 + low_free(initrd_total, initrd_addr); 667 + 668 + close_handles: 669 + for (k = j; k < nr_initrds; k++) 670 + efi_call_phys1(fh->close, initrds[k].handle); 671 + free_initrds: 672 + efi_call_phys1(sys_table->boottime->free_pool, initrds); 673 + fail: 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 + */ 685 + static 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 + 760 + again: 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 + 858 + free_mem_map: 859 + low_free(_size, (unsigned long)mem_map); 860 + free_cmdline: 861 + if (options_size) 862 + low_free(options_size, hdr->cmd_line_ptr); 863 + fail: 864 + return status; 865 + } 866 + 867 + /* 868 + * On success we return a pointer to a boot_params structure, and NULL 869 + * on failure. 870 + */ 871 + struct 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; 1012 + fail: 1013 + return NULL; 1014 + }
+60
arch/x86/boot/compressed/eboot.h
··· 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 + 22 + struct efi_pixel_bitmask { 23 + u32 red_mask; 24 + u32 green_mask; 25 + u32 blue_mask; 26 + u32 reserved_mask; 27 + }; 28 + 29 + struct 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 + 38 + struct 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 + 47 + struct 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 + 54 + struct efi_uga_draw_protocol { 55 + void *get_mode; 56 + void *set_mode; 57 + void *blt; 58 + }; 59 + 60 + #endif /* BOOT_COMPRESSED_EBOOT_H */
+86
arch/x86/boot/compressed/efi_stub_32.S
··· 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
+1
arch/x86/boot/compressed/efi_stub_64.S
··· 1 + #include "../../platform/efi/efi_stub_64.S"
+22
arch/x86/boot/compressed/head_32.S
··· 32 32 33 33 __HEAD 34 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 57 cld 36 58 /* 37 59 * Test KEEP_SEGMENTS flag to see if the bootloader is asking
+20
arch/x86/boot/compressed/head_64.S
··· 199 199 * an identity mapped page table being provied that maps our 200 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 223 /* Setup data segments. */ 204 224 xorl %eax, %eax
+9
arch/x86/boot/compressed/string.c
··· 1 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 11 #include "../string.c"
+158
arch/x86/boot/header.S
··· 45 45 46 46 .global bootsect_start 47 47 bootsect_start: 48 + #ifdef CONFIG_EFI_STUB 49 + # "MZ", MS-DOS header 50 + .byte 0x4d 51 + .byte 0x5a 52 + #endif 48 53 49 54 # Normalize the start address 50 55 ljmp $BOOTSEG, $start2 ··· 84 79 # invoke the BIOS reset code... 85 80 ljmp $0xf000,$0xfff0 86 81 82 + #ifdef CONFIG_EFI_STUB 83 + .org 0x3c 84 + # 85 + # Offset to the PE header. 86 + # 87 + .long pe_header 88 + #endif /* CONFIG_EFI_STUB */ 89 + 87 90 .section ".bsdata", "a" 88 91 bugger_off_msg: 89 92 .ascii "Direct booting from floppy is no longer supported.\r\n" ··· 100 87 .ascii "Remove disk and press any key to reboot . . .\r\n" 101 88 .byte 0 102 89 90 + #ifdef CONFIG_EFI_STUB 91 + pe_header: 92 + .ascii "PE" 93 + .word 0 94 + 95 + coff_header: 96 + #ifdef CONFIG_X86_32 97 + .word 0x14c # i386 98 + #else 99 + .word 0x8664 # x86-64 100 + #endif 101 + .word 2 # nr_sections 102 + .long 0 # TimeDateStamp 103 + .long 0 # PointerToSymbolTable 104 + .long 1 # NumberOfSymbols 105 + .word section_table - optional_header # SizeOfOptionalHeader 106 + #ifdef CONFIG_X86_32 107 + .word 0x306 # Characteristics. 108 + # IMAGE_FILE_32BIT_MACHINE | 109 + # IMAGE_FILE_DEBUG_STRIPPED | 110 + # IMAGE_FILE_EXECUTABLE_IMAGE | 111 + # IMAGE_FILE_LINE_NUMS_STRIPPED 112 + #else 113 + .word 0x206 # Characteristics 114 + # IMAGE_FILE_DEBUG_STRIPPED | 115 + # IMAGE_FILE_EXECUTABLE_IMAGE | 116 + # IMAGE_FILE_LINE_NUMS_STRIPPED 117 + #endif 118 + 119 + optional_header: 120 + #ifdef CONFIG_X86_32 121 + .word 0x10b # PE32 format 122 + #else 123 + .word 0x20b # PE32+ format 124 + #endif 125 + .byte 0x02 # MajorLinkerVersion 126 + .byte 0x14 # MinorLinkerVersion 127 + 128 + # Filled in by build.c 129 + .long 0 # SizeOfCode 130 + 131 + .long 0 # SizeOfInitializedData 132 + .long 0 # SizeOfUninitializedData 133 + 134 + # Filled in by build.c 135 + .long 0x0000 # AddressOfEntryPoint 136 + 137 + .long 0x0000 # BaseOfCode 138 + #ifdef CONFIG_X86_32 139 + .long 0 # data 140 + #endif 141 + 142 + extra_header_fields: 143 + #ifdef CONFIG_X86_32 144 + .long 0 # ImageBase 145 + #else 146 + .quad 0 # ImageBase 147 + #endif 148 + .long 0x1000 # SectionAlignment 149 + .long 0x200 # FileAlignment 150 + .word 0 # MajorOperatingSystemVersion 151 + .word 0 # MinorOperatingSystemVersion 152 + .word 0 # MajorImageVersion 153 + .word 0 # MinorImageVersion 154 + .word 0 # MajorSubsystemVersion 155 + .word 0 # MinorSubsystemVersion 156 + .long 0 # Win32VersionValue 157 + 158 + # 159 + # The size of the bzImage is written in tools/build.c 160 + # 161 + .long 0 # SizeOfImage 162 + 163 + .long 0x200 # SizeOfHeaders 164 + .long 0 # CheckSum 165 + .word 0xa # Subsystem (EFI application) 166 + .word 0 # DllCharacteristics 167 + #ifdef CONFIG_X86_32 168 + .long 0 # SizeOfStackReserve 169 + .long 0 # SizeOfStackCommit 170 + .long 0 # SizeOfHeapReserve 171 + .long 0 # SizeOfHeapCommit 172 + #else 173 + .quad 0 # SizeOfStackReserve 174 + .quad 0 # SizeOfStackCommit 175 + .quad 0 # SizeOfHeapReserve 176 + .quad 0 # SizeOfHeapCommit 177 + #endif 178 + .long 0 # LoaderFlags 179 + .long 0x1 # NumberOfRvaAndSizes 180 + 181 + .quad 0 # ExportTable 182 + .quad 0 # ImportTable 183 + .quad 0 # ResourceTable 184 + .quad 0 # ExceptionTable 185 + .quad 0 # CertificationTable 186 + .quad 0 # BaseRelocationTable 187 + 188 + # Section table 189 + section_table: 190 + .ascii ".text" 191 + .byte 0 192 + .byte 0 193 + .byte 0 194 + .long 0 195 + .long 0x0 # startup_{32,64} 196 + .long 0 # Size of initialized data 197 + # on disk 198 + .long 0x0 # startup_{32,64} 199 + .long 0 # PointerToRelocations 200 + .long 0 # PointerToLineNumbers 201 + .word 0 # NumberOfRelocations 202 + .word 0 # NumberOfLineNumbers 203 + .long 0x60500020 # Characteristics (section flags) 204 + 205 + # 206 + # The EFI application loader requires a relocation section 207 + # because EFI applications are relocatable and not having 208 + # this section seems to confuse it. But since we don't need 209 + # the loader to fixup any relocs for us just fill it with a 210 + # single dummy reloc. 211 + # 212 + .ascii ".reloc" 213 + .byte 0 214 + .byte 0 215 + .long reloc_end - reloc_start 216 + .long reloc_start 217 + .long reloc_end - reloc_start # SizeOfRawData 218 + .long reloc_start # PointerToRawData 219 + .long 0 # PointerToRelocations 220 + .long 0 # PointerToLineNumbers 221 + .word 0 # NumberOfRelocations 222 + .word 0 # NumberOfLineNumbers 223 + .long 0x42100040 # Characteristics (section flags) 224 + #endif /* CONFIG_EFI_STUB */ 103 225 104 226 # Kernel attributes; used by setup. This is part 1 of the 105 227 # header, from the old boot sector. ··· 466 318 setup_corrupt: 467 319 .byte 7 468 320 .string "No setup signature found...\n" 321 + 322 + .data 323 + dummy: .long 0 324 + 325 + .section .reloc 326 + reloc_start: 327 + .long dummy - reloc_start 328 + .long 10 329 + .word 0 330 + reloc_end:
+35
arch/x86/boot/string.c
··· 111 111 112 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 + }
+39
arch/x86/boot/tools/build.c
··· 135 135 136 136 int main(int argc, char ** argv) 137 137 { 138 + #ifdef CONFIG_EFI_STUB 139 + unsigned int file_sz, pe_header; 140 + #endif 138 141 unsigned int i, sz, setup_sectors; 139 142 int c; 140 143 u32 sys_size; ··· 196 193 buf[0x1f5] = sys_size >> 8; 197 194 buf[0x1f6] = sys_size >> 16; 198 195 buf[0x1f7] = sys_size >> 24; 196 + 197 + #ifdef CONFIG_EFI_STUB 198 + file_sz = sz + i + ((sys_size * 16) - sz); 199 + 200 + pe_header = *(unsigned int *)&buf[0x3c]; 201 + 202 + /* Size of code */ 203 + *(unsigned int *)&buf[pe_header + 0x1c] = file_sz; 204 + 205 + /* Size of image */ 206 + *(unsigned int *)&buf[pe_header + 0x50] = file_sz; 207 + 208 + #ifdef CONFIG_X86_32 209 + /* Address of entry point */ 210 + *(unsigned int *)&buf[pe_header + 0x28] = i; 211 + 212 + /* .text size */ 213 + *(unsigned int *)&buf[pe_header + 0xb0] = file_sz; 214 + 215 + /* .text size of initialised data */ 216 + *(unsigned int *)&buf[pe_header + 0xb8] = file_sz; 217 + #else 218 + /* 219 + * Address of entry point. startup_32 is at the beginning and 220 + * the 64-bit entry point (startup_64) is always 512 bytes 221 + * after. 222 + */ 223 + *(unsigned int *)&buf[pe_header + 0x28] = i + 512; 224 + 225 + /* .text size */ 226 + *(unsigned int *)&buf[pe_header + 0xc0] = file_sz; 227 + 228 + /* .text size of initialised data */ 229 + *(unsigned int *)&buf[pe_header + 0xc8] = file_sz; 230 + #endif /* CONFIG_X86_32 */ 231 + #endif /* CONFIG_EFI_STUB */ 199 232 200 233 crc = partial_crc32(buf, i, crc); 201 234 if (fwrite(buf, 1, i, stdout) != i)
+2
arch/x86/kernel/asm-offsets.c
··· 67 67 OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); 68 68 OFFSET(BP_version, boot_params, hdr.version); 69 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 }