linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Matt Fleming <matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
To: linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: "H. Peter Anvin" <hpa-YMNOUZJC4hwAvxtiuMwx3w@public.gmane.org>,
	Borislav Petkov <bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org>,
	Alan Cox <alan-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>,
	Matthew Garrett <mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>,
	Matt Fleming
	<matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Subject: [RFC][PATCH 08/11] x86/efi: Split the boot stub into 32/64 code paths
Date: Wed, 29 Jan 2014 16:23:54 +0000	[thread overview]
Message-ID: <1391012637-4839-9-git-send-email-matt@console-pimps.org> (raw)
In-Reply-To: <1391012637-4839-1-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>

From: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Make the decision which code path to take at runtime based on
efi_early->is64.

Signed-off-by: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 arch/x86/boot/compressed/eboot.c | 398 +++++++++++++++++++++++++++++++--------
 1 file changed, 323 insertions(+), 75 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 9eff6cd473b7..4e428380bd56 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -75,10 +75,10 @@ static void efi_printk(efi_system_table_t *, char *);
 static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 static efi_status_t
-efi_file_size(efi_system_table_t *sys_table, void *__fh,
-	      efi_char16_t *filename_16, void **handle, u64 *file_sz)
+__file_size32(void *__fh, efi_char16_t *filename_16,
+	      void **handle, u64 *file_sz)
 {
-	efi_file_handle_t *h, *fh = __fh;
+	efi_file_handle_32_t *h, *fh = __fh;
 	efi_file_info_t *info;
 	efi_status_t status;
 	efi_guid_t info_guid = EFI_FILE_INFO_ID;
@@ -127,30 +127,134 @@ grow:
 	return status;
 }
 
+static efi_status_t
+__file_size64(void *__fh, efi_char16_t *filename_16,
+	      void **handle, u64 *file_sz)
+{
+	efi_file_handle_64_t *h, *fh = __fh;
+	efi_file_info_t *info;
+	efi_status_t status;
+	efi_guid_t info_guid = EFI_FILE_INFO_ID;
+	u32 info_sz;
+
+	status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
+				 EFI_FILE_MODE_READ, (u64)0);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table, "Failed to open file: ");
+		efi_char16_printk(sys_table, filename_16);
+		efi_printk(sys_table, "\n");
+		return status;
+	}
+
+	*handle = h;
+
+	info_sz = 0;
+	status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
+				 &info_sz, NULL);
+	if (status != EFI_BUFFER_TOO_SMALL) {
+		efi_printk(sys_table, "Failed to get file info size\n");
+		return status;
+	}
+
+grow:
+	status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
+				 info_sz, (void **)&info);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table, "Failed to alloc mem for file info\n");
+		return status;
+	}
+
+	status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
+				 &info_sz, info);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		efi_early->call(efi_early->free_pool, info);
+		return status;
+	}
+
+	*file_sz = info->file_size;
+	efi_early->call(efi_early->free_pool, info);
+
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table, "Failed to get initrd info\n");
+
+	return status;
+}
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table, void *__fh,
+	      efi_char16_t *filename_16, void **handle, u64 *file_sz)
+{
+	if (efi_early->is64)
+		return __file_size64(__fh, filename_16, handle, file_sz);
+
+	return __file_size32(__fh, filename_16, handle, file_sz);
+}
+
 static inline efi_status_t
 efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
 {
-	efi_file_handle_t *fh = __fh;
-	return efi_early->call((unsigned long)fh->read, fh, handle, size, addr);
+	unsigned long func;
+
+	if (efi_early->is64) {
+		efi_file_handle_64_t *fh = __fh;
+
+		func = (unsigned long)fh->read;
+		return efi_early->call(func, fh, handle, size, addr);
+	} else {
+		efi_file_handle_32_t *fh = __fh;
+
+		func = (unsigned long)fh->read;
+		return efi_early->call(func, fh, handle, size, addr);
+	}
 }
 
 static inline efi_status_t efi_file_close(void *__fh, void *handle)
 {
-	efi_file_handle_t *fh = __fh;
+	if (efi_early->is64) {
+		efi_file_handle_64_t *fh = __fh;
+
+		return efi_early->call((unsigned long)fh->close, handle);
+	} else {
+		efi_file_handle_32_t *fh = __fh;
 
-	return efi_early->call((unsigned long)fh->close, handle);
+		return efi_early->call((unsigned long)fh->close, handle);
+	}
 }
 
