#include <asm/page.h>
#include <asm/asm_defns.h>
#include <asm/early_printk.h>
+#include <efi/efierr.h>
+#include <asm/arm64/efibind.h>
#define PT_PT 0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
#define PT_MEM 0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
/*
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
*/
- b real_start /* branch to kernel start, magic */
- .long 0 /* reserved */
+efi_head:
+ /*
+ * This add instruction has no meaningful effect except that
+ * its opcode forms the magic "MZ" signature of a PE/COFF file
+ * that is required for UEFI applications.
+ */
+ add x13, x18, #0x16
+ b real_start /* branch to kernel start */
.quad 0 /* Image load offset from start of RAM */
.quad 0 /* reserved */
.quad 0 /* reserved */
.byte 0x52
.byte 0x4d
.byte 0x64
- .word 0 /* reserved */
+ .long pe_header - efi_head /* Offset to the PE header. */
+
+ /*
+ * Add the PE/COFF header to the file. The address of this header
+ * is at offset 0x3c in the file, and is part of Linux "Image"
+ * header. The arm64 Linux Image format is designed to support
+ * being both an 'Image' format binary and a PE/COFF binary.
+ * The PE/COFF format is defined by Microsoft, and is available
+ * from: http://msdn.microsoft.com/en-us/gg463119.aspx
+ * Version 8.3 adds support for arm64 and UEFI usage.
+ */
+
+ .align 3
+pe_header:
+ .ascii "PE"
+ .short 0
+coff_header:
+ .short 0xaa64 /* AArch64 */
+ .short 2 /* nr_sections */
+ .long 0 /* TimeDateStamp */
+ .long 0 /* PointerToSymbolTable */
+ .long 1 /* NumberOfSymbols */
+ .short section_table - optional_header /* SizeOfOptionalHeader */
+ .short 0x206 /* Characteristics. */
+ /* IMAGE_FILE_DEBUG_STRIPPED | */
+ /* IMAGE_FILE_EXECUTABLE_IMAGE | */
+ /* IMAGE_FILE_LINE_NUMS_STRIPPED */
+optional_header:
+ .short 0x20b /* PE32+ format */
+ .byte 0x02 /* MajorLinkerVersion */
+ .byte 0x14 /* MinorLinkerVersion */
+ .long _end - real_start /* SizeOfCode */
+ .long 0 /* SizeOfInitializedData */
+ .long 0 /* SizeOfUninitializedData */
+ .long efi_start - efi_head /* AddressOfEntryPoint */
+ .long real_start - efi_head /* BaseOfCode */
+
+extra_header_fields:
+ .quad 0 /* ImageBase */
+ .long 0x1000 /* SectionAlignment (4 KByte) */
+ .long 0x8 /* FileAlignment */
+ .short 0 /* MajorOperatingSystemVersion */
+ .short 0 /* MinorOperatingSystemVersion */
+ .short 0 /* MajorImageVersion */
+ .short 0 /* MinorImageVersion */
+ .short 0 /* MajorSubsystemVersion */
+ .short 0 /* MinorSubsystemVersion */
+ .long 0 /* Win32VersionValue */
+
+ .long _end - efi_head /* SizeOfImage */
+
+ /* Everything before the kernel image is considered part of the header */
+ .long real_start - efi_head /* SizeOfHeaders */
+ .long 0 /* CheckSum */
+ .short 0xa /* Subsystem (EFI application) */
+ .short 0 /* DllCharacteristics */
+ .quad 0 /* SizeOfStackReserve */
+ .quad 0 /* SizeOfStackCommit */
+ .quad 0 /* SizeOfHeapReserve */
+ .quad 0 /* SizeOfHeapCommit */
+ .long 0 /* LoaderFlags */
+ .long 0x6 /* NumberOfRvaAndSizes */
+
+ .quad 0 /* ExportTable */
+ .quad 0 /* ImportTable */
+ .quad 0 /* ResourceTable */
+ .quad 0 /* ExceptionTable */
+ .quad 0 /* CertificationTable */
+ .quad 0 /* BaseRelocationTable */
+
+ /* Section table */
+section_table:
+ /*
+ * The EFI application loader requires a relocation section
+ * because EFI applications must be relocatable. This is a
+ * dummy section as far as we are concerned.
+ */
+ .ascii ".reloc"
+ .byte 0
+ .byte 0 /* end of 0 padding of section name */
+ .long 0
+ .long 0
+ .long 0 /* SizeOfRawData */
+ .long 0 /* PointerToRawData */
+ .long 0 /* PointerToRelocations */
+ .long 0 /* PointerToLineNumbers */
+ .short 0 /* NumberOfRelocations */
+ .short 0 /* NumberOfLineNumbers */
+ .long 0x42100040 /* Characteristics (section flags) */
+
+
+ .ascii ".text"
+ .byte 0
+ .byte 0
+ .byte 0 /* end of 0 padding of section name */
+ .long _end - real_start /* VirtualSize */
+ .long real_start - efi_head /* VirtualAddress */
+ .long __init_end_efi - real_start /* SizeOfRawData */
+ .long real_start - efi_head /* PointerToRawData */
+
+ .long 0 /* PointerToRelocations (0 for executables) */
+ .long 0 /* PointerToLineNumbers (0 for executables) */
+ .short 0 /* NumberOfRelocations (0 for executables) */
+ .short 0 /* NumberOfLineNumbers (0 for executables) */
+ .long 0xe0500020 /* Characteristics (section flags) */
+ .align 5
real_start:
msr DAIFSet, 0xf /* Disable all interrupts */
ENTRY(lookup_processor_type)
mov x0, #0
ret
+/*
+ * Function to transition from EFI loader in C, to Xen entry point.
+ * void noreturn efi_xen_start(void *fdt_ptr);
+ */
+ENTRY(efi_xen_start)
+ /*
+ * Turn off cache and MMU as Xen expects. EFI enables them, but also
+ * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
+ * MMU while executing EFI code before entering Xen.
+ * The EFI loader calls this to start Xen.
+ * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
+ * restore for entry into Xen.
+ */
+ mov x20, x0
+ bl __flush_dcache_all
+ ic ialluis
+
+ /* Turn off Dcache and MMU */
+ mrs x0, sctlr_el2
+ bic x0, x0, #1 << 0 /* clear SCTLR.M */
+ bic x0, x0, #1 << 2 /* clear SCTLR.C */
+ msr sctlr_el2, x0
+ isb
+
+ /* Jump to Xen entry point */
+ mov x0, x20
+ mov x1, xzr
+ mov x2, xzr
+ mov x3, xzr
+ b real_start
+ENDPROC(efi_xen_start)
/*
* Local variables:
--- /dev/null
+/*
+ * Architecture specific implementation for EFI boot code. This file
+ * is intended to be included by common/efi/boot.c _only_, and
+ * therefore can define arch specific global variables.
+ */
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <asm/setup.h>
+
+void noreturn efi_xen_start(void *fdt_ptr);
+
+#define DEVICE_TREE_GUID \
+{0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}}
+
+static struct file __initdata dtbfile;
+static void __initdata *fdt;
+static void __initdata *memmap;
+
+static int __init setup_chosen_node(void *fdt, int *addr_cells, int *size_cells)
+{
+ int node;
+ const struct fdt_property *prop;
+ int len;
+ uint32_t val;
+
+ if ( !fdt || !addr_cells || !size_cells )
+ return -1;
+
+ /* locate chosen node, which is where we add Xen module info. */
+ node = fdt_subnode_offset(fdt, 0, "chosen");
+ if ( node < 0 )
+ {
+ node = fdt_add_subnode(fdt, 0, "chosen");
+ if ( node < 0 )
+ return node;
+ }
+
+ /* Get or set #address-cells and #size-cells */
+ prop = fdt_get_property(fdt, node, "#address-cells", &len);
+ if ( !prop )
+ {
+ val = cpu_to_fdt32(2);
+ if ( fdt_setprop(fdt, node, "#address-cells", &val, sizeof(val)) )
+ return -1;
+ *addr_cells = 2;
+ }
+ else
+ *addr_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+ prop = fdt_get_property(fdt, node, "#size-cells", &len);
+ if ( !prop )
+ {
+ val = cpu_to_fdt32(2);
+ if ( fdt_setprop(fdt, node, "#size-cells", &val, sizeof(val)) )
+ return -1;
+ *size_cells = 2;
+ }
+ else
+ *size_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+ /*
+ * Make sure ranges is empty if it exists, otherwise create empty ranges
+ * property.
+ */
+ prop = fdt_get_property(fdt, node, "ranges", &len);
+ if ( !prop )
+ {
+ val = cpu_to_fdt32(0);
+ if ( fdt_setprop(fdt, node, "ranges", &val, 0) )
+ return -1;
+ }
+ else if ( fdt32_to_cpu(prop->len) )
+ return -1; /* Non-empty ranges property */
+ return node;
+}
+
+/*
+ * Set a single 'reg' property taking into account the
+ * configured addr and size cell sizes.
+ */
+static int __init fdt_set_reg(void *fdt, int node, int addr_cells,
+ int size_cells, uint64_t addr, uint64_t len)
+{
+ __be32 val[4]; /* At most 2 64 bit values to be stored */
+ __be32 *cellp;
+
+ /*
+ * Make sure that the values provided can be represented in
+ * the reg property, and sizes are valid.
+ */
+ if ( addr_cells < 1 || addr_cells > 2 || size_cells < 1 || size_cells > 2 )
+ return -1;
+ if ( addr_cells == 1 && (addr >> 32) )
+ return -1;
+ if ( size_cells == 1 && (len >> 32) )
+ return -1;
+
+ cellp = (__be32 *)val;
+ dt_set_cell(&cellp, addr_cells, addr);
+ dt_set_cell(&cellp, size_cells, len);
+
+ return(fdt_setprop(fdt, node, "reg", val, sizeof(*cellp) * (cellp - val)));
+}
+
+static void __init *lookup_fdt_config_table(EFI_SYSTEM_TABLE *sys_table)
+{
+ const EFI_GUID fdt_guid = DEVICE_TREE_GUID;
+ EFI_CONFIGURATION_TABLE *tables;
+ void *fdt = NULL;
+ int i;
+
+ tables = sys_table->ConfigurationTable;
+ for ( i = 0; i < sys_table->NumberOfTableEntries; i++ )
+ {
+ if ( match_guid(&tables[i].VendorGuid, &fdt_guid) )
+ {
+ fdt = tables[i].VendorTable;
+ break;
+ }
+ }
+ return fdt;
+}
+
+static EFI_STATUS __init efi_process_memory_map_bootinfo(EFI_MEMORY_DESCRIPTOR *map,
+ UINTN mmap_size,
+ UINTN desc_size)
+{
+ int Index;
+ int i = 0;
+ EFI_MEMORY_DESCRIPTOR *desc_ptr = map;
+
+ for ( Index = 0; Index < (mmap_size / desc_size); Index++ )
+ {
+ if ( desc_ptr->Type == EfiConventionalMemory
+ || desc_ptr->Type == EfiBootServicesCode
+ || desc_ptr->Type == EfiBootServicesData )
+ {
+ bootinfo.mem.bank[i].start = desc_ptr->PhysicalStart;
+ bootinfo.mem.bank[i].size = desc_ptr->NumberOfPages * EFI_PAGE_SIZE;
+ if ( ++i >= NR_MEM_BANKS )
+ {
+ PrintStr(L"Warning: All ");
+ DisplayUint(NR_MEM_BANKS, -1);
+ PrintStr(L" bootinfo mem banks exhausted.\r\n");
+ break;
+ }
+ }
+ desc_ptr = NextMemoryDescriptor(desc_ptr, desc_size);
+ }
+
+ bootinfo.mem.nr_banks = i;
+ return EFI_SUCCESS;
+}
+
+/*
+ * Add the FDT nodes for the standard EFI information, which consist
+ * of the System table address, the address of the final EFI memory map,
+ * and memory map information.
+ */
+EFI_STATUS __init fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table,
+ void *fdt,
+ EFI_MEMORY_DESCRIPTOR *memory_map,
+ UINTN map_size,
+ UINTN desc_size,
+ UINT32 desc_ver)
+{
+ int node;
+ int status;
+ u32 fdt_val32;
+ u64 fdt_val64;
+ int prev;
+ int num_rsv;
+
+ /*
+ * Delete any memory nodes present. The EFI memory map is the only
+ * memory description provided to Xen.
+ */
+ prev = 0;
+ for (;;)
+ {
+ const char *type;
+ int len;
+
+ node = fdt_next_node(fdt, prev, NULL);
+ if ( node < 0 )
+ break;
+
+ type = fdt_getprop(fdt, node, "device_type", &len);
+ if ( type && strncmp(type, "memory", len) == 0 )
+ {
+ fdt_del_node(fdt, node);
+ continue;
+ }
+
+ prev = node;
+ }
+
+ /*
+ * Delete all memory reserve map entries. When booting via UEFI,
+ * kernel will use the UEFI memory map to find reserved regions.
+ */
+ num_rsv = fdt_num_mem_rsv(fdt);
+ while ( num_rsv-- > 0 )
+ fdt_del_mem_rsv(fdt, num_rsv);
+
+ /* Add FDT entries for EFI runtime services in chosen node. */
+ node = fdt_subnode_offset(fdt, 0, "chosen");
+ if ( node < 0 )
+ {
+ node = fdt_add_subnode(fdt, 0, "chosen");
+ if ( node < 0 )
+ {
+ status = node; /* node is error code when negative */
+ goto fdt_set_fail;
+ }
+ }
+
+ fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)sys_table);
+ status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+ &fdt_val64, sizeof(fdt_val64));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)memory_map);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+ &fdt_val64, sizeof(fdt_val64));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(map_size);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+ &fdt_val32, sizeof(fdt_val32));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(desc_size);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+ &fdt_val32, sizeof(fdt_val32));
+ if ( status )
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(desc_ver);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+ &fdt_val32, sizeof(fdt_val32));
+ if ( status )
+ goto fdt_set_fail;
+
+ return EFI_SUCCESS;
+
+fdt_set_fail:
+ if ( status == -FDT_ERR_NOSPACE )
+ return EFI_BUFFER_TOO_SMALL;
+
+ return EFI_LOAD_ERROR;
+}
+
+/*
+ * Allocates new memory for a larger FDT, and frees existing memory if
+ * struct file size is non-zero. Updates file struct with new memory
+ * address/size for later freeing. If fdtfile.ptr is NULL, an empty FDT
+ * is created.
+ */
+static void __init *fdt_increase_size(struct file *fdtfile, int add_size)
+{
+ EFI_STATUS status;
+ EFI_PHYSICAL_ADDRESS fdt_addr;
+ int fdt_size;
+ int pages;
+ void *new_fdt;
+
+ if ( fdtfile->ptr )
+ fdt_size = fdt_totalsize(fdtfile->ptr);
+ else
+ fdt_size = 0;
+
+ pages = PFN_UP(fdt_size + add_size);
+ status = efi_bs->AllocatePages(AllocateAnyPages, EfiLoaderData,
+ pages, &fdt_addr);
+
+ if ( status != EFI_SUCCESS )
+ return NULL;
+
+ new_fdt = (void *)fdt_addr;
+
+ if ( fdt_size )
+ {
+ if ( fdt_open_into(dtbfile.ptr, new_fdt, pages * EFI_PAGE_SIZE) )
+ return NULL;
+ }
+ else
+ {
+ /*
+ * Create an empty FDT if not provided one, which is the expected case
+ * when booted from the UEFI shell on an ACPI only system. We will use
+ * the FDT to pass the EFI information to Xen, as well as nodes for
+ * any modules the stub loads. The ACPI tables are part of the UEFI
+ * system table that is passed in the FDT.
+ */
+ if ( fdt_create_empty_tree(new_fdt, pages * EFI_PAGE_SIZE) )
+ return NULL;
+ }
+
+ /*
+ * Now that we have the new FDT allocated and copied, free the
+ * original and update the struct file so that the error handling
+ * code will free it. If the original FDT came from a configuration
+ * table, we don't own that memory and can't free it.
+ */
+ if ( dtbfile.size )
+ efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+
+ /* Update 'file' info for new memory so we clean it up on error exits */
+ dtbfile.addr = fdt_addr;
+ dtbfile.size = pages * EFI_PAGE_SIZE;
+ return new_fdt;
+}
+
+static void __init efi_arch_relocate_image(unsigned long delta)
+{
+}
+
+static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
+ void *map,
+ UINTN map_size,
+ UINTN desc_size,
+ UINT32 desc_ver)
+{
+ EFI_STATUS status;
+
+ status = efi_process_memory_map_bootinfo(map, map_size, desc_size);
+ if ( EFI_ERROR(status) )
+ blexit(L"EFI memory map processing failed");
+
+ status = fdt_add_uefi_nodes(SystemTable, fdt, map, map_size, desc_size,
+ desc_ver);
+ if ( EFI_ERROR(status) )
+ PrintErrMesg(L"Updating FDT failed\r\n", status);
+}
+
+static void __init efi_arch_pre_exit_boot(void)
+{
+}
+
+static void __init efi_arch_post_exit_boot(void)
+{
+ efi_xen_start(fdt);
+}
+
+static void __init efi_arch_cfg_file_early(EFI_FILE_HANDLE dir_handle, char *section)
+{
+ union string name;
+
+ /*
+ * The DTB must be processed before any other entries in the configuration
+ * file, as the DTB is updated as modules are loaded.
+ */
+ name.s = get_value(&cfg, section, "dtb");
+ if ( name.s )
+ {
+ split_string(name.s);
+ read_file(dir_handle, s2w(&name), &dtbfile, NULL);
+ blexit(NULL);
+ efi_bs->FreePool(name.w);
+ }
+ fdt = fdt_increase_size(&dtbfile, cfg.size + EFI_PAGE_SIZE);
+ if ( !fdt )
+ blexit(L"Unable to create new FDT");
+}
+
+static void __init efi_arch_cfg_file_late(EFI_FILE_HANDLE dir_handle, char *section)
+{
+}
+
+static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
+{
+ void *ptr;
+ EFI_STATUS status;
+
+ status = efi_bs->AllocatePool(EfiLoaderData, map_size + EFI_PAGE_SIZE, &ptr);
+ if ( status != EFI_SUCCESS )
+ return NULL;
+ return ptr;
+}
+
+static void __init efi_arch_edd(void)
+{
+}
+
+static void __init efi_arch_memory_setup(void)
+{
+}
+
+static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
+ CHAR16 *cmdline_options,
+ char *cfgfile_options)
+{
+ union string name;
+ char *buf;
+ EFI_STATUS status;
+ int prop_len;
+ int chosen;
+
+ /* locate chosen node, which is where we add Xen module info. */
+ chosen = fdt_subnode_offset(fdt, 0, "chosen");
+ if ( chosen < 0 )
+ blexit(L"Unable to find chosen node");
+
+ status = efi_bs->AllocatePool(EfiBootServicesData, EFI_PAGE_SIZE, (void **)&buf);
+ if ( EFI_ERROR(status) )
+ PrintErrMesg(L"Unable to allocate string buffer\r\n", status);
+
+ if ( image_name )
+ {
+ name.w = image_name;
+ w2s(&name);
+ }
+ else
+ name.s = "xen";
+
+ prop_len = 0;
+ prop_len += snprintf(buf + prop_len,
+ EFI_PAGE_SIZE - prop_len, "%s", name.s);
+ if ( prop_len >= EFI_PAGE_SIZE )
+ blexit(L"FDT string overflow");
+
+ if ( cfgfile_options )
+ {
+ prop_len += snprintf(buf + prop_len,
+ EFI_PAGE_SIZE - prop_len, " %s", cfgfile_options);
+ if ( prop_len >= EFI_PAGE_SIZE )
+ blexit(L"FDT string overflow");
+ }
+
+ if ( cmdline_options )
+ {
+ name.w = cmdline_options;
+ w2s(&name);
+ }
+ else
+ name.s = NULL;
+
+ if ( name.s )
+ {
+ prop_len += snprintf(buf + prop_len,
+ EFI_PAGE_SIZE - prop_len, " %s", name.s);
+ if ( prop_len >= EFI_PAGE_SIZE )
+ blexit(L"FDT string overflow");
+ }
+
+ if ( fdt_setprop_string(fdt, chosen, "xen,xen-bootargs", buf) < 0 )
+ blexit(L"Unable to set xen,xen-bootargs property.");
+
+ efi_bs->FreePool(buf);
+}
+
+static void __init efi_arch_handle_module(struct file *file, const CHAR16 *name,
+ char *options)
+{
+ int node;
+ int chosen;
+ int addr_len, size_len;
+
+ if ( file == &dtbfile )
+ return;
+ chosen = setup_chosen_node(fdt, &addr_len, &size_len);
+ if ( chosen < 0 )
+ blexit(L"Unable to setup chosen node");
+
+ if ( file == &ramdisk )
+ {
+ char ramdisk_compat[] = "multiboot,ramdisk\0multiboot,module";
+ node = fdt_add_subnode(fdt, chosen, "ramdisk");
+ if ( node < 0 )
+ blexit(L"Unable to add ramdisk FDT node.");
+ if ( fdt_setprop(fdt, node, "compatible", ramdisk_compat,
+ sizeof(ramdisk_compat)) < 0 )
+ blexit(L"Unable to set compatible property.");
+ if ( fdt_set_reg(fdt, node, addr_len, size_len, ramdisk.addr,
+ ramdisk.size) < 0 )
+ blexit(L"Unable to set reg property.");
+ }
+ else if ( file == &xsm )
+ {
+ char xsm_compat[] = "xen,xsm-policy\0multiboot,module";
+ node = fdt_add_subnode(fdt, chosen, "xsm");
+ if ( node < 0 )
+ blexit(L"Unable to add xsm FDT node.");
+ if ( fdt_setprop(fdt, node, "compatible", xsm_compat,
+ sizeof(xsm_compat)) < 0 )
+ blexit(L"Unable to set compatible property.");
+ if ( fdt_set_reg(fdt, node, addr_len, size_len, xsm.addr,
+ xsm.size) < 0 )
+ blexit(L"Unable to set reg property.");
+ }
+ else if ( file == &kernel )
+ {
+ char kernel_compat[] = "multiboot,kernel\0multiboot,module";
+ node = fdt_add_subnode(fdt, chosen, "kernel");
+ if ( node < 0 )
+ blexit(L"Unable to add dom0 FDT node.");
+ if ( fdt_setprop(fdt, node, "compatible", kernel_compat,
+ sizeof(kernel_compat)) < 0 )
+ blexit(L"Unable to set compatible property.");
+ if ( options && fdt_setprop_string(fdt, node, "bootargs", options) < 0 )
+ blexit(L"Unable to set bootargs property.");
+ if ( fdt_set_reg(fdt, node, addr_len, size_len, kernel.addr,
+ kernel.size) < 0 )
+ blexit(L"Unable to set reg property.");
+ }
+ else
+ blexit(L"Unknown module type");
+}
+
+static void __init efi_arch_cpu(void)
+{
+}
+
+static void __init efi_arch_blexit(void)
+{
+ if ( dtbfile.addr && dtbfile.size )
+ efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+ if ( memmap )
+ efi_bs->FreePool(memmap);
+}
+
+static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
+{
+ if ( (unsigned long)loaded_image->ImageBase & ((1 << 12) - 1) )
+ blexit(L"Xen must be loaded at a 4 KByte boundary.");
+}
+
+static bool_t __init efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
+{
+ /*
+ * For arm, we may get a device tree from GRUB (or other bootloader)
+ * that contains modules that have already been loaded into memory. In
+ * this case, we do not use a configuration file, and rely on the
+ * bootloader to have loaded all required modules and appropriate
+ * options.
+ */
+
+ fdt = lookup_fdt_config_table(SystemTable);
+ dtbfile.ptr = fdt;
+ dtbfile.size = 0; /* Config table memory can't be freed, so set size to 0 */
+ if ( !fdt || fdt_node_offset_by_compatible(fdt, 0, "multiboot,module") < 0 )
+ {
+ /*
+ * We either have no FDT, or one without modules, so we must have a
+ * Xen EFI configuration file to specify modules. (dom0 required)
+ */
+ return 1;
+ }
+ PrintStr(L"Using modules provided by bootloader in FDT\r\n");
+ /* We have modules already defined in fdt, just add space. */
+ fdt = fdt_increase_size(&dtbfile, EFI_PAGE_SIZE);
+ return 0;
+}
+
+static void __init efi_arch_console_init(UINTN cols, UINTN rows)
+{
+}
+
+static void __init efi_arch_video_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
+ UINTN info_size,
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info)
+{
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*++
+
+Copyright (c) 1998 Intel Corporation
+
+Module Name:
+
+ efefind.h
+
+Abstract:
+
+ EFI to compile bindings
+
+
+
+
+Revision History
+
+--*/
+
+#ifndef __GNUC__
+#pragma pack()
+#endif
+
+#define EFIERR(a) (0x8000000000000000 | a)
+#define EFI_ERROR_MASK 0x8000000000000000
+#define EFIERR_OEM(a) (0xc000000000000000 | a)
+
+#define BAD_POINTER 0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
+
+#define EFI_STUB_ERROR MAX_ADDRESS
+
+#ifndef __ASSEMBLY__
+//
+// Basic int types of various widths
+//
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )
+
+ // No ANSI C 1999/2000 stdint.h integer width declarations
+
+ #if defined(__GNUC__)
+ typedef unsigned long long uint64_t __attribute__((aligned (8)));
+ typedef long long int64_t __attribute__((aligned (8)));
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #elif defined(UNIX_LP64)
+
+ /* Use LP64 programming model from C_FLAGS for integer width declarations */
+
+ typedef unsigned long uint64_t;
+ typedef long int64_t;
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #else
+
+ /* Assume P64 programming model from C_FLAGS for integer width declarations */
+
+ typedef unsigned long long uint64_t __attribute__((aligned (8)));
+ typedef long long int64_t __attribute__((aligned (8)));
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #endif
+#endif
+
+//
+// Basic EFI types of various widths
+//
+
+#ifndef __WCHAR_TYPE__
+# define __WCHAR_TYPE__ short
+#endif
+
+typedef uint64_t UINT64;
+typedef int64_t INT64;
+
+#ifndef _BASETSD_H_
+ typedef uint32_t UINT32;
+ typedef int32_t INT32;
+#endif
+
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef uint8_t UINT8;
+typedef int8_t INT8;
+typedef __WCHAR_TYPE__ WCHAR;
+
+#undef VOID
+#define VOID void
+
+
+typedef int64_t INTN;
+typedef uint64_t UINTN;
+
+#define POST_CODE(_Data)
+
+
+#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32
+
+//
+// Pointers must be aligned to these address to function
+//
+
+#define MIN_ALIGNMENT_SIZE 4
+
+#define ALIGN_VARIABLE(Value ,Adjustment) \
+ (UINTN)Adjustment = 0; \
+ if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
+ (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
+ Value = (UINTN)Value + (UINTN)Adjustment
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+
+#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+#define EXPORTAPI
+
+
+//
+// EFIAPI - prototype calling convention for EFI function pointers
+// BOOTSERVICE - prototype for implementation of a boot service interface
+// RUNTIMESERVICE - prototype for implementation of a runtime service interface
+// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
+// RUNTIME_CODE - pragma macro for declaring runtime code
+//
+
+#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
+ #define EFIAPI // Substitute expresion to force C calling convention
+#endif
+
+#define BOOTSERVICE
+//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a
+//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a
+#define RUNTIMESERVICE
+#define RUNTIMEFUNCTION
+
+
+#define RUNTIME_CODE(a) alloc_text("rtcode", a)
+#define BEGIN_RUNTIME_DATA() data_seg("rtdata")
+#define END_RUNTIME_DATA() data_seg("")
+
+#define VOLATILE volatile
+
+#define MEMORY_FENCE()
+
+
+//
+// When build similiar to FW, then link everything together as
+// one big module.
+//
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction) \
+ UINTN \
+ InitializeDriver ( \
+ VOID *ImageHandle, \
+ VOID *SystemTable \
+ ) \
+ { \
+ return InitFunction(ImageHandle, \
+ SystemTable); \
+ } \
+ \
+ EFI_STATUS efi_main( \
+ EFI_HANDLE image, \
+ EFI_SYSTEM_TABLE *systab \
+ ) __attribute__((weak, \
+ alias ("InitializeDriver")));
+
+#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
+ (_if)->LoadInternal(type, name, entry)
+
+
+//
+// Some compilers don't support the forward reference construct:
+// typedef struct XXXXX
+//
+// The following macro provide a workaround for such cases.
+//
+#ifdef NO_INTERFACE_DECL
+#define INTERFACE_DECL(x)
+#else
+#ifdef __GNUC__
+#define INTERFACE_DECL(x) struct x
+#else
+#define INTERFACE_DECL(x) typedef struct x
+#endif
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */