/* -----------------------------------------------------------------------
*
* 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 <linux/efi.h>
#include <linux/pci.h>
#include <asm/efi.h>
#include <asm/e820/types.h>
#include <asm/setup.h>
#include <asm/desc.h>
#include "../string.h"
#include "eboot.h"
static efi_system_table_t *sys_table;
static struct efi_config *efi_early;
__pure const struct efi_config *__efi_early(void)
{
return efi_early;
}
#define BOOT_SERVICES(bits) \
static void setup_boot_services##bits(struct efi_config *c) \
{ \
efi_system_table_##bits##_t *table; \
\
table = (typeof(table))sys_table; \
\
c->runtime_services = table->runtime; \
c->boot_services = table->boottime; \
c->text_output = table->con_out; \
}
BOOT_SERVICES(32);
BOOT_SERVICES(64);
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_call_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_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;
unsigned long func;
status = efi_call_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;
}
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);
}
void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
{
efi_call_proto(efi_simple_text_output_protocol, output_string,
efi_early->text_output, str);
}
static efi_status_t
__setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
{
struct pci_setup_rom *rom = NULL;
efi_status_t status;
unsigned long size;
uint64_t attributes;
status = efi_early->call(pci->attributes, pci,
EfiPciIoAttributeOperationGet, 0, 0,
&attributes);
if (status != EFI_SUCCESS)
return status