mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86-64: EFI boot code
Besides introducing the relevant code paralleling parts of what is under xen/arch/x86/boot/, this adjusts the build logic so that with a single compilation two images (gzip-compressed ELF and EFI application) can get created. The EFI part of this depends on a new enough compiler (supposedly gcc 4.4.x and above, but so far only tested to work with 4.5.x) and a properly configured linker (must support the i386pep emulation). If either functionality is found to not be available, the EFI part of the build will simply be skipped. The patch adds all code to allow Xen and the (accordingly enabled) Dom0 kernel to boot, but doesn't allow Dom0 to make use of EFI runtime calls (this will be the subject of the next patch). Parts of the code were lifted from an earlier never published OS project of ours - whether respective license information needs to be added to the respective source file is unclear to me (I was told internally that adding a GPLv2 license header can be done if needed by the community). Open issues (not preventing this from being committed imo): The trampoline allocation and initialization isn't really nice. This is due to the trampoline needing to be placed at a fixed address, and hence making the trampoline relocatable would seem desirable here (as well as for BIOS-based booting, where the trampoline location needed to be adjusted a number of time already in the past, due to it colliding with firmware data). By excluding mem.S, edd.S, and video.S from copied trampoline (i.e. moving up wakeup.S? and making sure none of the symbols are used from EFI code), the effective trampoline size could at least be reduced. Should the mappings of [__XEN_VIRT_START, mbi.mem_upper) and [_end, __XEN_VIRT_START+BOOTSTRAP_MAP_BASE) be destroyed, despite non-EFI code also keeping them? Signed-off-by: Jan Beulich <jbeulich@novell.com>
This commit is contained in:
1 parent
f402de45cd
commit
bf6501a62e
29 files changed
+2065
-24
No files matched your search
@@ -12,6 +12,8 @@ export XEN_DOMAIN ?= $(shell ([ -x /bin/dnsdomainname ] && /bin/dnsdomainname) |
|
||||
export BASEDIR := $(CURDIR)
|
||||
export XEN_ROOT := $(BASEDIR)/..
|
||||
|
||||
EFI_MOUNTPOINT ?= /boot/efi
|
||||
|
||||
.PHONY: default
|
||||
default: build
|
||||
|
||||
@@ -33,6 +35,13 @@ _install: $(TARGET).gz
|
||||
ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).gz
|
||||
ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET)).gz
|
||||
$(INSTALL_DATA) $(TARGET)-syms $(DESTDIR)/boot/$(notdir $(TARGET))-syms-$(XEN_FULLVERSION)
|
||||
if [ -r $(TARGET).efi -a -n "$(EFI_MOUNTPOINT)" ]; then \
|
||||
if [ -n '$(EFI_VENDOR)' ]; then \
|
||||
$(INSTALL_DATA) $(TARGET).efi $(DESTDIR)$(EFI_MOUNTPOINT)/efi/$(EFI_VENDOR)/$(notdir $(TARGET))-$(XEN_FULLVERSION).efi; \
|
||||
elif [ "$(DESTDIR)" = "$(patsubst $(shell cd $(XEN_ROOT) && pwd)/%,%,$(DESTDIR))" ]; then \
|
||||
echo 'EFI installation not done (EFI_VENDOR not set)' >&2; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
.PHONY: _debug
|
||||
_debug:
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ _clean_%/: FORCE
|
||||
SPECIAL_DATA_SECTIONS := rodata $(foreach n,1 2 4 8,rodata.str1.$(n)) \
|
||||
$(foreach r,rel rel.ro,data.$(r) data.$(r).local)
|
||||
|
||||
$(filter %.init.o,$(obj-y) $(obj-bin-y)): %.init.o: %.o Makefile
|
||||
$(filter %.init.o,$(obj-y) $(obj-bin-y) $(extra-y)): %.init.o: %.o Makefile
|
||||
$(OBJDUMP) -h $< | sed -n '/[0-9]/{s,00*,0,g;p}' | while read idx name sz rest; do \
|
||||
case "$$name" in \
|
||||
.text|.text.*|.data|.data.*|.bss) \
|
||||
|
||||
+61
-4
@@ -62,28 +62,43 @@ obj-$(crash_debug) += gdbstub.o
|
||||
|
||||
x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
|
||||
|
||||
$(TARGET): $(TARGET)-syms boot/mkelf32
|
||||
efi-$(x86_64) := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \
|
||||
-O $(BASEDIR)/include/xen/compile.h ]; then \
|
||||
echo '$(TARGET).efi'; fi)
|
||||
|
||||
$(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32
|
||||
./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \
|
||||
`$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'`
|
||||
|
||||
|
||||
ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o $(ALL_OBJS)
|
||||
ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o $(BASEDIR)/arch/x86/efi/built_in.o $(ALL_OBJS)
|
||||
|
||||
ifeq ($(lto),y)
|
||||
# Gather all LTO objects together
|
||||
prelink_lto.o: $(ALL_OBJS)
|
||||
$(LD_LTO) -r -o $@ $^
|
||||
|
||||
prelink-efi_lto.o: $(ALL_OBJS) efi/runtime.o efi/compat.o
|
||||
$(guard) $(LD_LTO) -r -o $@ $(filter-out %/efi/built_in.o,$^)
|
||||
|
||||
# Link it with all the binary objects
|
||||
prelink.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink_lto.o
|
||||
$(LD) $(LDFLAGS) -r -o $@ $^
|
||||
|
||||
prelink-efi.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink-efi_lto.o efi/boot.init.o
|
||||
$(guard) $(LD) $(LDFLAGS) -r -o $@ $^
|
||||
else
|
||||
prelink.o: $(ALL_OBJS)
|
||||
$(LD) $(LDFLAGS) -r -o $@ $^
|
||||
|
||||
prelink-efi.o: $(ALL_OBJS) efi/boot.init.o efi/runtime.o efi/compat.o
|
||||
$(guard) $(LD) $(LDFLAGS) -r -o $@ $(filter-out %/efi/built_in.o,$^)
|
||||
endif
|
||||
|
||||
$(TARGET)-syms: prelink.o xen.lds
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/common/symbols-dummy.o
|
||||
$(BASEDIR)/common/symbols-dummy.o:
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C $(BASEDIR)/common symbols-dummy.o
|
||||
|
||||
$(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o
|
||||
$(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
|
||||
$(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0
|
||||
$(NM) -n $(@D)/.$(@F).0 | $(BASEDIR)/tools/symbols >$(@D)/.$(@F).0.S
|
||||
@@ -96,6 +111,39 @@ $(TARGET)-syms: prelink.o xen.lds
|
||||
$(@D)/.$(@F).1.o -o $@
|
||||
rm -f $(@D)/.$(@F).[0-9]*
|
||||
|
||||
EFI_LDFLAGS = $(patsubst -m%,-mi386pep,$(LDFLAGS)) --subsystem=10
|
||||
EFI_LDFLAGS += --image-base=$(1) --stack=0,0 --heap=0,0 --strip-debug
|
||||
EFI_LDFLAGS += --section-alignment=0x200000 --file-alignment=0x20
|
||||
EFI_LDFLAGS += --major-image-version=$(XEN_VERSION)
|
||||
EFI_LDFLAGS += --minor-image-version=$(XEN_SUBVERSION)
|
||||
EFI_LDFLAGS += --major-os-version=2 --minor-os-version=0
|
||||
EFI_LDFLAGS += --major-subsystem-version=2 --minor-subsystem-version=0
|
||||
|
||||
$(TARGET).efi: VIRT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A VIRT_START$$,,p')
|
||||
$(TARGET).efi: ALT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A ALT_START$$,,p')
|
||||
# Don't use $(wildcard ...) here - at least make 3.80 expands this too early!
|
||||
$(TARGET).efi: guard = $(if $(shell echo efi/dis* | grep disabled),:)
|
||||
$(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbols-dummy.o efi/mkreloc
|
||||
$(foreach base, $(VIRT_BASE) $(ALT_BASE), \
|
||||
$(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< efi/relocs-dummy.o \
|
||||
$(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).$(base).0 &&) :
|
||||
$(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) $(ALT_BASE),$(@D)/.$(@F).$(base).0) >$(@D)/.$(@F).0r.S
|
||||
$(guard) $(NM) -n $(@D)/.$(@F).$(VIRT_BASE).0 | $(guard) $(BASEDIR)/tools/symbols >$(@D)/.$(@F).0s.S
|
||||
$(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o
|
||||
$(foreach base, $(VIRT_BASE) $(ALT_BASE), \
|
||||
$(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< \
|
||||
$(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o -o $(@D)/.$(@F).$(base).1 &&) :
|
||||
$(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) $(ALT_BASE),$(@D)/.$(@F).$(base).1) >$(@D)/.$(@F).1r.S
|
||||
$(guard) $(NM) -n $(@D)/.$(@F).$(VIRT_BASE).1 | $(guard) $(BASEDIR)/tools/symbols >$(@D)/.$(@F).1s.S
|
||||
$(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o
|
||||
$(guard) $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T efi.lds -N $< \
|
||||
$(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o -o $@
|
||||
if $(guard) false; then rm -f $@; echo 'EFI support disabled'; fi
|
||||
rm -f $(@D)/.$(@F).[0-9]*
|
||||
|
||||
efi/boot.init.o efi/runtime.o efi/compat.o: $(BASEDIR)/arch/x86/efi/built_in.o
|
||||
efi/boot.init.o efi/runtime.o efi/compat.o: ;
|
||||
|
||||
asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c
|
||||
$(CC) $(filter-out -flto,$(CFLAGS)) -S -o $@ $<
|
||||
|
||||
@@ -104,11 +152,20 @@ xen.lds: xen.lds.S
|
||||
sed -e 's/xen\.lds\.o:/xen\.lds:/g' <.xen.lds.d >.xen.lds.d.new
|
||||
mv -f .xen.lds.d.new .xen.lds.d
|
||||
|
||||
efi.lds: xen.lds.S
|
||||
$(CC) -P -E -Ui386 -DEFI $(AFLAGS) -o $@ $<
|
||||
sed -e 's/efi\.lds\.o:/efi\.lds:/g' <.$(@F).d >.$(@F).d.new
|
||||
mv -f .$(@F).d.new .$(@F).d
|
||||
|
||||
boot/mkelf32: boot/mkelf32.c
|
||||
$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
|
||||
|
||||
efi/mkreloc: efi/mkreloc.c
|
||||
$(HOSTCC) $(HOSTCFLAGS) -g -o $@ $<
|
||||
|
||||
.PHONY: clean
|
||||
clean::
|
||||
rm -f asm-offsets.s xen.lds boot/*.o boot/*~ boot/core boot/mkelf32
|
||||
rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d
|
||||
rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/mkreloc
|
||||
rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
|
||||
@@ -38,6 +38,7 @@ trampoline_gdt:
|
||||
.long 0x0000ffff | ((BOOT_TRAMPOLINE & 0x00ffff) << 16)
|
||||
.long 0x00009200 | ((BOOT_TRAMPOLINE & 0xff0000) >> 16)
|
||||
|
||||
.globl cpuid_ext_features
|
||||
cpuid_ext_features:
|
||||
.long 0
|
||||
|
||||
|
||||
@@ -84,11 +84,13 @@ multiboot_ptr:
|
||||
.long 0
|
||||
|
||||
.word 0
|
||||
.globl gdt_descr
|
||||
gdt_descr:
|
||||
.word LAST_RESERVED_GDT_BYTE
|
||||
.quad boot_cpu_gdt_table - FIRST_RESERVED_GDT_BYTE
|
||||
|
||||
.word 0,0,0
|
||||
.globl idt_descr
|
||||
idt_descr:
|
||||
.word 256*16-1
|
||||
.quad idt_table
|
||||
|
||||
+64
-2
@@ -9,6 +9,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <xen/dmi.h>
|
||||
#include <xen/efi.h>
|
||||
|
||||
#define bt_ioremap(b,l) ((void *)__acpi_map_table(b,l))
|
||||
#define bt_iounmap(b,l) ((void)0)
|
||||
@@ -122,11 +123,39 @@ static inline bool_t __init dmi_checksum(const void __iomem *buf,
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
static u32 __initdata efi_dmi_address;
|
||||
static u32 __initdata efi_dmi_size;
|
||||
|
||||
/*
|
||||
* Important: This function gets called while still in EFI
|
||||
* (pseudo-)physical mode.
|
||||
*/
|
||||
void __init dmi_efi_get_table(void *smbios)
|
||||
{
|
||||
struct smbios_eps *eps = smbios;
|
||||
|
||||
if (memcmp(eps->anchor, "_SM_", 4) &&
|
||||
dmi_checksum(eps, eps->length) &&
|
||||
memcmp(eps->dmi.anchor, "_DMI_", 5) == 0 &&
|
||||
dmi_checksum(&eps->dmi, sizeof(eps->dmi))) {
|
||||
efi_dmi_address = eps->dmi.address;
|
||||
efi_dmi_size = eps->dmi.size;
|
||||
}
|
||||
}
|
||||
|
||||
int __init dmi_get_table(u32 *base, u32 *len)
|
||||
{
|
||||
struct dmi_eps eps;
|
||||
char __iomem *p, *q;
|
||||
|
||||
if (efi_enabled) {
|
||||
if (!efi_dmi_size)
|
||||
return -1;
|
||||
*base = efi_dmi_address;
|
||||
*len = efi_dmi_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = maddr_to_virt(0xF0000);
|
||||
for (q = p; q < p + 0x10000; q += 16) {
|
||||
memcpy_fromio(&eps, q, 15);
|
||||
@@ -178,6 +207,39 @@ static int __init dmi_iterate(void (*decode)(struct dmi_header *))
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __init dmi_efi_iterate(void (*decode)(struct dmi_header *))
|
||||
{
|
||||
struct smbios_eps eps;
|
||||
const struct smbios_eps __iomem *p;
|
||||
int ret = -1;
|
||||
|
||||
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
|
||||
return -1;
|
||||
|
||||
p = bt_ioremap(efi.smbios, sizeof(eps));
|
||||
if (!p)
|
||||
return -1;
|
||||
memcpy_fromio(&eps, p, sizeof(eps));
|
||||
bt_iounmap(p, sizeof(eps));
|
||||
|
||||
if (memcmp(eps.anchor, "_SM_", 4))
|
||||
return -1;
|
||||
|
||||
p = bt_ioremap(efi.smbios, eps.length);
|
||||
if (!p)
|
||||
return -1;
|
||||
if (dmi_checksum(p, eps.length) &&
|
||||
memcmp(eps.dmi.anchor, "_DMI_", 5) == 0 &&
|
||||
dmi_checksum(&eps.dmi, sizeof(eps.dmi))) {
|
||||
printk(KERN_INFO "SMBIOS %d.%d present.\n",
|
||||
eps.major, eps.minor);
|
||||
ret = _dmi_iterate(&eps.dmi, p, decode);
|
||||
}
|
||||
bt_iounmap(p, eps.length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *__initdata dmi_ident[DMI_STRING_MAX];
|
||||
|
||||
/*
|
||||
@@ -418,8 +480,8 @@ static void __init dmi_decode(struct dmi_header *dm)
|
||||
|
||||
void __init dmi_scan_machine(void)
|
||||
{
|
||||
int err = dmi_iterate(dmi_decode);
|
||||
if(err == 0)
|
||||
if ((!efi_enabled ? dmi_iterate(dmi_decode) :
|
||||
dmi_efi_iterate(dmi_decode)) == 0)
|
||||
dmi_check_system(dmi_blacklist);
|
||||
else
|
||||
printk(KERN_INFO "DMI not present.\n");
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
CFLAGS += -fshort-wchar -mno-sse
|
||||
|
||||
obj-y += stub.o
|
||||
|
||||
create = test -e $(1) || touch -t 199901010000 $(1)
|
||||
|
||||
efi := $(filter y,$(x86_64)$(shell rm -f disabled))
|
||||
efi := $(if $(efi),$(shell $(CC) -c -Werror check.c 2>disabled && echo y))
|
||||
efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 2>disabled && echo y))
|
||||
efi := $(if $(efi),$(shell rm disabled)y,$(shell $(call create,boot.init.o); $(call create,runtime.o)))
|
||||
|
||||
extra-$(efi) += boot.init.o relocs-dummy.o runtime.o compat.o
|
||||
|
||||
stub.o: $(extra-y)
|
||||
|
||||
clean::
|
||||
rm -f disabled *.efi
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,4 @@
|
||||
int __attribute__((__ms_abi__)) test(int i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <xen/guest_access.h>
|
||||
#include <compat/platform.h>
|
||||
|
||||
#define efi_get_info efi_compat_get_info
|
||||
#define xenpf_efi_info compat_pf_efi_info
|
||||
|
||||
#define COMPAT
|
||||
#undef DEFINE_XEN_GUEST_HANDLE
|
||||
#define DEFINE_XEN_GUEST_HANDLE DEFINE_COMPAT_HANDLE
|
||||
#undef guest_handle_okay
|
||||
#define guest_handle_okay compat_handle_okay
|
||||
#undef guest_handle_cast
|
||||
#define guest_handle_cast compat_handle_cast
|
||||
#undef __copy_to_guest_offset
|
||||
#define __copy_to_guest_offset __copy_to_compat_offset
|
||||
#include "runtime.c"
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <asm/efibind.h>
|
||||
#include <efi/efidef.h>
|
||||
#include <efi/efierr.h>
|
||||
#include <efi/eficon.h>
|
||||
#include <efi/efidevp.h>
|
||||
#include <efi/efiapi.h>
|
||||
#include <xen/efi.h>
|
||||
|
||||
extern unsigned int efi_num_ct;
|
||||
extern EFI_CONFIGURATION_TABLE *efi_ct;
|
||||
|
||||
extern unsigned int efi_version, efi_fw_revision;
|
||||
extern const CHAR16 *efi_fw_vendor;
|
||||
|
||||
extern EFI_RUNTIME_SERVICES *efi_rs;
|
||||
|
||||
extern UINTN efi_memmap_size, efi_mdesc_size;
|
||||
extern void *efi_memmap;
|
||||
@@ -0,0 +1,377 @@
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct mz_hdr {
|
||||
uint16_t signature;
|
||||
#define MZ_SIGNATURE 0x5a4d
|
||||
uint16_t last_page_size;
|
||||
uint16_t page_count;
|
||||
uint16_t relocation_count;
|
||||
uint16_t header_paras;
|
||||
uint16_t min_paras;
|
||||
uint16_t max_paras;
|
||||
uint16_t entry_ss;
|
||||
uint16_t entry_sp;
|
||||
uint16_t checksum;
|
||||
uint16_t entry_ip;
|
||||
uint16_t entry_cs;
|
||||
uint16_t relocations;
|
||||
uint16_t overlay;
|
||||
uint8_t reserved[32];
|
||||
uint32_t extended_header_base;
|
||||
};
|
||||
|
||||
struct pe_hdr {
|
||||
uint32_t signature;
|
||||
#define PE_SIGNATURE 0x00004550
|
||||
uint16_t cpu;
|
||||
uint16_t section_count;
|
||||
int32_t timestamp;
|
||||
uint32_t symbols_file_offset;
|
||||
uint32_t symbol_count;
|
||||
uint16_t opt_hdr_size;
|
||||
uint16_t flags;
|
||||
struct {
|
||||
uint16_t magic;
|
||||
#define PE_MAGIC_EXE32 0x010b
|
||||
#define PE_MAGIC_EXE32PLUS 0x020b
|
||||
uint8_t linker_major, linker_minor;
|
||||
uint32_t code_size, data_size, bss_size;
|
||||
uint32_t entry_rva, code_rva, data_rva;
|
||||
} opt_hdr;
|
||||
};
|
||||
|
||||
#define PE_PAGE_SIZE 0x1000
|
||||
|
||||
#define PE_BASE_RELOC_ABS 0
|
||||
#define PE_BASE_RELOC_HIGHLOW 3
|
||||
#define PE_BASE_RELOC_DIR64 10
|
||||
|
||||
struct coff_section {
|
||||
char name[8];
|
||||
uint32_t size;
|
||||
uint32_t rva;
|
||||
uint32_t file_size;
|
||||
uint32_t file_offset;
|
||||
uint32_t relocation_file_offset;
|
||||
uint32_t line_number_file_offset;
|
||||
uint16_t relocation_count;
|
||||
uint16_t line_number_count;
|
||||
uint32_t flags;
|
||||
#define COFF_SECTION_BSS 0x00000080
|
||||
#define COFF_SECTION_DISCARDABLE 0x02000000
|
||||
};
|
||||
|
||||
static void usage(const char *cmd, int rc)
|
||||
{
|
||||
fprintf(rc ? stderr : stdout,
|
||||
"Usage: %s <image1> <image2>\n",
|
||||
cmd);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
static unsigned int load(const char *name, int *handle,
|
||||
struct coff_section **sections,
|
||||
uint_fast64_t *image_base,
|
||||
uint32_t *image_size,
|
||||
unsigned int *width)
|
||||
{
|
||||
int in = open(name, O_RDONLY);
|
||||
struct mz_hdr mz_hdr;
|
||||
struct pe_hdr pe_hdr;
|
||||
uint32_t base;
|
||||
|
||||
if ( in < 0 ||
|
||||
read(in, &mz_hdr, sizeof(mz_hdr)) != sizeof(mz_hdr) )
|
||||
{
|
||||
perror(name);
|
||||
exit(2);
|
||||
}
|
||||
if ( mz_hdr.signature != MZ_SIGNATURE ||
|
||||
mz_hdr.relocations < sizeof(mz_hdr) ||
|
||||
!mz_hdr.extended_header_base )
|
||||
{
|
||||
fprintf(stderr, "%s: Wrong DOS file format\n", name);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ( lseek(in, mz_hdr.extended_header_base, SEEK_SET) < 0 ||
|
||||
read(in, &pe_hdr, sizeof(pe_hdr)) != sizeof(pe_hdr) ||
|
||||
read(in, &base, sizeof(base)) != sizeof(base) ||
|
||||
/*
|
||||
* Luckily the image size field lives at the
|
||||
* same offset for both formats.
|
||||
*/
|
||||
lseek(in, 24, SEEK_CUR) < 0 ||
|
||||
read(in, image_size, sizeof(*image_size)) != sizeof(*image_size) )
|
||||
{
|
||||
perror(name);
|
||||
exit(3);
|
||||
}
|
||||
switch ( (pe_hdr.signature == PE_SIGNATURE &&
|
||||
pe_hdr.opt_hdr_size > sizeof(pe_hdr.opt_hdr)) *
|
||||
pe_hdr.opt_hdr.magic )
|
||||
{
|
||||
case PE_MAGIC_EXE32:
|
||||
*width = 32;
|
||||
*image_base = base;
|
||||
break;
|
||||
case PE_MAGIC_EXE32PLUS:
|
||||
*width = 64;
|
||||
*image_base = ((uint64_t)base << 32) | pe_hdr.opt_hdr.data_rva;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: Wrong PE file format\n", name);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
*sections = malloc(pe_hdr.section_count * sizeof(**sections));
|
||||
if ( !*sections )
|
||||
{
|
||||
perror(NULL);
|
||||
exit(4);
|
||||
}
|
||||
if ( lseek(in,
|
||||
mz_hdr.extended_header_base + offsetof(struct pe_hdr, opt_hdr) +
|
||||
pe_hdr.opt_hdr_size,
|
||||
SEEK_SET) < 0 ||
|
||||
read(in, *sections, pe_hdr.section_count * sizeof(**sections)) !=
|
||||
pe_hdr.section_count * sizeof(**sections) )
|
||||
{
|
||||
perror(name);
|
||||
exit(4);
|
||||
}
|
||||
|
||||
*handle = in;
|
||||
|
||||
return pe_hdr.section_count;
|
||||
}
|
||||
|
||||
static long page_size;
|
||||
|
||||
static const void *map_section(const struct coff_section *sec, int in,
|
||||
const char *name)
|
||||
{
|
||||
const char *ptr;
|
||||
unsigned long offs;
|
||||
|
||||
if ( !page_size )
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
offs = sec->file_offset & (page_size - 1);
|
||||
|
||||
ptr = mmap(0, offs + sec->file_size, PROT_READ, MAP_PRIVATE, in,
|
||||
sec->file_offset - offs);
|
||||
if ( ptr == MAP_FAILED )
|
||||
{
|
||||
perror(name);
|
||||
exit(6);
|
||||
}
|
||||
|
||||
return ptr + offs;
|
||||
}
|
||||
|
||||
static void unmap_section(const void *ptr, const struct coff_section *sec)
|
||||
{
|
||||
unsigned long offs = sec->file_offset & (page_size - 1);
|
||||
|
||||
munmap((char *)ptr - offs, offs + sec->file_size);
|
||||
}
|
||||
|
||||
static void diff_sections(const unsigned char *ptr1, const unsigned char *ptr2,
|
||||
const struct coff_section *sec,
|
||||
int_fast64_t diff, unsigned int width,
|
||||
uint_fast64_t base, uint_fast64_t end)
|
||||
{
|
||||
static uint_fast32_t cur_rva, reloc_size;
|
||||
unsigned int disp = 0;
|
||||
uint_fast32_t i;
|
||||
|
||||
if ( !sec )
|
||||
{
|
||||
reloc_size += reloc_size & 2;
|
||||
if ( reloc_size )
|
||||
printf("\t.balign 4\n"
|
||||
"\t.equ rva_%08" PRIxFAST32 "_relocs, %#08" PRIxFAST32 "\n",
|
||||
cur_rva, reloc_size);
|
||||
return;
|
||||
}
|
||||
|
||||
while ( !(diff & (((int_fast64_t)1 << ((disp + 1) * CHAR_BIT)) - 1)) )
|
||||
++disp;
|
||||
|
||||
for ( i = 0; i < sec->file_size; ++i )
|
||||
{
|
||||
uint_fast32_t rva;
|
||||
union {
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
} val1, val2;
|
||||
int_fast64_t delta;
|
||||
unsigned int reloc = (width == 4 ? PE_BASE_RELOC_HIGHLOW :
|
||||
PE_BASE_RELOC_DIR64);
|
||||
|
||||
if ( ptr1[i] == ptr2[i] )
|
||||
continue;
|
||||
|
||||
if ( i < disp || i + width - disp > sec->file_size )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Bogus difference at %s:%08" PRIxFAST32 "\n",
|
||||
sec->name, i);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
memcpy(&val1, ptr1 + i - disp, width);
|
||||
memcpy(&val2, ptr2 + i - disp, width);
|
||||
delta = width == 4 ? val2.u32 - val1.u32 : val2.u64 - val1.u64;
|
||||
if ( delta != diff )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Difference at %s:%08" PRIxFAST32 " is %#" PRIxFAST64
|
||||
" (expected %#" PRIxFAST64 ")\n",
|
||||
sec->name, i, delta, diff);
|
||||
continue;
|
||||
}
|
||||
if ( width == 8 && (val1.u64 < base || val1.u64 > end) )
|
||||
reloc = PE_BASE_RELOC_HIGHLOW;
|
||||
|
||||
rva = (sec->rva + i - disp) & ~(PE_PAGE_SIZE - 1);
|
||||
if ( rva > cur_rva )
|
||||
{
|
||||
reloc_size += reloc_size & 2;
|
||||
if ( reloc_size )
|
||||
printf("\t.equ rva_%08" PRIxFAST32 "_relocs,"
|
||||
" %#08" PRIxFAST32 "\n",
|
||||
cur_rva, reloc_size);
|
||||
printf("\t.balign 4\n"
|
||||
"\t.long %#08" PRIxFAST32 ","
|
||||
" rva_%08" PRIxFAST32 "_relocs\n",
|
||||
rva, rva);
|
||||
cur_rva = rva;
|
||||
reloc_size = 8;
|
||||
}
|
||||
else if ( rva != cur_rva )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Cannot handle decreasing RVA (at %s:%08" PRIxFAST32 ")\n",
|
||||
sec->name, i);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
printf("\t.word (%u << 12) | 0x%03" PRIxFAST32 "\n",
|
||||
reloc, sec->rva + i - disp - rva);
|
||||
reloc_size += 2;
|
||||
i += width - disp - 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int in1, in2;
|
||||
unsigned int i, nsec, width1, width2;
|
||||
uint_fast64_t base1, base2;
|
||||
uint32_t size1, size2;
|
||||
struct coff_section *sec1, *sec2;
|
||||
|
||||
if ( argc == 1 ||
|
||||
!strcmp(argv[1], "-?") ||
|
||||
!strcmp(argv[1], "-h") ||
|
||||
!strcmp(argv[1], "--help") )
|
||||
usage(*argv, argc == 1);
|
||||
|
||||
if ( argc != 3 )
|
||||
usage(*argv, 1);
|
||||
|
||||
nsec = load(argv[1], &in1, &sec1, &base1, &size1, &width1);
|
||||
if ( nsec != load(argv[2], &in2, &sec2, &base2, &size2, &width2) )
|
||||
{
|
||||
fputs("Mismatched section counts\n", stderr);
|
||||
return 5;
|
||||
}
|
||||
if ( width1 != width2 )
|
||||
{
|
||||
fputs("Mismatched image types\n", stderr);
|
||||
return 5;
|
||||
}
|
||||
width1 >>= 3;
|
||||
if ( base1 == base2 )
|
||||
{
|
||||
fputs("Images must have different base addresses\n", stderr);
|
||||
return 5;
|
||||
}
|
||||
if ( size1 != size2 )
|
||||
{
|
||||
fputs("Images must have identical sizes\n", stderr);
|
||||
return 5;
|
||||
}
|
||||
|
||||
puts("\t.section .reloc, \"a\", @progbits\n"
|
||||
"\t.balign 4\n"
|
||||
"\t.globl __base_relocs_start, __base_relocs_end\n"
|
||||
"__base_relocs_start:");
|
||||
|
||||
for ( i = 0; i < nsec; ++i )
|
||||
{
|
||||
const void *ptr1, *ptr2;
|
||||
|
||||
if ( memcmp(sec1[i].name, sec2[i].name, sizeof(sec1[i].name)) ||
|
||||
sec1[i].rva != sec2[i].rva ||
|
||||
sec1[i].size != sec2[i].size ||
|
||||
sec1[i].file_size != sec2[i].file_size ||
|
||||
sec1[i].flags != sec2[i].flags )
|
||||
{
|
||||
fprintf(stderr, "Mismatched section %u parameters\n", i);
|
||||
return 5;
|
||||
}
|
||||
|
||||
if ( !sec1[i].size ||
|
||||
(sec1[i].flags & (COFF_SECTION_DISCARDABLE|COFF_SECTION_BSS)) )
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Don't generate relocations for sections that definitely
|
||||
* aren't used by the boot loader code.
|
||||
*/
|
||||
if ( memcmp(sec1[i].name, ".initcal", sizeof(sec1[i].name)) == 0 ||
|
||||
memcmp(sec1[i].name, ".init.se", sizeof(sec1[i].name)) == 0 ||
|
||||
memcmp(sec1[i].name, ".lockpro", sizeof(sec1[i].name)) == 0 )
|
||||
continue;
|
||||
|
||||
if ( !sec1[i].rva )
|
||||
{
|
||||
fprintf(stderr, "Can't handle section %u with zero RVA\n", i);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if ( sec1[i].file_size > sec1[i].size )
|
||||
{
|
||||
sec1[i].file_size = sec1[i].size;
|
||||
sec2[i].file_size = sec2[i].size;
|
||||
}
|
||||
ptr1 = map_section(sec1 + i, in1, argv[1]);
|
||||
ptr2 = map_section(sec2 + i, in2, argv[2]);
|
||||
|
||||
diff_sections(ptr1, ptr2, sec1 + i, base2 - base1, width1,
|
||||
base1, base1 + size1);
|
||||
|
||||
unmap_section(ptr1, sec1 + i);
|
||||
unmap_section(ptr2, sec2 + i);
|
||||
}
|
||||
|
||||
diff_sections(NULL, NULL, NULL, 0, 0, 0, 0);
|
||||
|
||||
puts("__base_relocs_end:");
|
||||
|
||||
close(in1);
|
||||
close(in2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <xen/config.h>
|
||||
|
||||
.section .reloc, "a", @progbits
|
||||
.balign 4
|
||||
.globl __base_relocs_start, __base_relocs_end
|
||||
__base_relocs_start:
|
||||
.long 0
|
||||
.long 8
|
||||
__base_relocs_end:
|
||||
|
||||
.globl VIRT_START, ALT_START
|
||||
.equ VIRT_START, XEN_VIRT_START
|
||||
.equ ALT_START, XEN_VIRT_END
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "efi.h"
|
||||
#include <xen/cache.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/guest_access.h>
|
||||
|
||||
DEFINE_XEN_GUEST_HANDLE(CHAR16);
|
||||
|
||||
#ifndef COMPAT
|
||||
|
||||
# include <public/platform.h>
|
||||
|
||||
const bool_t efi_enabled = 1;
|
||||
|
||||
unsigned int __read_mostly efi_num_ct;
|
||||
EFI_CONFIGURATION_TABLE *__read_mostly efi_ct;
|
||||
|
||||
unsigned int __read_mostly efi_version;
|
||||
unsigned int __read_mostly efi_fw_revision;
|
||||
const CHAR16 *__read_mostly efi_fw_vendor;
|
||||
|
||||
EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
|
||||
|
||||
UINTN __read_mostly efi_memmap_size;
|
||||
UINTN __read_mostly efi_mdesc_size;
|
||||
void *__read_mostly efi_memmap;
|
||||
|
||||
struct efi __read_mostly efi = {
|
||||
.acpi = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi20 = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios = EFI_INVALID_TABLE_ADDR,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
|
||||
{
|
||||
unsigned int i, n;
|
||||
|
||||
switch ( idx )
|
||||
{
|
||||
case XEN_FW_EFI_VERSION:
|
||||
info->version = efi_version;
|
||||
break;
|
||||
case XEN_FW_EFI_CONFIG_TABLE:
|
||||
info->cfg.addr = __pa(efi_ct);
|
||||
info->cfg.nent = efi_num_ct;
|
||||
break;
|
||||
case XEN_FW_EFI_VENDOR:
|
||||
info->vendor.revision = efi_fw_revision;
|
||||
n = info->vendor.bufsz / sizeof(*efi_fw_vendor);
|
||||
if ( !guest_handle_okay(guest_handle_cast(info->vendor.name,
|
||||
CHAR16), n) )
|
||||
return -EFAULT;
|
||||
for ( i = 0; i < n; ++i )
|
||||
{
|
||||
if ( __copy_to_guest_offset(info->vendor.name, i,
|
||||
efi_fw_vendor + i, 1) )
|
||||
return -EFAULT;
|
||||
if ( !efi_fw_vendor[i] )
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XEN_FW_EFI_MEM_INFO:
|
||||
for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
|
||||
{
|
||||
EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
|
||||
u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
|
||||
if ( info->mem.addr >= desc->PhysicalStart &&
|
||||
info->mem.addr < desc->PhysicalStart + len )
|
||||
{
|
||||
info->mem.type = desc->Type;
|
||||
info->mem.attr = desc->Attribute;
|
||||
if ( info->mem.addr + info->mem.size < info->mem.addr ||
|
||||
info->mem.addr + info->mem.size >
|
||||
desc->PhysicalStart + len )
|
||||
info->mem.size = desc->PhysicalStart + len -
|
||||
info->mem.addr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ESRCH;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <xen/efi.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/init.h>
|
||||
|
||||
#ifndef efi_enabled
|
||||
const bool_t efi_enabled = 0;
|
||||
#endif
|
||||
|
||||
void __init efi_init_memory(void) { }
|
||||
|
||||
int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *)
|
||||
__attribute__((__alias__("efi_get_info")));
|
||||
@@ -101,6 +101,7 @@
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/pfn.h>
|
||||
#include <xen/xmalloc.h>
|
||||
#include <xen/efi.h>
|
||||
#include <xen/grant_table.h>
|
||||
#include <asm/paging.h>
|
||||
#include <asm/shadow.h>
|
||||
@@ -382,6 +383,8 @@ void __init arch_init_memory(void)
|
||||
|
||||
subarch_init_memory();
|
||||
|
||||
efi_init_memory();
|
||||
|
||||
mem_sharing_init();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <xen/iocap.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/acpi.h>
|
||||
#include <xen/efi.h>
|
||||
#include <xen/cpu.h>
|
||||
#include <xen/pmstat.h>
|
||||
#include <xen/irq.h>
|
||||
@@ -290,6 +291,14 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
|
||||
bootsym(boot_edid_info), 128) )
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case XEN_FW_EFI_INFO:
|
||||
ret = efi_get_info(op->u.firmware_info.index,
|
||||
&op->u.firmware_info.u.efi_info);
|
||||
if ( ret == 0 &&
|
||||
copy_field_to_guest(u_xenpf_op, op,
|
||||
u.firmware_info.u.efi_info) )
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
||||
+27
-3
@@ -7,6 +7,7 @@
|
||||
#include <xen/serial.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/acpi.h>
|
||||
#include <xen/efi.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/serial.h>
|
||||
#include <xen/trace.h>
|
||||
@@ -444,6 +445,10 @@ static void __init parse_video_info(void)
|
||||
{
|
||||
struct boot_video_info *bvi = &bootsym(boot_vid_info);
|
||||
|
||||
/* The EFI loader fills vga_console_info directly. */
|
||||
if ( efi_enabled )
|
||||
return;
|
||||
|
||||
if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
|
||||
{
|
||||
vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
|
||||
@@ -615,6 +620,7 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
vga_console_info.u.text_mode_3.font_height);
|
||||
break;
|
||||
case XEN_VGATYPE_VESA_LFB:
|
||||
case XEN_VGATYPE_EFI_LFB:
|
||||
printk(" VGA is graphics mode %dx%d, %d bpp\n",
|
||||
vga_console_info.u.vesa_lfb.width,
|
||||
vga_console_info.u.vesa_lfb.height,
|
||||
@@ -660,7 +666,24 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) != 0 )
|
||||
EARLY_FAIL("Misaligned CPU0 stack.\n");
|
||||
|
||||
if ( e820_raw_nr != 0 )
|
||||
if ( efi_enabled )
|
||||
{
|
||||
set_pdx_range(xen_phys_start >> PAGE_SHIFT,
|
||||
(xen_phys_start + BOOTSTRAP_MAP_BASE) >> PAGE_SHIFT);
|
||||
|
||||
/* Clean up boot loader identity mappings. */
|
||||
destroy_xen_mappings(xen_phys_start,
|
||||
xen_phys_start + BOOTSTRAP_MAP_BASE);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/* Make boot page tables match non-EFI boot. */
|
||||
l3_bootmap[l3_table_offset(BOOTSTRAP_MAP_BASE)] =
|
||||
l3e_from_paddr(__pa(l2_bootmap), __PAGE_HYPERVISOR);
|
||||
#endif
|
||||
|
||||
memmap_type = loader;
|
||||
}
|
||||
else if ( e820_raw_nr != 0 )
|
||||
{
|
||||
memmap_type = "Xen-e820";
|
||||
}
|
||||
@@ -758,7 +781,7 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
* we can relocate the dom0 kernel and other multiboot modules. Also, on
|
||||
* x86/64, we relocate Xen to higher memory.
|
||||
*/
|
||||
for ( i = 0; i < mbi->mods_count; i++ )
|
||||
for ( i = 0; !efi_enabled && i < mbi->mods_count; i++ )
|
||||
{
|
||||
if ( mod[i].mod_start & (PAGE_SIZE - 1) )
|
||||
EARLY_FAIL("Bootloader didn't honor module alignment request.\n");
|
||||
@@ -946,7 +969,8 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
#else
|
||||
if ( !xen_phys_start )
|
||||
EARLY_FAIL("Not enough memory to relocate Xen.\n");
|
||||
reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end));
|
||||
reserve_e820_ram(&boot_e820, efi_enabled ? mbi->mem_upper : __pa(&_start),
|
||||
__pa(&_end));
|
||||
#endif
|
||||
|
||||
/* Late kexec reservation (dynamic start address). */
|
||||
|
||||
@@ -830,7 +830,8 @@ void __init zap_low_mappings(void)
|
||||
|
||||
/* Replace with mapping of the boot trampoline only. */
|
||||
map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
|
||||
0x10, __PAGE_HYPERVISOR);
|
||||
PFN_UP(trampoline_end - trampoline_start),
|
||||
__PAGE_HYPERVISOR);
|
||||
}
|
||||
|
||||
void *compat_arg_xlat_virt_base(void)
|
||||
|
||||
@@ -11,6 +11,8 @@ DEFINE_XEN_GUEST_HANDLE(compat_platform_op_t);
|
||||
#define xen_platform_op_t compat_platform_op_t
|
||||
#define do_platform_op(x) compat_platform_op(_##x)
|
||||
|
||||
#define efi_get_info efi_compat_get_info
|
||||
|
||||
#define xen_processor_px compat_processor_px
|
||||
#define xen_processor_px_t compat_processor_px_t
|
||||
#define xen_processor_performance compat_processor_performance
|
||||
|
||||
+40
-4
@@ -8,15 +8,34 @@
|
||||
#undef ENTRY
|
||||
#undef ALIGN
|
||||
|
||||
#ifdef EFI
|
||||
|
||||
#define FORMAT "pei-x86-64"
|
||||
#undef __XEN_VIRT_START
|
||||
#define __XEN_VIRT_START __image_base__
|
||||
|
||||
ENTRY(efi_start)
|
||||
|
||||
#else /* !EFI */
|
||||
|
||||
#ifdef __x86_64__
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
#define FORMAT "elf64-x86-64"
|
||||
#else
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
#define FORMAT "elf32-i386"
|
||||
#endif
|
||||
|
||||
ENTRY(start)
|
||||
|
||||
#endif /* EFI */
|
||||
|
||||
OUTPUT_FORMAT(FORMAT, FORMAT, FORMAT)
|
||||
|
||||
#ifdef __x86_64__
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
#else
|
||||
OUTPUT_ARCH(i386)
|
||||
#endif
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD ;
|
||||
@@ -122,12 +141,29 @@ SECTIONS
|
||||
} :text
|
||||
_end = . ;
|
||||
|
||||
#ifdef EFI
|
||||
. = ALIGN(4);
|
||||
.reloc : {
|
||||
*(.reloc)
|
||||
} :text
|
||||
/* Trick the linker into setting the image size to exactly 16Mb. */
|
||||
. = ALIGN(__section_alignment__);
|
||||
.pad : {
|
||||
. = ALIGN(0x1000000);
|
||||
} :text
|
||||
#else
|
||||
efi = .;
|
||||
#endif
|
||||
|
||||
/* Sections to be discarded */
|
||||
/DISCARD/ : {
|
||||
*(.exit.text)
|
||||
*(.exit.data)
|
||||
*(.exitcall.exit)
|
||||
*(.eh_frame)
|
||||
#ifdef EFI
|
||||
*(.comment)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
|
||||
@@ -36,9 +36,7 @@
|
||||
#include <acpi/platform/aclinux.h>
|
||||
#include <xen/spinlock.h>
|
||||
#include <xen/domain_page.h>
|
||||
#ifdef __ia64__
|
||||
#include <linux/efi.h>
|
||||
#endif
|
||||
#include <xen/efi.h>
|
||||
|
||||
#define _COMPONENT ACPI_OS_SERVICES
|
||||
ACPI_MODULE_NAME("osl")
|
||||
@@ -66,7 +64,6 @@ void __init acpi_os_vprintf(const char *fmt, va_list args)
|
||||
|
||||
acpi_physical_address __init acpi_os_get_root_pointer(void)
|
||||
{
|
||||
#ifdef __ia64__
|
||||
if (efi_enabled) {
|
||||
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
|
||||
return efi.acpi20;
|
||||
@@ -77,9 +74,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
|
||||
"System description tables not found\n");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
} else {
|
||||
acpi_physical_address pa = 0;
|
||||
|
||||
acpi_find_root_pointer(&pa);
|
||||
|
||||
@@ -87,6 +87,7 @@ void __init vga_init(void)
|
||||
vga_puts = vga_text_puts;
|
||||
break;
|
||||
case XEN_VGATYPE_VESA_LFB:
|
||||
case XEN_VGATYPE_EFI_LFB:
|
||||
vesa_early_init();
|
||||
break;
|
||||
default:
|
||||
@@ -113,6 +114,7 @@ void __init vga_endboot(void)
|
||||
memset(video, 0, columns * lines * 2);
|
||||
break;
|
||||
case XEN_VGATYPE_VESA_LFB:
|
||||
case XEN_VGATYPE_EFI_LFB:
|
||||
vesa_endboot(vgacon_keep);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -301,10 +301,14 @@ extern l2_pgentry_t idle_pg_table_l2[
|
||||
#elif CONFIG_PAGING_LEVELS == 4
|
||||
extern l2_pgentry_t *compat_idle_pg_table_l2;
|
||||
extern unsigned int m2p_compat_vstart;
|
||||
extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES],
|
||||
l2_bootmap[L2_PAGETABLE_ENTRIES];
|
||||
extern l3_pgentry_t l3_xenmap[L3_PAGETABLE_ENTRIES],
|
||||
l3_identmap[L3_PAGETABLE_ENTRIES],
|
||||
l3_bootmap[L3_PAGETABLE_ENTRIES];
|
||||
#endif
|
||||
extern l2_pgentry_t l2_identmap[4*L2_PAGETABLE_ENTRIES];
|
||||
extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES];
|
||||
extern l2_pgentry_t l2_xenmap[];
|
||||
void paging_init(void);
|
||||
void setup_idle_pagetable(void);
|
||||
#endif /* !defined(__ASSEMBLY__) */
|
||||
|
||||
@@ -118,6 +118,11 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t);
|
||||
#define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */
|
||||
#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
|
||||
#define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */
|
||||
#define XEN_FW_EFI_INFO 4 /* from EFI */
|
||||
#define XEN_FW_EFI_VERSION 0
|
||||
#define XEN_FW_EFI_CONFIG_TABLE 1
|
||||
#define XEN_FW_EFI_VENDOR 2
|
||||
#define XEN_FW_EFI_MEM_INFO 3
|
||||
struct xenpf_firmware_info {
|
||||
/* IN variables. */
|
||||
uint32_t type;
|
||||
@@ -148,6 +153,24 @@ struct xenpf_firmware_info {
|
||||
/* must refer to 128-byte buffer */
|
||||
XEN_GUEST_HANDLE(uint8) edid;
|
||||
} vbeddc_info; /* XEN_FW_VBEDDC_INFO */
|
||||
union xenpf_efi_info {
|
||||
uint32_t version;
|
||||
struct {
|
||||
uint64_t addr; /* EFI_CONFIGURATION_TABLE */
|
||||
uint32_t nent;
|
||||
} cfg;
|
||||
struct {
|
||||
uint32_t revision;
|
||||
uint32_t bufsz; /* input, in bytes */
|
||||
XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
|
||||
} vendor;
|
||||
struct {
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
uint64_t attr;
|
||||
uint32_t type;
|
||||
} mem;
|
||||
} efi_info; /* XEN_FW_EFI_INFO */
|
||||
} u;
|
||||
};
|
||||
typedef struct xenpf_firmware_info xenpf_firmware_info_t;
|
||||
|
||||
@@ -638,6 +638,7 @@ typedef struct dom0_vga_console_info {
|
||||
uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
|
||||
#define XEN_VGATYPE_TEXT_MODE_3 0x03
|
||||
#define XEN_VGATYPE_VESA_LFB 0x23
|
||||
#define XEN_VGATYPE_EFI_LFB 0x70
|
||||
|
||||
union {
|
||||
struct {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
/* Cast a compat handle to the specified type of handle. */
|
||||
#define compat_handle_cast(chnd, type) ({ \
|
||||
type *_x = (__typeof__(**(chnd)._) *)(full_ptr_t)(chnd).c; \
|
||||
(XEN_GUEST_HANDLE(type)) { _x }; \
|
||||
(COMPAT_HANDLE(type)) { (full_ptr_t)_x }; \
|
||||
})
|
||||
|
||||
#define guest_from_compat_handle(ghnd, chnd) \
|
||||
|
||||
@@ -35,6 +35,7 @@ struct dmi_system_id {
|
||||
extern int dmi_check_system(struct dmi_system_id *list);
|
||||
extern void dmi_scan_machine(void);
|
||||
extern int dmi_get_table(u32 *base, u32 *len);
|
||||
extern void dmi_efi_get_table(void *);
|
||||
extern void dmi_end_boot(void);
|
||||
|
||||
#endif /* __DMI_H__ */
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef __XEN_EFI_H__
|
||||
#define __XEN_EFI_H__
|
||||
|
||||
#include <xen/types.h>
|
||||
|
||||
#if defined(__ia64__)
|
||||
# #include <linux/efi.h>
|
||||
#else
|
||||
|
||||
# if defined(__i386__)
|
||||
# define efi_enabled 0
|
||||
# else
|
||||
extern const bool_t efi_enabled;
|
||||
# endif
|
||||
|
||||
#define EFI_INVALID_TABLE_ADDR (~0UL)
|
||||
|
||||
/* Add fields here only if they need to be referenced from non-EFI code. */
|
||||
struct efi {
|
||||
unsigned long acpi; /* ACPI table (IA64 ext 0.71) */
|
||||
unsigned long acpi20; /* ACPI table (ACPI 2.0) */
|
||||
unsigned long smbios; /* SM BIOS table */
|
||||
};
|
||||
|
||||
extern struct efi efi;
|
||||
|
||||
#endif
|
||||
|
||||
union xenpf_efi_info;
|
||||
union compat_pf_efi_info;
|
||||
|
||||
void efi_init_memory(void);
|
||||
#ifndef COMPAT
|
||||
int efi_get_info(uint32_t idx, union xenpf_efi_info *);
|
||||
#endif
|
||||
int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *);
|
||||
|
||||
#endif /* __XEN_EFI_H__ */
|
||||