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:
Jan Beulich committed 2011-06-28 09:19:35 +01:00
1 parent f402de45cd
commit bf6501a62e
29 files changed
+2065 -24

No files matched your search

+9
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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");
+17
View File
@@ -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
+4
View File
@@ -0,0 +1,4 @@
int __attribute__((__ms_abi__)) test(int i)
{
return i;
}
+16
View File
@@ -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"
+18
View File
@@ -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;
+377
View File
@@ -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;
}
+13
View File
@@ -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
+88
View File
@@ -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;
}
+17
View File
@@ -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")));
+3
View File
@@ -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();
}
+9
View File
@@ -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
View File
@@ -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). */
+2 -1
View File
@@ -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)
+2
View File
@@ -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
View File
@@ -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. */
+2 -7
View File
@@ -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);
+2
View File
@@ -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:
+5 -1
View File
@@ -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__) */
+23
View File
@@ -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;
+1
View File
@@ -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 {
+1 -1
View File
@@ -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) \
+1
View File
@@ -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__ */
+38
View File
@@ -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__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.