-static inline efi_status_t
-efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
+static inline efi_status_t __open_volume32(void *__image, void **__fh)
+{
+	efi_file_io_interface_t *io;
+	efi_loaded_image_32_t *image = __image;
+	efi_file_handle_32_t *fh;
+	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+	efi_status_t status;
+	void *handle = (void *)(unsigned long)image->device_handle;
+	unsigned long func;
+
+	status = efi_early->call(efi_early->handle_protocol, handle,
+				 &fs_proto, (void **)&io);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table, "Failed to handle fs_proto\n");
+		return status;
+	}
+
+	func = (unsigned long)io->open_volume;
+	status = efi_early->call(func, io, &fh);
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table, "Failed to open volume\n");
+
+	*__fh = fh;
+	return status;
+}
+
+static inline efi_status_t __open_volume64(void *__image, void **__fh)
 {
 	efi_file_io_interface_t *io;
-	efi_loaded_image_t *image = __image;
-	efi_file_handle_t *fh;
+	efi_loaded_image_64_t *image = __image;
+	efi_file_handle_64_t *fh;
 	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
 	efi_status_t status;
 	void *handle = (void *)(unsigned long)image->device_handle;
-	u32 func;
+	unsigned long func;
 
 	status = efi_early->call(efi_early->handle_protocol, handle,
 				 &fs_proto, (void **)&io);
@@ -168,19 +272,39 @@ efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
 	return status;
 }
 
-static inline void
-efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
+static inline efi_status_t
+efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
+{
+	if (efi_early->is64)
+		return __open_volume64(__image, __fh);
+
+	return __open_volume32(__image, __fh);
+}
+
+static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
 {
-	struct efi_simple_text_output_protocol *out;
 	unsigned long output_string;
 	size_t offset;
-	unsigned long *func;
 
-	offset = offsetof(typeof(*out), output_string);
-	output_string = efi_early->text_output + offset;
-	func = (unsigned long *)output_string;
+	if (efi_early->is64) {
+		struct efi_simple_text_output_protocol_64 *out;
+		u64 *func;
+
+		offset = offsetof(typeof(*out), output_string);
+		output_string = efi_early->text_output + offset;
+		func = (u64 *)output_string;
 
-	efi_early->call(*func, efi_early->text_output, str);
+		efi_early->call(*func, efi_early->text_output, str);
+	} else {
+		struct efi_simple_text_output_protocol_32 *out;
+		u32 *func;
+
+		offset = offsetof(typeof(*out), output_string);
+		output_string = efi_early->text_output + offset;
+		func = (u32 *)output_string;
+
+		efi_early->call(*func, efi_early->text_output, str);
+	}
 }
 
 #include "../../../../drivers/firmware/efi/efi-stub-helper.c"
@@ -208,6 +332,127 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
 	*size = len;
 }
 
