diff --git a/pkgs/os-specific/linux/kernel/efi-stub.patch b/pkgs/os-specific/linux/kernel/efi-stub.patch deleted file mode 100644 index 581a9fff27f..00000000000 --- a/pkgs/os-specific/linux/kernel/efi-stub.patch +++ /dev/null @@ -1,1778 +0,0 @@ -diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index 6a47bb2..d40c876 100644 ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -1466,6 +1466,13 @@ config EFI - resultant kernel should continue to boot on existing non-EFI - platforms. - -+config EFI_STUB -+ bool "EFI stub support" -+ depends on EFI -+ ---help--- -+ This kernel feature allows a bzImage to be loaded directly -+ by EFI firmware without the use of a bootloader. -+ - config SECCOMP - def_bool y - prompt "Enable seccomp to safely compute untrusted bytecode" -diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile -index 09664ef..b123b9a 100644 ---- a/arch/x86/boot/compressed/Makefile -+++ b/arch/x86/boot/compressed/Makefile -@@ -23,7 +23,15 @@ LDFLAGS_vmlinux := -T - - hostprogs-y := mkpiggy - --$(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 -+VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ -+ $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ -+ $(obj)/piggy.o -+ -+ifeq ($(CONFIG_EFI_STUB), y) -+ VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o -+endif -+ -+$(obj)/vmlinux: $(VMLINUX_OBJS) FORCE - $(call if_changed,ld) - @: - -diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -new file mode 100644 -index 0000000..c1b494d ---- /dev/null -+++ b/arch/x86/boot/compressed/eboot.c -@@ -0,0 +1,975 @@ -+/* ----------------------------------------------------------------------- -+ * -+ * Copyright 2011 Intel Corporation; author Matt Fleming -+ * -+ * This file is part of the Linux kernel, and is made available under -+ * the terms of the GNU General Public License version 2. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+#include -+#include -+#include -+#include -+ -+#define SEG_TYPE_DATA (0 << 3) -+#define SEG_TYPE_READ_WRITE (1 << 1) -+#define SEG_TYPE_CODE (1 << 3) -+#define SEG_TYPE_EXEC_READ (1 << 1) -+#define SEG_TYPE_TSS ((1 << 3) | (1 << 0)) -+#define SEG_OP_SIZE_32BIT (1 << 0) -+#define SEG_GRANULARITY_4KB (1 << 0) -+ -+#define DESC_TYPE_CODE_DATA (1 << 0) -+ -+#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) -+ -+#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 -+#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 -+#define PIXEL_BIT_MASK 2 -+#define PIXEL_BLT_ONLY 3 -+#define PIXEL_FORMAT_MAX 4 -+ -+typedef struct { -+ u32 red_mask; -+ u32 green_mask; -+ u32 blue_mask; -+ u32 reserved_mask; -+} efi_pixel_bitmask_t; -+ -+typedef struct { -+ u32 version; -+ u32 horizontal_resolution; -+ u32 vertical_resolution; -+ int pixel_format; -+ efi_pixel_bitmask_t pixel_information; -+ u32 pixels_per_scan_line; -+} __attribute__((packed)) efi_graphics_output_mode_information_t; -+ -+typedef struct { -+ u32 max_mode; -+ u32 mode; -+ unsigned long info; -+ unsigned long size_of_info; -+ u64 frame_buffer_base; -+ unsigned long frame_buffer_size; -+} __attribute__((packed)) efi_graphics_output_protocol_mode_t; -+ -+typedef struct { -+ void *query_mode; -+ unsigned long set_mode; -+ unsigned long blt; -+ efi_graphics_output_protocol_mode_t *mode; -+} efi_graphics_output_protocol_t; -+ -+typedef struct { -+ void *get_mode; -+ void *set_mode; -+ void *blt; -+} efi_uga_draw_protocol_t; -+ -+static efi_system_table_t *sys_table; -+ -+static efi_status_t low_alloc(unsigned long size, unsigned long align, -+ unsigned long *addr) -+{ -+ unsigned long map_size, key, desc_size; -+ efi_memory_desc_t *map; -+ efi_status_t status; -+ unsigned long nr_pages; -+ u32 desc_version; -+ int i; -+ -+ nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; -+ -+ map_size = sizeof(*map) * 32; -+ -+again: -+ /* -+ * Add an additional efi_memory_desc_t because we're doing an -+ * allocation which may be in a new descriptor region. -+ */ -+ map_size += sizeof(*map); -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, map_size, (void **)&map); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ status = efi_call_phys5(sys_table->boottime->get_memory_map, &map_size, -+ map, &key, &desc_size, &desc_version); -+ if (status == EFI_BUFFER_TOO_SMALL) { -+ efi_call_phys1(sys_table->boottime->free_pool, map); -+ goto again; -+ } -+ -+ if (status != EFI_SUCCESS) -+ goto free_pool; -+ -+ for (i = 0; i < map_size / desc_size; i++) { -+ efi_memory_desc_t *desc; -+ u64 start, end; -+ -+ desc = (efi_memory_desc_t *)((unsigned long)map + (i * desc_size)); -+ -+ if (desc->type != EFI_CONVENTIONAL_MEMORY) -+ continue; -+ -+ if (desc->num_pages < nr_pages) -+ continue; -+ -+ start = desc->phys_addr; -+ end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); -+ -+ /* -+ * Don't allocate at 0x0. It will confuse code that -+ * checks pointers against NULL. Skip the first 8 -+ * bytes so we start at a nice even number. -+ */ -+ if (start == 0x0) { -+ start += 8; -+ -+ /* Check for tiny memory regions */ -+ if (start >= end) -+ continue; -+ } -+ -+ start = round_up(start, align); -+ if ((start + size) > end) -+ continue; -+ -+ status = efi_call_phys4(sys_table->boottime->allocate_pages, -+ EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, -+ nr_pages, &start); -+ if (status == EFI_SUCCESS) { -+ *addr = start; -+ break; -+ } -+ } -+ -+ if (i == map_size / desc_size) -+ status = EFI_NOT_FOUND; -+ -+free_pool: -+ efi_call_phys1(sys_table->boottime->free_pool, map); -+fail: -+ return status; -+} -+ -+static void low_free(unsigned long size, unsigned long addr) -+{ -+ unsigned long nr_pages; -+ -+ nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; -+ efi_call_phys2(sys_table->boottime->free_pages, addr, size); -+} -+ -+static void find_bits(unsigned long mask, u8 *pos, u8 *size) -+{ -+ u8 first, len; -+ -+ first = 0; -+ len = 0; -+ -+ if (mask) { -+ while (!(mask & 0x1)) { -+ mask = mask >> 1; -+ first++; -+ } -+ -+ while (mask & 0x1) { -+ mask = mask >> 1; -+ len++; -+ } -+ } -+ -+ *pos = first; -+ *size = len; -+} -+ -+/* -+ * See if we have Graphics Output Protocol -+ */ -+static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, -+ unsigned long size) -+{ -+ efi_graphics_output_protocol_t *gop, *first_gop; -+ efi_pixel_bitmask_t pixel_info; -+ unsigned long nr_gops; -+ efi_status_t status; -+ void **gop_handle; -+ u16 width, height; -+ u32 fb_base, fb_size; -+ u32 pixels_per_scan_line; -+ int pixel_format; -+ int i; -+ -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, size, &gop_handle); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ status = efi_call_phys5(sys_table->boottime->locate_handle, -+ EFI_LOCATE_BY_PROTOCOL, proto, -+ NULL, &size, gop_handle); -+ if (status != EFI_SUCCESS) -+ goto free_handle; -+ -+ first_gop = NULL; -+ -+ nr_gops = size / sizeof(void *); -+ for (i = 0; i < nr_gops; i++) { -+ efi_graphics_output_mode_information_t *info; -+ efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; -+ void *pciio; -+ void *h = gop_handle[i]; -+ -+ status = efi_call_phys3(sys_table->boottime->handle_protocol, -+ h, proto, &gop); -+ if (status != EFI_SUCCESS) -+ continue; -+ -+ efi_call_phys3(sys_table->boottime->handle_protocol, -+ h, &pciio_proto, &pciio); -+ -+ status = efi_call_phys4(gop->query_mode, gop, -+ gop->mode->mode, &size, &info); -+ if (status == EFI_SUCCESS && (!first_gop || pciio)) { -+ /* -+ * Apple provide GOPs that are not backed by -+ * real hardware (they're used to handle -+ * multiple displays). The workaround is to -+ * search for a GOP implementing the PCIIO -+ * protocol, and if one isn't found, to just -+ * fallback to the first GOP. -+ */ -+ width = info->horizontal_resolution; -+ height = info->vertical_resolution; -+ fb_base = gop->mode->frame_buffer_base; -+ fb_size = gop->mode->frame_buffer_size; -+ pixel_format = info->pixel_format; -+ pixel_info = info->pixel_information; -+ pixels_per_scan_line = info->pixels_per_scan_line; -+ -+ /* -+ * Once we've found a GOP supporting PCIIO, -+ * don't bother looking any further. -+ */ -+ if (pciio) -+ break; -+ -+ first_gop = gop; -+ } -+ } -+ -+ /* Did we find any GOPs? */ -+ if (!first_gop) -+ goto free_handle; -+ -+ /* EFI framebuffer */ -+ si->orig_video_isVGA = VIDEO_TYPE_EFI; -+ -+ si->lfb_width = width; -+ si->lfb_height = height; -+ si->lfb_base = fb_base; -+ si->lfb_size = fb_size; -+ si->pages = 1; -+ -+ if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { -+ si->lfb_depth = 32; -+ si->lfb_linelength = pixels_per_scan_line * 4; -+ si->red_size = 8; -+ si->red_pos = 0; -+ si->green_size = 8; -+ si->green_pos = 8; -+ si->blue_size = 8; -+ si->blue_pos = 16; -+ si->rsvd_size = 8; -+ si->rsvd_pos = 24; -+ } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { -+ si->lfb_depth = 32; -+ si->lfb_linelength = pixels_per_scan_line * 4; -+ si->red_size = 8; -+ si->red_pos = 16; -+ si->green_size = 8; -+ si->green_pos = 8; -+ si->blue_size = 8; -+ si->blue_pos = 0; -+ si->rsvd_size = 8; -+ si->rsvd_pos = 24; -+ } else if (pixel_format == PIXEL_BIT_MASK) { -+ find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size); -+ find_bits(pixel_info.green_mask, &si->green_pos, -+ &si->green_size); -+ find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size); -+ find_bits(pixel_info.reserved_mask, &si->rsvd_pos, -+ &si->rsvd_size); -+ si->lfb_depth = si->red_size + si->green_size + -+ si->blue_size + si->rsvd_size; -+ si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; -+ } else { -+ si->lfb_depth = 4; -+ si->lfb_linelength = si->lfb_width / 2; -+ si->red_size = 0; -+ si->red_pos = 0; -+ si->green_size = 0; -+ si->green_pos = 0; -+ si->blue_size = 0; -+ si->blue_pos = 0; -+ si->rsvd_size = 0; -+ si->rsvd_pos = 0; -+ } -+ -+free_handle: -+ efi_call_phys1(sys_table->boottime->free_pool, gop_handle); -+ return status; -+} -+ -+/* -+ * See if we have Universal Graphics Adapter (UGA) protocol -+ */ -+static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, -+ unsigned long size) -+{ -+ efi_uga_draw_protocol_t *uga, *first_uga; -+ unsigned long nr_ugas; -+ efi_status_t status; -+ u32 width, height; -+ void **uga_handle = NULL; -+ int i; -+ -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, size, &uga_handle); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ status = efi_call_phys5(sys_table->boottime->locate_handle, -+ EFI_LOCATE_BY_PROTOCOL, uga_proto, -+ NULL, &size, uga_handle); -+ if (status != EFI_SUCCESS) -+ goto free_handle; -+ -+ first_uga = NULL; -+ -+ nr_ugas = size / sizeof(void *); -+ for (i = 0; i < nr_ugas; i++) { -+ efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; -+ void *handle = uga_handle[i]; -+ u32 w, h, depth, refresh; -+ void *pciio; -+ -+ status = efi_call_phys3(sys_table->boottime->handle_protocol, -+ handle, uga_proto, &uga); -+ if (status != EFI_SUCCESS) -+ continue; -+ -+ efi_call_phys3(sys_table->boottime->handle_protocol, -+ handle, &pciio_proto, &pciio); -+ -+ status = efi_call_phys5(uga->get_mode, uga, &w, &h, -+ &depth, &refresh); -+ if (status == EFI_SUCCESS && (!first_uga || pciio)) { -+ width = w; -+ height = h; -+ -+ /* -+ * Once we've found a UGA supporting PCIIO, -+ * don't bother looking any further. -+ */ -+ if (pciio) -+ break; -+ -+ first_uga = uga; -+ } -+ } -+ -+ if (!first_uga) -+ goto free_handle; -+ -+ /* EFI framebuffer */ -+ si->orig_video_isVGA = VIDEO_TYPE_EFI; -+ -+ si->lfb_depth = 32; -+ si->lfb_width = width; -+ si->lfb_height = height; -+ -+ si->red_size = 8; -+ si->red_pos = 16; -+ si->green_size = 8; -+ si->green_pos = 8; -+ si->blue_size = 8; -+ si->blue_pos = 0; -+ si->rsvd_size = 8; -+ si->rsvd_pos = 24; -+ -+ -+free_handle: -+ efi_call_phys1(sys_table->boottime->free_pool, uga_handle); -+ return status; -+} -+ -+void setup_graphics(struct boot_params *boot_params) -+{ -+ efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; -+ struct screen_info *si; -+ efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; -+ efi_status_t status; -+ unsigned long size; -+ void **gop_handle = NULL; -+ void **uga_handle = NULL; -+ -+ si = &boot_params->screen_info; -+ memset(si, 0, sizeof(*si)); -+ -+ size = 0; -+ status = efi_call_phys5(sys_table->boottime->locate_handle, -+ EFI_LOCATE_BY_PROTOCOL, &graphics_proto, -+ NULL, &size, gop_handle); -+ if (status == EFI_BUFFER_TOO_SMALL) -+ status = setup_gop(si, &graphics_proto, size); -+ -+ if (status != EFI_SUCCESS) { -+ size = 0; -+ status = efi_call_phys5(sys_table->boottime->locate_handle, -+ EFI_LOCATE_BY_PROTOCOL, &uga_proto, -+ NULL, &size, uga_handle); -+ if (status == EFI_BUFFER_TOO_SMALL) -+ setup_uga(si, &uga_proto, size); -+ } -+} -+ -+struct initrd { -+ efi_file_handle_t *handle; -+ u64 size; -+}; -+ -+/* -+ * Check the cmdline for a LILO-style initrd= arguments. -+ * -+ * We only support loading an initrd from the same filesystem as the -+ * kernel image. -+ */ -+static efi_status_t handle_ramdisks(efi_loaded_image_t *image, -+ struct setup_header *hdr) -+{ -+ struct initrd *initrds; -+ unsigned long initrd_addr; -+ efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; -+ u64 initrd_total; -+ efi_file_io_interface_t *io; -+ efi_file_handle_t *fh; -+ efi_status_t status; -+ int nr_initrds; -+ char *str; -+ int i, j, k; -+ -+ initrd_addr = 0; -+ initrd_total = 0; -+ -+ str = (char *)(unsigned long)hdr->cmd_line_ptr; -+ -+ j = 0; /* See close_handles */ -+ -+ if (!str || !*str) -+ return EFI_SUCCESS; -+ -+ for (nr_initrds = 0; *str; nr_initrds++) { -+ str = strstr(str, "initrd="); -+ if (!str) -+ break; -+ -+ str += 7; -+ -+ /* Skip any leading slashes */ -+ while (*str == '/' || *str == '\\') -+ str++; -+ -+ while (*str && *str != ' ' && *str != '\n') -+ str++; -+ } -+ -+ if (!nr_initrds) -+ return EFI_SUCCESS; -+ -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, -+ nr_initrds * sizeof(*initrds), -+ &initrds); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ str = (char *)(unsigned long)hdr->cmd_line_ptr; -+ for (i = 0; i < nr_initrds; i++) { -+ struct initrd *initrd; -+ efi_file_handle_t *h; -+ efi_file_info_t *info; -+ efi_char16_t filename[256]; -+ unsigned long info_sz; -+ efi_guid_t info_guid = EFI_FILE_INFO_ID; -+ efi_char16_t *p; -+ u64 file_sz; -+ -+ str = strstr(str, "initrd="); -+ if (!str) -+ break; -+ -+ str += 7; -+ -+ initrd = &initrds[i]; -+ p = filename; -+ -+ /* Skip any leading slashes */ -+ while (*str == '/' || *str == '\\') -+ str++; -+ -+ while (*str && *str != ' ' && *str != '\n') { -+ if (p >= filename + sizeof(filename)) -+ break; -+ -+ *p++ = *str++; -+ } -+ -+ *p = '\0'; -+ -+ /* Only open the volume once. */ -+ if (!i) { -+ efi_boot_services_t *boottime; -+ -+ boottime = sys_table->boottime; -+ -+ status = efi_call_phys3(boottime->handle_protocol, -+ image->device_handle, &fs_proto, &io); -+ if (status != EFI_SUCCESS) -+ goto free_initrds; -+ -+ status = efi_call_phys2(io->open_volume, io, &fh); -+ if (status != EFI_SUCCESS) -+ goto free_initrds; -+ } -+ -+ status = efi_call_phys5(fh->open, fh, &h, filename, -+ EFI_FILE_MODE_READ, (u64)0); -+ if (status != EFI_SUCCESS) -+ goto close_handles; -+ -+ initrd->handle = h; -+ -+ info_sz = 0; -+ status = efi_call_phys4(h->get_info, h, &info_guid, -+ &info_sz, NULL); -+ if (status != EFI_BUFFER_TOO_SMALL) -+ goto close_handles; -+ -+grow: -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, info_sz, &info); -+ if (status != EFI_SUCCESS) -+ goto close_handles; -+ -+ status = efi_call_phys4(h->get_info, h, &info_guid, -+ &info_sz, info); -+ if (status == EFI_BUFFER_TOO_SMALL) { -+ efi_call_phys1(sys_table->boottime->free_pool, info); -+ goto grow; -+ } -+ -+ file_sz = info->file_size; -+ efi_call_phys1(sys_table->boottime->free_pool, info); -+ -+ if (status != EFI_SUCCESS) -+ goto close_handles; -+ -+ initrd->size = file_sz; -+ initrd_total += file_sz; -+ } -+ -+ if (initrd_total) { -+ unsigned long addr; -+ -+ /* -+ * Multiple initrd's need to be at consecutive -+ * addresses in memory, so allocate enough memory for -+ * all the initrd's. -+ */ -+ status = low_alloc(initrd_total, 0x1000, &initrd_addr); -+ if (status != EFI_SUCCESS) -+ goto close_handles; -+ -+ /* We've run out of free low memory. */ -+ if (initrd_addr > hdr->initrd_addr_max) { -+ status = EFI_INVALID_PARAMETER; -+ goto free_initrd_total; -+ } -+ -+ addr = initrd_addr; -+ for (j = 0; j < nr_initrds; j++) { -+ u64 size; -+ -+ size = initrds[j].size; -+ status = efi_call_phys3(fh->read, initrds[j].handle, -+ &size, addr); -+ if (status != EFI_SUCCESS) -+ goto free_initrd_total; -+ -+ efi_call_phys1(fh->close, initrds[j].handle); -+ -+ addr += size; -+ } -+ -+ } -+ -+ efi_call_phys1(sys_table->boottime->free_pool, initrds); -+ -+ hdr->ramdisk_image = initrd_addr; -+ hdr->ramdisk_size = initrd_total; -+ -+ return status; -+ -+free_initrd_total: -+ low_free(initrd_total, initrd_addr); -+ -+close_handles: -+ for (k = j; k < nr_initrds; k++) -+ efi_call_phys1(fh->close, initrds[k].handle); -+free_initrds: -+ efi_call_phys1(sys_table->boottime->free_pool, initrds); -+fail: -+ hdr->ramdisk_image = 0; -+ hdr->ramdisk_size = 0; -+ -+ return status; -+} -+ -+/* -+ * Because the x86 boot code expects to be passed a boot_params we -+ * need to create one ourselves (usually the bootloader would create -+ * one for us). -+ */ -+static efi_status_t make_boot_params(struct boot_params *boot_params, -+ efi_loaded_image_t *image, -+ void *handle) -+{ -+ struct efi_info *efi = &boot_params->efi_info; -+ struct apm_bios_info *bi = &boot_params->apm_bios_info; -+ struct sys_desc_table *sdt = &boot_params->sys_desc_table; -+ struct e820entry *e820_map = &boot_params->e820_map[0]; -+ struct e820entry *prev = NULL; -+ struct setup_header *hdr = &boot_params->hdr; -+ unsigned long size, key, desc_size, _size; -+ efi_memory_desc_t *mem_map; -+ void *options = image->load_options; -+ u32 load_options_size = image->load_options_size; -+ int options_size = 0; -+ efi_status_t status; -+ __u32 desc_version; -+ unsigned long cmdline; -+ u8 nr_entries; -+ u16 *s2; -+ u8 *s1; -+ int i; -+ -+ hdr->type_of_loader = 0x21; -+ -+ /* Convert unicode cmdline to ascii */ -+ cmdline = 0; -+ s2 = (u16 *)options; -+ -+ if (s2) { -+ while (*s2 && *s2 != '\n' && options_size < load_options_size) { -+ s2++; -+ options_size++; -+ } -+ -+ if (options_size) { -+ if (options_size > hdr->cmdline_size) -+ options_size = hdr->cmdline_size; -+ -+ options_size++; /* NUL termination */ -+ -+ status = low_alloc(options_size, 1, &cmdline); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ s1 = (u8 *)(unsigned long)cmdline; -+ s2 = (u16 *)options; -+ -+ for (i = 0; i < options_size - 1; i++) -+ *s1++ = *s2++; -+ -+ *s1 = '\0'; -+ } -+ } -+ -+ hdr->cmd_line_ptr = cmdline; -+ -+ hdr->ramdisk_image = 0; -+ hdr->ramdisk_size = 0; -+ -+ status = handle_ramdisks(image, hdr); -+ if (status != EFI_SUCCESS) -+ goto free_cmdline; -+ -+ setup_graphics(boot_params); -+ -+ /* Clear APM BIOS info */ -+ memset(bi, 0, sizeof(*bi)); -+ -+ memset(sdt, 0, sizeof(*sdt)); -+ -+ memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); -+ -+ size = sizeof(*mem_map) * 32; -+ -+again: -+ size += sizeof(*mem_map); -+ _size = size; -+ status = low_alloc(size, 1, (unsigned long *)&mem_map); -+ if (status != EFI_SUCCESS) -+ goto free_cmdline; -+ -+ status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, -+ mem_map, &key, &desc_size, &desc_version); -+ if (status == EFI_BUFFER_TOO_SMALL) { -+ low_free(_size, (unsigned long)mem_map); -+ goto again; -+ } -+ -+ if (status != EFI_SUCCESS) -+ goto free_mem_map; -+ -+ efi->efi_systab = (unsigned long)sys_table; -+ efi->efi_memdesc_size = desc_size; -+ efi->efi_memdesc_version = desc_version; -+ efi->efi_memmap = (unsigned long)mem_map; -+ efi->efi_memmap_size = size; -+ -+#ifdef CONFIG_X86_64 -+ efi->efi_systab_hi = (unsigned long)sys_table >> 32; -+ efi->efi_memmap_hi = (unsigned long)mem_map >> 32; -+#endif -+ -+ /* Might as well exit boot services now */ -+ status = efi_call_phys2(sys_table->boottime->exit_boot_services, -+ handle, key); -+ if (status != EFI_SUCCESS) -+ goto free_mem_map; -+ -+ /* Historic? */ -+ boot_params->alt_mem_k = 32 * 1024; -+ -+ /* -+ * Convert the EFI memory map to E820. -+ */ -+ nr_entries = 0; -+ for (i = 0; i < size / desc_size; i++) { -+ efi_memory_desc_t *d; -+ unsigned int e820_type = 0; -+ -+ d = (efi_memory_desc_t *)((unsigned long)mem_map + (i * desc_size)); -+ switch(d->type) { -+ case EFI_RESERVED_TYPE: -+ case EFI_RUNTIME_SERVICES_CODE: -+ case EFI_RUNTIME_SERVICES_DATA: -+ case EFI_MEMORY_MAPPED_IO: -+ case EFI_MEMORY_MAPPED_IO_PORT_SPACE: -+ case EFI_PAL_CODE: -+ e820_type = E820_RESERVED; -+ break; -+ -+ case EFI_UNUSABLE_MEMORY: -+ e820_type = E820_UNUSABLE; -+ break; -+ -+ case EFI_ACPI_RECLAIM_MEMORY: -+ e820_type = E820_ACPI; -+ break; -+ -+ case EFI_LOADER_CODE: -+ case EFI_LOADER_DATA: -+ case EFI_BOOT_SERVICES_CODE: -+ case EFI_BOOT_SERVICES_DATA: -+ case EFI_CONVENTIONAL_MEMORY: -+ e820_type = E820_RAM; -+ break; -+ -+ case EFI_ACPI_MEMORY_NVS: -+ e820_type = E820_NVS; -+ break; -+ -+ default: -+ continue; -+ } -+ -+ /* Merge adjacent mappings */ -+ if (prev && prev->type == e820_type && -+ (prev->addr + prev->size) == d->phys_addr) -+ prev->size += d->num_pages << 12; -+ else { -+ e820_map->addr = d->phys_addr; -+ e820_map->size = d->num_pages << 12; -+ e820_map->type = e820_type; -+ prev = e820_map++; -+ nr_entries++; -+ } -+ } -+ -+ boot_params->e820_entries = nr_entries; -+ -+ return EFI_SUCCESS; -+ -+free_mem_map: -+ low_free(_size, (unsigned long)mem_map); -+free_cmdline: -+ if (options_size) -+ low_free(options_size, hdr->cmd_line_ptr); -+fail: -+ return status; -+} -+ -+/* -+ * On success we return a pointer to a boot_params structure, and NULL -+ * on failure. -+ */ -+struct boot_params *efi_main(void *handle, efi_system_table_t *_table) -+{ -+ struct boot_params *boot_params; -+ unsigned long start, nr_pages; -+ struct desc_ptr *gdt, *idt; -+ efi_loaded_image_t *image; -+ struct setup_header *hdr; -+ efi_status_t status; -+ efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; -+ struct desc_struct *desc; -+ -+ sys_table = _table; -+ -+ /* Check if we were booted by the EFI firmware */ -+ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) -+ goto fail; -+ -+ status = efi_call_phys3(sys_table->boottime->handle_protocol, -+ handle, &proto, (void *)&image); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ memset(boot_params, 0x0, 0x4000); -+ -+ /* Copy first two sectors to boot_params */ -+ memcpy(boot_params, image->image_base, 1024); -+ -+ hdr = &boot_params->hdr; -+ -+ /* -+ * The EFI firmware loader could have placed the kernel image -+ * anywhere in memory, but the kernel has various restrictions -+ * on the max physical address it can run at. Attempt to move -+ * the kernel to boot_params.pref_address, or as close as -+ * possible to it. -+ */ -+ start = hdr->pref_address; -+ nr_pages = round_up(hdr->init_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; -+ -+ status = efi_call_phys4(sys_table->boottime->allocate_pages, -+ EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, -+ nr_pages, &start); -+ if (status != EFI_SUCCESS) { -+ status = low_alloc(hdr->init_size, hdr->kernel_alignment, -+ &start); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ } -+ -+ hdr->code32_start = (__u32)start; -+ hdr->pref_address = (__u64)(unsigned long)image->image_base; -+ -+ memcpy((void *)start, image->image_base, image->image_size); -+ -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, sizeof(*gdt), -+ (void **)&gdt); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ gdt->size = 0x800; -+ status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, sizeof(*idt), -+ (void **)&idt); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ idt->size = 0; -+ idt->address = 0; -+ -+ status = make_boot_params(boot_params, image, handle); -+ if (status != EFI_SUCCESS) -+ goto fail; -+ -+ memset((char *)gdt->address, 0x0, gdt->size); -+ desc = (struct desc_struct *)gdt->address; -+ -+ /* The first GDT is a dummy and the second is unused. */ -+ desc += 2; -+ -+ desc->limit0 = 0xffff; -+ desc->base0 = 0x0000; -+ desc->base1 = 0x0000; -+ desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ; -+ desc->s = DESC_TYPE_CODE_DATA; -+ desc->dpl = 0; -+ desc->p = 1; -+ desc->limit = 0xf; -+ desc->avl = 0; -+ desc->l = 0; -+ desc->d = SEG_OP_SIZE_32BIT; -+ desc->g = SEG_GRANULARITY_4KB; -+ desc->base2 = 0x00; -+ -+ desc++; -+ desc->limit0 = 0xffff; -+ desc->base0 = 0x0000; -+ desc->base1 = 0x0000; -+ desc->type = SEG_TYPE_DATA | SEG_TYPE_READ_WRITE; -+ desc->s = DESC_TYPE_CODE_DATA; -+ desc->dpl = 0; -+ desc->p = 1; -+ desc->limit = 0xf; -+ desc->avl = 0; -+ desc->l = 0; -+ desc->d = SEG_OP_SIZE_32BIT; -+ desc->g = SEG_GRANULARITY_4KB; -+ desc->base2 = 0x00; -+ -+#ifdef CONFIG_X86_64 -+ /* Task segment value */ -+ desc++; -+ desc->limit0 = 0x0000; -+ desc->base0 = 0x0000; -+ desc->base1 = 0x0000; -+ desc->type = SEG_TYPE_TSS; -+ desc->s = 0; -+ desc->dpl = 0; -+ desc->p = 1; -+ desc->limit = 0x0; -+ desc->avl = 0; -+ desc->l = 0; -+ desc->d = 0; -+ desc->g = SEG_GRANULARITY_4KB; -+ desc->base2 = 0x00; -+#endif /* CONFIG_X86_64 */ -+ -+ asm volatile ("lidt %0" :: "m" (*idt)); -+ asm volatile ("lgdt %0" :: "m" (*gdt)); -+ -+ asm volatile("cli"); -+ -+ return boot_params; -+fail: -+ return NULL; -+} -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 0000000..5047cd9 ---- /dev/null -+++ b/arch/x86/boot/compressed/efi_stub_32.S -@@ -0,0 +1,87 @@ -+/* -+ * EFI call stub for IA32. -+ * -+ * This stub allows us to make EFI calls in physical mode with interrupts -+ * turned off. Note that this implementation is different from the one in -+ * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical -+ * mode at this point. -+ */ -+ -+#include -+#include -+ -+/* -+ * efi_call_phys(void *, ...) is a function with variable parameters. -+ * All the callers of this function assure that all the parameters are 4-bytes. -+ */ -+ -+/* -+ * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save. -+ * So we'd better save all of them at the beginning of this function and restore -+ * at the end no matter how many we use, because we can not assure EFI runtime -+ * service functions will comply with gcc calling convention, too. -+ */ -+ -+.text -+ENTRY(efi_call_phys) -+ /* -+ * 0. The function can only be called in Linux kernel. So CS has been -+ * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found -+ * the values of these registers are the same. And, the corresponding -+ * GDT entries are identical. So I will do nothing about segment reg -+ * and GDT, but change GDT base register in prelog and epilog. -+ */ -+ -+ /* -+ * 1. Because we haven't been relocated by this point we need to -+ * use relative addressing. -+ */ -+ call 1f -+1: popl %edx -+ subl $1b, %edx -+ -+ /* -+ * 2. Now on the top of stack is the return -+ * address in the caller of efi_call_phys(), then parameter 1, -+ * parameter 2, ..., param n. To make things easy, we save the return -+ * address of efi_call_phys in a global variable. -+ */ -+ popl %ecx -+ movl %ecx, saved_return_addr(%edx) -+ /* get the function pointer into ECX*/ -+ popl %ecx -+ movl %ecx, efi_rt_function_ptr(%edx) -+ -+ /* -+ * 3. Call the physical function. -+ */ -+ call *%ecx -+ -+ /* -+ * 4. Balance the stack. And because EAX contain the return value, -+ * we'd better not clobber it. We need to calculate our address -+ * again because %ecx and %edx are not preserved across EFI function -+ * calls. -+ */ -+ call 1f -+1: popl %edx -+ subl $1b, %edx -+ -+ movl efi_rt_function_ptr(%edx), %ecx -+ pushl %ecx -+ -+ /* -+ * 10. Push the saved return address onto the stack and return. -+ */ -+ movl saved_return_addr(%edx), %ecx -+ pushl %ecx -+ ret -+ENDPROC(efi_call_phys) -+.previous -+ -+.data -+saved_return_addr: -+ .long 0 -+efi_rt_function_ptr: -+ .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 0000000..cedc60d ---- /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 67a655a..a055993 100644 ---- a/arch/x86/boot/compressed/head_32.S -+++ b/arch/x86/boot/compressed/head_32.S -@@ -32,6 +32,28 @@ - - __HEAD - ENTRY(startup_32) -+#ifdef CONFIG_EFI_STUB -+ /* -+ * We don't need the return address, so set up the stack so -+ * efi_main() can find its arugments. -+ */ -+ add $0x4, %esp -+ -+ call efi_main -+ cmpl $0, %eax -+ je preferred_addr -+ movl %eax, %esi -+ call 1f -+1: -+ popl %eax -+ subl $1b, %eax -+ subl BP_pref_address(%esi), %eax -+ add BP_code32_start(%esi), %eax -+ leal preferred_addr(%eax), %eax -+ jmp *%eax -+ -+preferred_addr: -+#endif - cld - /* - * 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 35af09d..558d76c 100644 ---- a/arch/x86/boot/compressed/head_64.S -+++ b/arch/x86/boot/compressed/head_64.S -@@ -199,6 +199,26 @@ ENTRY(startup_64) - * an identity mapped page table being provied that maps our - * entire text+data+bss and hopefully all of memory. - */ -+#ifdef CONFIG_EFI_STUB -+ pushq %rsi -+ mov %rcx, %rdi -+ mov %rdx, %rsi -+ call efi_main -+ popq %rsi -+ cmpq $0,%rax -+ je preferred_addr -+ movq %rax,%rsi -+ call 1f -+1: -+ popq %rax -+ subq $1b, %rax -+ subq BP_pref_address(%rsi), %rax -+ add BP_code32_start(%esi), %eax -+ leaq preferred_addr(%rax), %rax -+ jmp *%rax -+ -+preferred_addr: -+#endif - - /* Setup data segments. */ - xorl %eax, %eax -diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c -index 19b3e69..ffb9c5c 100644 ---- a/arch/x86/boot/compressed/string.c -+++ b/arch/x86/boot/compressed/string.c -@@ -1,2 +1,11 @@ - #include "misc.h" -+ -+int memcmp(const void *s1, const void *s2, size_t len) -+{ -+ u8 diff; -+ asm("repe; cmpsb; setnz %0" -+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); -+ return diff; -+} -+ - #include "../string.c" -diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S -index 93e689f..c4756f6 100644 ---- a/arch/x86/boot/header.S -+++ b/arch/x86/boot/header.S -@@ -45,6 +45,11 @@ SYSSEG = 0x1000 /* historical load address >> 4 */ - - .global bootsect_start - bootsect_start: -+#ifdef CONFIG_EFI_STUB -+ # "MZ", MS-DOS header -+ .byte 0x4d -+ .byte 0x5a -+#endif - - # Normalize the start address - ljmp $BOOTSEG, $start2 -@@ -79,6 +84,14 @@ bs_die: - # invoke the BIOS reset code... - ljmp $0xf000,$0xfff0 - -+#ifdef CONFIG_EFI_STUB -+ .org 0x3c -+ # -+ # Offset to the PE header. -+ # -+ .long pe_header -+#endif /* CONFIG_EFI_STUB */ -+ - .section ".bsdata", "a" - bugger_off_msg: - .ascii "Direct booting from floppy is no longer supported.\r\n" -@@ -87,6 +100,141 @@ bugger_off_msg: - .ascii "Remove disk and press any key to reboot . . .\r\n" - .byte 0 - -+#ifdef CONFIG_EFI_STUB -+pe_header: -+ .ascii "PE" -+ .word 0 -+ -+coff_header: -+#ifdef CONFIG_X86_32 -+ .word 0x14c # i386 -+#else -+ .word 0x8664 # x86-64 -+#endif -+ .word 2 # nr_sections -+ .long 0 # TimeDateStamp -+ .long 0 # PointerToSymbolTable -+ .long 1 # NumberOfSymbols -+ .word section_table - optional_header # SizeOfOptionalHeader -+#ifdef CONFIG_X86_32 -+ .word 0x306 # Characteristics. -+ # IMAGE_FILE_32BIT_MACHINE | -+ # IMAGE_FILE_DEBUG_STRIPPED | -+ # IMAGE_FILE_EXECUTABLE_IMAGE | -+ # IMAGE_FILE_LINE_NUMS_STRIPPED -+#else -+ .word 0x206 # Characteristics -+ # IMAGE_FILE_DEBUG_STRIPPED | -+ # IMAGE_FILE_EXECUTABLE_IMAGE | -+ # IMAGE_FILE_LINE_NUMS_STRIPPED -+#endif -+ -+optional_header: -+#ifdef CONFIG_X86_32 -+ .word 0x10b # PE32 format -+#else -+ .word 0x20b # PE32+ format -+#endif -+ .byte 0x02 # MajorLinkerVersion -+ .byte 0x14 # MinorLinkerVersion -+ -+ # Filled in by build.c -+ .long 0 # SizeOfCode -+ -+ .long 0 # SizeOfInitializedData -+ .long 0 # SizeOfUninitializedData -+ -+ # Filled in by build.c -+ .long 0x0000 # AddressOfEntryPoint -+ -+ .long 0x0000 # BaseOfCode -+#ifdef CONFIG_X86_32 -+ .long 0 # data -+#endif -+ -+extra_header_fields: -+#ifdef CONFIG_X86_32 -+ .long 0 # ImageBase -+#else -+ .quad 0 # ImageBase -+#endif -+ .long 0x1000 # SectionAlignment -+ .long 0x200 # FileAlignment -+ .word 0 # MajorOperatingSystemVersion -+ .word 0 # MinorOperatingSystemVersion -+ .word 0 # MajorImageVersion -+ .word 0 # MinorImageVersion -+ .word 0 # MajorSubsystemVersion -+ .word 0 # MinorSubsystemVersion -+ .long 0 # Win32VersionValue -+ -+ # -+ # The size of the bzImage is written in tools/build.c -+ # -+ .long 0 # SizeOfImage -+ -+ .long 0x200 # SizeOfHeaders -+ .long 0 # CheckSum -+ .word 0xa # Subsystem (EFI application) -+ .word 0 # DllCharacteristics -+#ifdef CONFIG_X86_32 -+ .long 0 # SizeOfStackReserve -+ .long 0 # SizeOfStackCommit -+ .long 0 # SizeOfHeapReserve -+ .long 0 # SizeOfHeapCommit -+#else -+ .quad 0 # SizeOfStackReserve -+ .quad 0 # SizeOfStackCommit -+ .quad 0 # SizeOfHeapReserve -+ .quad 0 # SizeOfHeapCommit -+#endif -+ .long 0 # LoaderFlags -+ .long 0x1 # NumberOfRvaAndSizes -+ -+ .quad 0 # ExportTable -+ .quad 0 # ImportTable -+ .quad 0 # ResourceTable -+ .quad 0 # ExceptionTable -+ .quad 0 # CertificationTable -+ .quad 0 # BaseRelocationTable -+ -+ # Section table -+section_table: -+ .ascii ".text" -+ .byte 0 -+ .byte 0 -+ .byte 0 -+ .long 0 -+ .long 0x0 # startup_{32,64} -+ .long 0 # Size of initialized data -+ # on disk -+ .long 0x0 # startup_{32,64} -+ .long 0 # PointerToRelocations -+ .long 0 # PointerToLineNumbers -+ .word 0 # NumberOfRelocations -+ .word 0 # NumberOfLineNumbers -+ .long 0x60500020 # Characteristics (section flags) -+ -+ # -+ # The EFI application loader requires a relocation section -+ # because EFI applications are relocatable and not having -+ # this section seems to confuse it. But since we don't need -+ # the loader to fixup any relocs for us just fill it with a -+ # single dummy reloc. -+ # -+ .ascii ".reloc" -+ .byte 0 -+ .byte 0 -+ .long reloc_end - reloc_start -+ .long reloc_start -+ .long reloc_end - reloc_start # SizeOfRawData -+ .long reloc_start # PointerToRawData -+ .long 0 # PointerToRelocations -+ .long 0 # PointerToLineNumbers -+ .word 0 # NumberOfRelocations -+ .word 0 # NumberOfLineNumbers -+ .long 0x42100040 # Characteristics (section flags) -+#endif /* CONFIG_EFI_STUB */ - - # Kernel attributes; used by setup. This is part 1 of the - # header, from the old boot sector. -@@ -318,3 +466,13 @@ die: - setup_corrupt: - .byte 7 - .string "No setup signature found...\n" -+ -+ .data -+dummy: .long 0 -+ -+ .section .reloc -+reloc_start: -+ .long dummy - reloc_start -+ .long 10 -+ .word 0 -+reloc_end: -diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c -index 3cbc405..574dedf 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 - - return result; - } -+ -+/** -+ * strlen - Find the length of a string -+ * @s: The string to be sized -+ */ -+size_t strlen(const char *s) -+{ -+ const char *sc; -+ -+ for (sc = s; *sc != '\0'; ++sc) -+ /* nothing */; -+ return sc - s; -+} -+ -+/** -+ * strstr - Find the first substring in a %NUL terminated string -+ * @s1: The string to be searched -+ * @s2: The string to search for -+ */ -+char *strstr(const char *s1, const char *s2) -+{ -+ size_t l1, l2; -+ -+ l2 = strlen(s2); -+ if (!l2) -+ return (char *)s1; -+ l1 = strlen(s1); -+ while (l1 >= l2) { -+ l1--; -+ if (!memcmp(s1, s2, l2)) -+ return (char *)s1; -+ s1++; -+ } -+ return NULL; -+} -diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c -index fdc60a0..4e9bd6b 100644 ---- a/arch/x86/boot/tools/build.c -+++ b/arch/x86/boot/tools/build.c -@@ -135,6 +135,9 @@ static void usage(void) - - int main(int argc, char ** argv) - { -+#ifdef CONFIG_EFI_STUB -+ unsigned int file_sz, pe_header; -+#endif - unsigned int i, sz, setup_sectors; - int c; - u32 sys_size; -@@ -194,6 +197,42 @@ int main(int argc, char ** argv) - buf[0x1f6] = sys_size >> 16; - buf[0x1f7] = sys_size >> 24; - -+#ifdef CONFIG_EFI_STUB -+ file_sz = sz + i + ((sys_size * 16) - sz); -+ -+ pe_header = *(unsigned int *)&buf[0x3c]; -+ -+ /* Size of code */ -+ *(unsigned int *)&buf[pe_header + 0x1c] = file_sz; -+ -+ /* Size of image */ -+ *(unsigned int *)&buf[pe_header + 0x50] = file_sz; -+ -+#ifdef CONFIG_X86_32 -+ /* Address of entry point */ -+ *(unsigned int *)&buf[pe_header + 0x28] = i; -+ -+ /* .text size */ -+ *(unsigned int *)&buf[pe_header + 0xb0] = file_sz; -+ -+ /* .text size of initialised data */ -+ *(unsigned int *)&buf[pe_header + 0xb8] = file_sz; -+#else -+ /* -+ * Address of entry point. startup_32 is at the beginning and -+ * the 64-bit entry point (startup_64) is always 512 bytes -+ * after. -+ */ -+ *(unsigned int *)&buf[pe_header + 0x28] = i + 512; -+ -+ /* .text size */ -+ *(unsigned int *)&buf[pe_header + 0xc0] = file_sz; -+ -+ /* .text size of initialised data */ -+ *(unsigned int *)&buf[pe_header + 0xc8] = file_sz; -+#endif /* CONFIG_X86_32 */ -+#endif /* CONFIG_EFI_STUB */ -+ - crc = partial_crc32(buf, i, crc); - if (fwrite(buf, 1, i, stdout) != i) - die("Writing setup failed"); -diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h -index e020d88..2f90c51 100644 ---- a/arch/x86/include/asm/bootparam.h -+++ b/arch/x86/include/asm/bootparam.h -@@ -64,6 +64,8 @@ struct setup_header { - __u32 payload_offset; - __u32 payload_length; - __u64 setup_data; -+ __u64 pref_address; -+ __u32 init_size; - } __attribute__((packed)); - - struct sys_desc_table { -diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h -index 7093e4a..844f735 100644 ---- a/arch/x86/include/asm/efi.h -+++ b/arch/x86/include/asm/efi.h -@@ -3,6 +3,8 @@ - - #ifdef CONFIG_X86_32 - -+#define EFI_LOADER_SIGNATURE "EL32" -+ - extern unsigned long asmlinkage efi_call_phys(void *, ...); - - #define efi_call_phys0(f) efi_call_phys(f) -@@ -37,6 +39,8 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); - - #else /* !CONFIG_X86_32 */ - -+#define EFI_LOADER_SIGNATURE "EL64" -+ - extern u64 efi_call0(void *fp); - extern u64 efi_call1(void *fp, u64 arg1); - 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 4f13faf..68de2dc 100644 ---- a/arch/x86/kernel/asm-offsets.c -+++ b/arch/x86/kernel/asm-offsets.c -@@ -67,4 +67,6 @@ void common(void) { - OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); - OFFSET(BP_version, boot_params, hdr.version); - OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); -+ OFFSET(BP_pref_address, boot_params, hdr.pref_address); -+ OFFSET(BP_code32_start, boot_params, hdr.code32_start); - } -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index afaf384..eca164b 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -750,12 +750,7 @@ void __init setup_arch(char **cmdline_p) - #endif - #ifdef CONFIG_EFI - if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, --#ifdef CONFIG_X86_32 -- "EL32", --#else -- "EL64", --#endif -- 4)) { -+ EFI_LOADER_SIGNATURE, 4)) { - efi_enabled = 1; - efi_memblock_x86_reserve_range(); - } -diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c -index 5cab48e..1156e9a 100644 ---- a/arch/x86/platform/efi/efi_32.c -+++ b/arch/x86/platform/efi/efi_32.c -@@ -44,8 +44,12 @@ void efi_call_phys_prelog(void) - { - unsigned long cr4; - unsigned long temp; -+ unsigned long phys_addr, virt_addr; - struct desc_ptr gdt_descr; - -+ virt_addr = (unsigned long)_text; -+ phys_addr = virt_addr - PAGE_OFFSET; -+ - local_irq_save(efi_rt_eflags); - - /* -@@ -57,18 +61,18 @@ void efi_call_phys_prelog(void) - - if (cr4 & X86_CR4_PAE) { - efi_bak_pg_dir_pointer[0].pgd = -- swapper_pg_dir[pgd_index(0)].pgd; -- swapper_pg_dir[0].pgd = -- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; -+ swapper_pg_dir[pgd_index(phys_addr)].pgd; -+ swapper_pg_dir[pgd_index(phys_addr)].pgd = -+ swapper_pg_dir[pgd_index(virt_addr)].pgd; - } else { - efi_bak_pg_dir_pointer[0].pgd = -- swapper_pg_dir[pgd_index(0)].pgd; -+ swapper_pg_dir[pgd_index(phys_addr)].pgd; - efi_bak_pg_dir_pointer[1].pgd = -- swapper_pg_dir[pgd_index(0x400000)].pgd; -- swapper_pg_dir[pgd_index(0)].pgd = -- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; -- temp = PAGE_OFFSET + 0x400000; -- swapper_pg_dir[pgd_index(0x400000)].pgd = -+ swapper_pg_dir[pgd_index(phys_addr + 0x400000)].pgd; -+ swapper_pg_dir[pgd_index(phys_addr)].pgd = -+ swapper_pg_dir[pgd_index(virt_addr)].pgd; -+ temp = virt_addr + 0x400000; -+ swapper_pg_dir[pgd_index(phys_addr + 0x400000)].pgd = - swapper_pg_dir[pgd_index(temp)].pgd; - } - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 2362a0b..37c3007 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -109,6 +109,14 @@ typedef struct { - u32 imagesize; - } efi_capsule_header_t; - -+/* -+ * Allocation types for calls to boottime->allocate_pages. -+ */ -+#define EFI_ALLOCATE_ANY_PAGES 0 -+#define EFI_ALLOCATE_MAX_ADDRESS 1 -+#define EFI_ALLOCATE_ADDRESS 2 -+#define EFI_MAX_ALLOCATE_TYPE 3 -+ - typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); - - /* -@@ -139,6 +147,57 @@ typedef struct { - } efi_time_cap_t; - - /* -+ * EFI Boot Services table -+ */ -+typedef struct { -+ efi_table_hdr_t hdr; -+ void *raise_tpl; -+ void *restore_tpl; -+ void *allocate_pages; -+ void *free_pages; -+ void *get_memory_map; -+ void *allocate_pool; -+ void *free_pool; -+ void *create_event; -+ void *set_timer; -+ void *wait_for_event; -+ void *signal_event; -+ void *close_event; -+ void *check_event; -+ void *install_protocol_interface; -+ void *reinstall_protocol_interface; -+ void *uninstall_protocol_interface; -+ void *handle_protocol; -+ void *__reserved; -+ void *register_protocol_notify; -+ void *locate_handle; -+ void *locate_device_path; -+ void *install_configuration_table; -+ void *load_image; -+ void *start_image; -+ void *exit; -+ void *unload_image; -+ void *exit_boot_services; -+ void *get_next_monotonic_count; -+ void *stall; -+ void *set_watchdog_timer; -+ void *connect_controller; -+ void *disconnect_controller; -+ void *open_protocol; -+ void *close_protocol; -+ void *open_protocol_information; -+ void *protocols_per_handle; -+ void *locate_handle_buffer; -+ void *locate_protocol; -+ void *install_multiple_protocol_interfaces; -+ void *uninstall_multiple_protocol_interfaces; -+ void *calculate_crc32; -+ void *copy_mem; -+ void *set_mem; -+ void *create_event_ex; -+} efi_boot_services_t; -+ -+/* - * Types and defines for EFI ResetSystem - */ - #define EFI_RESET_COLD 0 -@@ -236,6 +295,24 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, - #define LINUX_EFI_CRASH_GUID \ - EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 ) - -+#define LOADED_IMAGE_PROTOCOL_GUID \ -+ EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) -+ -+#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ -+ EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a ) -+ -+#define EFI_UGA_PROTOCOL_GUID \ -+ EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 ) -+ -+#define EFI_PCI_IO_PROTOCOL_GUID \ -+ EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a ) -+ -+#define EFI_FILE_INFO_ID \ -+ EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) -+ -+#define EFI_FILE_SYSTEM_GUID \ -+ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) -+ - typedef struct { - efi_guid_t guid; - unsigned long table; -@@ -261,7 +338,7 @@ typedef struct { - unsigned long stderr_handle; - unsigned long stderr; - efi_runtime_services_t *runtime; -- unsigned long boottime; -+ efi_boot_services_t *boottime; - unsigned long nr_tables; - unsigned long tables; - } efi_system_table_t; -@@ -275,6 +352,56 @@ struct efi_memory_map { - unsigned long desc_size; - }; - -+typedef struct { -+ u32 revision; -+ void *parent_handle; -+ efi_system_table_t *system_table; -+ void *device_handle; -+ void *file_path; -+ void *reserved; -+ u32 load_options_size; -+ void *load_options; -+ void *image_base; -+ __aligned_u64 image_size; -+ unsigned int image_code_type; -+ unsigned int image_data_type; -+ unsigned long unload; -+} efi_loaded_image_t; -+ -+typedef struct { -+ u64 revision; -+ void *open_volume; -+} efi_file_io_interface_t; -+ -+typedef struct { -+ u64 size; -+ u64 file_size; -+ u64 phys_size; -+ efi_time_t create_time; -+ efi_time_t last_access_time; -+ efi_time_t modification_time; -+ __aligned_u64 attribute; -+ efi_char16_t filename[1]; -+} efi_file_info_t; -+ -+typedef struct { -+ u64 revision; -+ void *open; -+ void *close; -+ void *delete; -+ void *read; -+ void *write; -+ void *get_position; -+ void *set_position; -+ void *get_info; -+ void *set_info; -+ void *flush; -+} efi_file_handle_t; -+ -+#define EFI_FILE_MODE_READ 0x0000000000000001 -+#define EFI_FILE_MODE_WRITE 0x0000000000000002 -+#define EFI_FILE_MODE_CREATE 0x8000000000000000 -+ - #define EFI_INVALID_TABLE_ADDR (~0UL) - - /* -@@ -385,6 +512,13 @@ extern int __init efi_setup_pcdp_console(char *); - #define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 - - /* -+ * The type of search to perform when calling boottime->locate_handle -+ */ -+#define EFI_LOCATE_ALL_HANDLES 0 -+#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 -+#define EFI_LOCATE_BY_PROTOCOL 2 -+ -+/* - * EFI Device Path information - */ - #define EFI_DEV_HW 0x01 diff --git a/pkgs/os-specific/linux/kernel/patches.nix b/pkgs/os-specific/linux/kernel/patches.nix index 585a8c0340b..672464e8965 100644 --- a/pkgs/os-specific/linux/kernel/patches.nix +++ b/pkgs/os-specific/linux/kernel/patches.nix @@ -415,13 +415,4 @@ rec { name = "glibc-getline"; patch = ./getline.patch; }; - - efi_stub = - { - # Patch to enable making the kernel a bootable efi image to avoid - # needing a bootloader on efi systems - # From the x86/efi-stub branch of git://github.com/mfleming/linux-2.6.git - name = "efi-stub"; - patch = ./efi-stub.patch; - }; } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index fce97d6030b..1bf59e4e34f 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -5595,7 +5595,6 @@ let kernelPatches = [ #kernelPatches.fbcondecor_2_6_38 kernelPatches.sec_perm_2_6_24 - kernelPatches.efi_stub #kernelPatches.aufs2_1_2_6_38 #kernelPatches.mips_restart_2_6_36 ];