+static efi_status_t
+__setup_efi_pci32(efi_pci_io_protocol *__pci, struct pci_setup_rom **__rom)
+{
+	efi_pci_io_protocol_32 *pci;
+	struct pci_setup_rom *rom;
+	efi_status_t status;
+	unsigned long size;
+	uint64_t attributes;
+
+	pci = (efi_pci_io_protocol_32 *)__pci;
+
+	status = efi_early->call(pci->attributes, pci,
+				 EfiPciIoAttributeOperationGet, 0, 0,
+				 &attributes);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	if (!pci->romimage || !pci->romsize)
+		return EFI_INVALID_PARAMETER;
+
+	size = pci->romsize + sizeof(*rom);
+
+	status = efi_early->call(efi_early->allocate_pool,
+				 EFI_LOADER_DATA, size, &rom);
+
+	if (status != EFI_SUCCESS)
+		return status;
+
+	rom->data.type = SETUP_PCI;
+	rom->data.len = size - sizeof(struct setup_data);
+	rom->data.next = 0;
+	rom->pcilen = pci->romsize;
+	*__rom = rom;
+
+	status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+				 PCI_VENDOR_ID, 1, &(rom->vendor));
+
+	if (status != EFI_SUCCESS)
+		goto free_struct;
+
+	status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+				 PCI_DEVICE_ID, 1, &(rom->devid));
+
+	if (status != EFI_SUCCESS)
+		goto free_struct;
+
+	status = efi_early->call(pci->get_location, pci, &(rom->segment),
+				 &(rom->bus), &(rom->device), &(rom->function));
+
+	if (status != EFI_SUCCESS)
+		goto free_struct;
+
+	memcpy(rom->romdata, pci->romimage, pci->romsize);
+	return status;
+
+free_struct:
+	efi_early->call(efi_early->free_pool, rom);
+	return status;
+}
+
+static efi_status_t
+__setup_efi_pci64(efi_pci_io_protocol *__pci, struct pci_setup_rom **__rom)
+{
+	efi_pci_io_protocol_64 *pci;
+	struct pci_setup_rom *rom;
+	efi_status_t status;
+	unsigned long size;
+	uint64_t attributes;
+
+	pci = (efi_pci_io_protocol_64 *)__pci;
+
+	status = efi_early->call(pci->attributes, pci,
+				 EfiPciIoAttributeOperationGet, 0,
+				 &attributes);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	if (!pci->romimage || !pci->romsize)
+		return EFI_INVALID_PARAMETER;
+
+	size = pci->romsize + sizeof(*rom);
+
+	status = efi_early->call(efi_early->allocate_pool,
+				 EFI_LOADER_DATA, size, &rom);
+
+	if (status != EFI_SUCCESS)
+		return status;
+
+	rom->data.type = SETUP_PCI;
+	rom->data.len = size - sizeof(struct setup_data);
+	rom->data.next = 0;
+	rom->pcilen = pci->romsize;
+	*__rom = rom;
+
+	status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+				 PCI_VENDOR_ID, 1, &(rom->vendor));
+
+	if (status != EFI_SUCCESS)
+		goto free_struct;
+
+	status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+				 PCI_DEVICE_ID, 1, &(rom->devid));
+
+	if (status != EFI_SUCCESS)
+		goto free_struct;
+
+	status = efi_early->call(pci->get_location, pci, &(rom->segment),
+				 &(rom->bus), &(rom->device), &(rom->function));
+
+	if (status != EFI_SUCCESS)
+		goto free_struct;
+
+	memcpy(rom->romdata, pci->romimage, pci->romsize);
+	return status;
+
+free_struct:
+	efi_early->call(efi_early->free_pool, rom);
+	return status;
+
+}
+
 static efi_status_t setup_efi_pci(struct boot_params *params)
 {
 	efi_pci_io_protocol *pci;
@@ -246,7 +491,6 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
 	nr_pci = size / sizeof(void *);
 	for (i = 0; i < nr_pci; i++) {
 		void *h = pci_handle[i];
-		uint64_t attributes;
 		struct pci_setup_rom *rom;
 
 		status = efi_early->call(efi_early->handle_protocol, h,
@@ -258,71 +502,72 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
 		if (!pci)
 			continue;
 
-#ifdef CONFIG_X86_64
-		status = efi_early->call((unsigned long)pci->attributes, pci,
-					 EfiPciIoAttributeOperationGet, 0,
-					 &attributes);
-#else
-		status = efi_early->call((unsigned long)pci->attributes, pci,
-					 EfiPciIoAttributeOperationGet, 0, 0,
-					 &attributes);
-#endif
-		if (status != EFI_SUCCESS)
-			continue;
-
-		if (!pci->romimage || !pci->romsize)
-			continue;
-
-		size = pci->romsize + sizeof(*rom);
-
-		status = efi_early->call(efi_early->allocate_pool,
-					 EFI_LOADER_DATA, size, &rom);
+		if (efi_early->is64)
+			status = __setup_efi_pci64(pci, &rom);
+		else
+			status = __setup_efi_pci32(pci, &rom);
 
 		if (status != EFI_SUCCESS)
 			continue;
 
-		rom->data.type = SETUP_PCI;
-		rom->data.len = size - sizeof(struct setup_data);
-		rom->data.next = 0;
-		rom->pcilen = pci->romsize;
+		if (data)
+			data->next = (unsigned long)rom;
+		else
+			params->hdr.setup_data = (unsigned long)rom;
 
-		status = efi_early->call((unsigned long)pci->pci.read, pci,
-					 EfiPciIoWidthUint16, PCI_VENDOR_ID,
-					 1, &(rom->vendor));
+		data = (struct setup_data *)rom;
+	}
 
-		if (status != EFI_SUCCESS)
-			goto free_struct;
+free_handle:
+	efi_early->call(efi_early->free_pool, pci_handle);
+	return status;
+}
 
-		status = efi_early->call((unsigned long)pci->pci.read, pci,
-					 EfiPciIoWidthUint16, PCI_DEVICE_ID,
-					 1, &(rom->devid));
+static efi_status_t
+__gop_query32(struct efi_graphics_output_protocol *__gop,
+	      struct efi_graphics_output_mode_info **info,
+	      unsigned long *size, u32 *fb_base, u32 *fb_size)
+{
+	struct efi_graphics_output_protocol_32 *gop;
+	struct efi_graphics_output_protocol_mode_32 *mode;
+	efi_status_t status;
+	unsigned long m;
 
-		if (status != EFI_SUCCESS)
-			goto free_struct;
+	gop = (struct efi_graphics_output_protocol_32 *)__gop;
 
-		status = efi_early->call((unsigned long)pci->get_location, pci,
-					 &(rom->segment), &(rom->bus),
-					 &(rom->device), &(rom->function));
+	m = gop->mode;
+	mode = (struct efi_graphics_output_protocol_mode_32 *)m;
 
-		if (status != EFI_SUCCESS)
-			goto free_struct;
+	status = efi_early->call(gop->query_mode, gop, mode->mode, size, info);
+	if (status != EFI_SUCCESS)
+		return status;
 
-		memcpy(rom->romdata, pci->romimage, pci->romsize);
+	*fb_base = mode->frame_buffer_base;
+	*fb_size = mode->frame_buffer_size;
+	return status;
+}
 
-		if (data)
-			data->next = (unsigned long)rom;
-		else
-			params->hdr.setup_data = (unsigned long)rom;
+static efi_status_t
+__gop_query64(struct efi_graphics_output_protocol *__gop,
+	      struct efi_graphics_output_mode_info **info,
+	      unsigned long *size, u32 *fb_base, u32 *fb_size)
+{
+	struct efi_graphics_output_protocol_64 *gop;
+	struct efi_graphics_output_protocol_mode_64 *mode;
+	efi_status_t status;
+	unsigned long m;
 
-		data = (struct setup_data *)rom;
+	gop = (struct efi_graphics_output_protocol_64 *)__gop;
 
-		continue;
-	free_struct:
-		efi_early->call(efi_early->free_pool, rom);
-	}
+	m = gop->mode;
+	mode = (struct efi_graphics_output_protocol_mode_64 *)m;
 
-free_handle:
-	efi_early->call(efi_early->free_pool, pci_handle);
+	status = efi_early->call(gop->query_mode, gop, mode->mode, size, info);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	*fb_base = mode->frame_buffer_base;
+	*fb_size = mode->frame_buffer_size;
 	return status;
 }
 
@@ -375,8 +620,13 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		if (status == EFI_SUCCESS)
 			conout_found = true;
 
-		status = efi_early->call((unsigned long)gop->query_mode, gop,
-					 gop->mode->mode, &size, &info);
+		if (efi_early->is64)
+			status = __gop_query64(gop, &info, &size,
+					       &fb_base, &fb_size);
+		else
+			status = __gop_query32(gop, &info, &size,
+					       &fb_base, &fb_size);
+
 		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
 			/*
 			 * Systems that use the UEFI Console Splitter may
@@ -387,8 +637,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 			 */
 			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;
-- 
1.8.3.1

  parent reply	other threads:[~2014-01-29 16:23 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-29 16:23 [RFC][PATCH 00/11] EFI mixed mode Matt Fleming
     [not found] ` <1391012637-4839-1-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-01-29 16:23   ` [RFC][PATCH 01/11] x86/boot: Cleanup header.S by removing some #ifdefs Matt Fleming
     [not found]     ` <1391012637-4839-2-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-01-30 15:54       ` Borislav Petkov
     [not found]         ` <20140130155438.GD23342-fF5Pk5pvG8Y@public.gmane.org>
2014-01-30 16:03           ` Matt Fleming
2014-01-29 16:23   ` [RFC][PATCH 02/11] x86, tools: Consolidate #ifdef code Matt Fleming
     [not found]     ` <1391012637-4839-3-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-01-30 16:05       ` Borislav Petkov
2014-01-29 16:23   ` [RFC][PATCH 03/11] x86/mm/pageattr: Make __lookup_address_in_pgd() global Matt Fleming
     [not found]     ` <1391012637-4839-4-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-01-30 16:36       ` Borislav Petkov
2014-01-29 16:23   ` [RFC][PATCH 04/11] x86/efi: Delete dead code when checking for non-native Matt Fleming
     [not found]     ` <1391012637-4839-5-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-02-07 16:40       ` Borislav Petkov
2014-01-29 16:23   ` [RFC][PATCH 05/11] efi: Add separate 32-bit/64-bit definitions Matt Fleming
     [not found]     ` <1391012637-4839-6-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-02-07 16:52       ` Borislav Petkov
2014-01-29 16:23   ` [RFC][PATCH 06/11] x86/efi: Build our own EFI services pointer table Matt Fleming
2014-01-29 16:23   ` [RFC][PATCH 07/11] x86/efi: Add early thunk code to go from 64-bit to 32-bit Matt Fleming
2014-01-29 16:23   ` Matt Fleming [this message]
2014-01-29 16:23   ` [RFC][PATCH 09/11] x86/efi: Firmware agnostic handover entry points Matt Fleming
2014-01-29 16:23   ` [RFC][PATCH 10/11] x86/efi: Add mixed runtime services support Matt Fleming
2014-01-29 16:23   ` [RFC][PATCH 11/11] x86/efi: Wire up CONFIG_EFI_MIXED Matt Fleming

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1391012637-4839-9-git-send-email-matt@console-pimps.org \
    --to=matt-hnk1s37rvnbexh+ff434mdi2o/jbrioy@public.gmane.org \
    --cc=alan-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org \
    --cc=bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org \
    --cc=hpa-YMNOUZJC4hwAvxtiuMwx3w@public.gmane.org \
    --cc=linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).