@@ -18,16 +18,6 @@
#include <xen/string.h>
#include <xen/stringify.h>
#include <xen/vga.h>
-#include <asm/e820.h>
-#include <asm/edd.h>
-#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
-#include <asm/fixmap.h>
-#undef __ASSEMBLY__
-#include <asm/msr.h>
-#include <asm/processor.h>
-
-/* Using SetVirtualAddressMap() is incompatible with kexec: */
-#undef USE_SET_VIRTUAL_ADDRESS_MAP
#define SHIM_LOCK_PROTOCOL_GUID \
{ 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
@@ -41,8 +31,10 @@ typedef struct {
EFI_SHIM_LOCK_VERIFY Verify;
} EFI_SHIM_LOCK_PROTOCOL;
-extern char start[];
-extern u32 cpuid_ext_features;
+static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer);
+static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
+static void __init DisplayUint(UINT64 Val, INTN Width);
+static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s);
union string {
CHAR16 *w;
@@ -69,19 +61,18 @@ static UINT32 __initdata mdesc_ver;
static struct file __initdata cfg;
static struct file __initdata kernel;
static struct file __initdata ramdisk;
-static struct file __initdata ucode;
static struct file __initdata xsm;
-
-static multiboot_info_t __initdata mbi = {
- .flags = MBI_MODULES | MBI_LOADERNAME
-};
-static module_t __initdata mb_modules[3];
-
static CHAR16 __initdata newline[] = L"\r\n";
#define PrintStr(s) StdOut->OutputString(StdOut, s)
#define PrintErr(s) StdErr->OutputString(StdErr, s)
+/*
+ * Include architecture specific implementation here, which references the
+ * static globals defined above.
+ */
+#include <asm/efi-boot.h>
+
static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer)
{
if ( Val >= 10 )
@@ -255,32 +246,6 @@ static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
blexit(mesg);
}
-static void __init place_string(u32 *addr, const char *s)
-{
- static char *__initdata alloc = start;
-
- if ( s && *s )
- {
- size_t len1 = strlen(s) + 1;
- const char *old = (char *)(long)*addr;
- size_t len2 = *addr ? strlen(old) + 1 : 0;
-
- alloc -= len1 + len2;
- /*
- * Insert new string before already existing one. This is needed
- * for options passed on the command line to override options from
- * the configuration file.
- */
- memcpy(alloc, s, len1);
- if ( *addr )
- {
- alloc[len1 - 1] = ' ';
- memcpy(alloc + len1, old, len2);
- }
- }
- *addr = (long)alloc;
-}
-
static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
CHAR16 *cmdline, UINTN cmdsize)
{
@@ -574,104 +539,6 @@ static void __init split_value(char *s)
*s = 0;
}
-static void __init edd_put_string(u8 *dst, size_t n, const char *src)
-{
- while ( n-- && *src )
- *dst++ = *src++;
- if ( *src )
- PrintErrMesg(L"Internal error populating EDD info",
- EFI_BUFFER_TOO_SMALL);
- while ( n-- )
- *dst++ = ' ';
-}
-#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
-
-static void __init setup_efi_pci(void)
-{
- EFI_STATUS status;
- EFI_HANDLE *handles;
- static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
- UINTN i, nr_pci, size = 0;
- struct efi_pci_rom *last = NULL;
-
- status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
- if ( status == EFI_BUFFER_TOO_SMALL )
- status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
- if ( !EFI_ERROR(status) )
- status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size,
- handles);
- if ( EFI_ERROR(status) )
- size = 0;
-
- nr_pci = size / sizeof(*handles);
- for ( i = 0; i < nr_pci; ++i )
- {
- EFI_PCI_IO *pci = NULL;
- u64 attributes;
- struct efi_pci_rom *rom, *va;
- UINTN segment, bus, device, function;
-
- status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
- if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
- continue;
-
- status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
- &attributes);
- if ( EFI_ERROR(status) ||
- !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
- EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
- &function)) )
- continue;
-
- DisplayUint(segment, 4);
- PrintStr(L":");
- DisplayUint(bus, 2);
- PrintStr(L":");
- DisplayUint(device, 2);
- PrintStr(L".");
- DisplayUint(function, 1);
- PrintStr(L": ROM: ");
- DisplayUint(pci->RomSize, 0);
- PrintStr(L" bytes at ");
- DisplayUint((UINTN)pci->RomImage, 0);
- PrintStr(newline);
-
- size = pci->RomSize + sizeof(*rom);
- status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
- (void **)&rom);
- if ( EFI_ERROR(status) )
- continue;
-
- rom->next = NULL;
- rom->size = pci->RomSize;
-
- status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
- &rom->vendor);
- if ( !EFI_ERROR(status) )
- status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
- &rom->devid);
- if ( EFI_ERROR(status) )
- {
- efi_bs->FreePool(rom);
- continue;
- }
-
- rom->segment = segment;
- rom->bus = bus;
- rom->devfn = (device << 3) | function;
- memcpy(rom->data, pci->RomImage, pci->RomSize);
-
- va = (void *)rom + DIRECTMAP_VIRT_START;
- if ( last )
- last->next = va;
- else
- efi_pci_roms = va;
- last = rom;
- }
-
- efi_bs->FreePool(handles);
-}
-
static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
{
if ( bpp < 0 )
@@ -687,82 +554,6 @@ static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
return max(*pos + *sz, bpp);
}
-extern const intpte_t __page_tables_start[], __page_tables_end[];
-#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
- (intpte_t *)(v) < __page_tables_end)
-
-#define PE_BASE_RELOC_ABS 0
-#define PE_BASE_RELOC_HIGHLOW 3
-#define PE_BASE_RELOC_DIR64 10
-
-extern const struct pe_base_relocs {
- u32 rva;
- u32 size;
- u16 entries[];
-} __base_relocs_start[], __base_relocs_end[];
-
-static void __init relocate_image(unsigned long delta)
-{
- const struct pe_base_relocs *base_relocs;
-
- for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
- {
- unsigned int i, n;
-
- n = (base_relocs->size - sizeof(*base_relocs)) /
- sizeof(*base_relocs->entries);
- for ( i = 0; i < n; ++i )
- {
- unsigned long addr = xen_phys_start + base_relocs->rva +
- (base_relocs->entries[i] & 0xfff);
-
- switch ( base_relocs->entries[i] >> 12 )
- {
- case PE_BASE_RELOC_ABS:
- break;
- case PE_BASE_RELOC_HIGHLOW:
- if ( delta )
- {
- *(u32 *)addr += delta;
- if ( in_page_tables(addr) )
- *(u32 *)addr += xen_phys_start;
- }
- break;
- case PE_BASE_RELOC_DIR64:
- if ( delta )
- {
- *(u64 *)addr += delta;
- if ( in_page_tables(addr) )
- *(intpte_t *)addr += xen_phys_start;
- }
- break;
- default:
- blexit(L"Unsupported relocation type");
- }
- }
- base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
- }
-}
-
-extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
-extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
-
-static void __init relocate_trampoline(unsigned long phys)
-{
- const s32 *trampoline_ptr;
-
- trampoline_phys = phys;
- /* Apply relocations to trampoline. */
- for ( trampoline_ptr = __trampoline_rel_start;
- trampoline_ptr < __trampoline_rel_stop;
- ++trampoline_ptr )
- *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
- for ( trampoline_ptr = __trampoline_seg_start;
- trampoline_ptr < __trampoline_seg_stop;
- ++trampoline_ptr )
- *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
-}
-
void EFIAPI __init noreturn
efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
@@ -879,7 +670,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
- relocate_image(0);
+ efi_arch_relocate_image(0);
if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
&cols, &rows) == EFI_SUCCESS )
@@ -1258,7 +1049,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
dmi_efi_get_table((void *)(long)efi.smbios);
/* Collect PCI ROM contents. */
- setup_efi_pci();
+ efi_arch_pci();
/* Get snapshot of variable store parameters. */
status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
@@ -1460,7 +1251,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
- relocate_image(__XEN_VIRT_START - xen_phys_start);
+ efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
/* Set system registers and transfer control. */
@@ -1496,228 +1287,3 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
for( ; ; ); /* not reached */
}
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-static __init void copy_mapping(unsigned long mfn, unsigned long end,
- bool_t (*is_valid)(unsigned long smfn,
- unsigned long emfn))
-{
- unsigned long next;
-
- for ( ; mfn < end; mfn = next )
- {
- l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
- l3_pgentry_t *l3src, *l3dst;
- unsigned long va = (unsigned long)mfn_to_virt(mfn);
-
- next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
- if ( !is_valid(mfn, min(next, end)) )
- continue;
- if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
- {
- l3dst = alloc_xen_pagetable();
- BUG_ON(!l3dst);
- clear_page(l3dst);
- efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
- l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
- }
- else
- l3dst = l4e_to_l3e(l4e);
- l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
- l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
- }
-}
-
-static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
-{
- unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
-
- return !(smfn & pfn_hole_mask) &&
- find_next_bit(pdx_group_valid, sz,
- pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
-}
-
-static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
-{
- return 1;
-}
-#endif
-
-#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
- (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
-
-void __init efi_init_memory(void)
-{
- unsigned int i;
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
- struct rt_extra {
- struct rt_extra *next;
- unsigned long smfn, emfn;
- unsigned int prot;
- } *extra, *extra_head = NULL;
-#endif
-
- printk(XENLOG_INFO "EFI memory map:\n");
- 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;
- unsigned long smfn, emfn;
- unsigned int prot = PAGE_HYPERVISOR;
-
- printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
- " type=%u attr=%016" PRIx64 "\n",
- desc->PhysicalStart, desc->PhysicalStart + len - 1,
- desc->Type, desc->Attribute);
-
- if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
- continue;
-
- desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
-
- smfn = PFN_DOWN(desc->PhysicalStart);
- emfn = PFN_UP(desc->PhysicalStart + len);
-
- if ( desc->Attribute & EFI_MEMORY_WB )
- /* nothing */;
- else if ( desc->Attribute & EFI_MEMORY_WT )
- prot |= _PAGE_PWT | MAP_SMALL_PAGES;
- else if ( desc->Attribute & EFI_MEMORY_WC )
- prot |= _PAGE_PAT | MAP_SMALL_PAGES;
- else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
- prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
- else
- {
- printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
- smfn, emfn - 1);
- continue;
- }
-
- if ( desc->Attribute & EFI_MEMORY_WP )
- prot &= _PAGE_RW;
- if ( desc->Attribute & EFI_MEMORY_XP )
- prot |= _PAGE_NX_BIT;
-
- if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
- !(smfn & pfn_hole_mask) &&
- !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
- {
- if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
- prot &= ~_PAGE_GLOBAL;
- if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
- smfn, emfn - smfn, prot) == 0 )
- desc->VirtualStart =
- (unsigned long)maddr_to_virt(desc->PhysicalStart);
- else
- printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
- smfn, emfn - 1);
- }
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
- else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
- (extra = xmalloc(struct rt_extra)) != NULL )
- {
- extra->smfn = smfn;
- extra->emfn = emfn;
- extra->prot = prot & ~_PAGE_GLOBAL;
- extra->next = extra_head;
- extra_head = extra;
- desc->VirtualStart = desc->PhysicalStart;
- }
-#endif
- else
- {
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
- /* XXX allocate e.g. down from FIXADDR_START */
-#endif
- printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
- smfn, emfn - 1);
- }
- }
-
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
- efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
- mdesc_ver, efi_memmap);
-#else
- /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
- efi_l4_pgtable = alloc_xen_pagetable();
- BUG_ON(!efi_l4_pgtable);
- clear_page(efi_l4_pgtable);
-
- copy_mapping(0, max_page, ram_range_valid);
-
- /* Insert non-RAM runtime mappings inside the direct map. */
- for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
- {
- const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-
- if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
- desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
- desc->VirtualStart != desc->PhysicalStart )
- copy_mapping(PFN_DOWN(desc->PhysicalStart),
- PFN_UP(desc->PhysicalStart +
- (desc->NumberOfPages << EFI_PAGE_SHIFT)),
- rt_range_valid);
- }
-
- /* Insert non-RAM runtime mappings outside of the direct map. */
- while ( (extra = extra_head) != NULL )
- {
- unsigned long addr = extra->smfn << PAGE_SHIFT;
- l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
- l3_pgentry_t *pl3e;
- l2_pgentry_t *pl2e;
- l1_pgentry_t *l1t;
-
- if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
- {
- pl3e = alloc_xen_pagetable();
- BUG_ON(!pl3e);
- clear_page(pl3e);
- efi_l4_pgtable[l4_table_offset(addr)] =
- l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
- }
- else
- pl3e = l4e_to_l3e(l4e);
- pl3e += l3_table_offset(addr);
- if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
- {
- pl2e = alloc_xen_pagetable();
- BUG_ON(!pl2e);
- clear_page(pl2e);
- *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
- }
- else
- {
- BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
- pl2e = l3e_to_l2e(*pl3e);
- }
- pl2e += l2_table_offset(addr);
- if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
- {
- l1t = alloc_xen_pagetable();
- BUG_ON(!l1t);
- clear_page(l1t);
- *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
- }
- else
- {
- BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
- l1t = l2e_to_l1e(*pl2e);
- }
- for ( i = l1_table_offset(addr);
- i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
- ++i, ++extra->smfn )
- l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
-
- if ( extra->smfn == extra->emfn )
- {
- extra_head = extra->next;
- xfree(extra);
- }
- }
-
- /* Insert Xen mappings. */
- for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
- i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
- efi_l4_pgtable[i] = idle_pg_table[i];
-#endif
-}
new file mode 100644
@@ -0,0 +1,451 @@
+/*
+ * Architecture specific implementation for EFI boot code. This file
+ * is intended to be included by XXX _only_, and therefore can define
+ * arch specific global variables.
+ */
+#include <asm/e820.h>
+#include <asm/edd.h>
+#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
+#include <asm/fixmap.h>
+#undef __ASSEMBLY__
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+static struct file __initdata ucode;
+static multiboot_info_t __initdata mbi = {
+ .flags = MBI_MODULES | MBI_LOADERNAME
+};
+static module_t __initdata mb_modules[3];
+
+static void noreturn blexit(const CHAR16 *str);
+static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
+
+/* Using SetVirtualAddressMap() is incompatible with kexec: */
+#undef USE_SET_VIRTUAL_ADDRESS_MAP
+extern char start[];
+extern u32 cpuid_ext_features;
+
+static void __init edd_put_string(u8 *dst, size_t n, const char *src)
+{
+ while ( n-- && *src )
+ *dst++ = *src++;
+ if ( *src )
+ PrintErrMesg(L"Internal error populating EDD info",
+ EFI_BUFFER_TOO_SMALL);
+ while ( n-- )
+ *dst++ = ' ';
+}
+#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
+
+static void __init efi_arch_pci(void)
+{
+ EFI_STATUS status;
+ EFI_HANDLE *handles;
+ static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
+ UINTN i, nr_pci, size = 0;
+ struct efi_pci_rom *last = NULL;
+
+ status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
+ if ( status == EFI_BUFFER_TOO_SMALL )
+ status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+ if ( !EFI_ERROR(status) )
+ status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size,
+ handles);
+ if ( EFI_ERROR(status) )
+ size = 0;
+
+ nr_pci = size / sizeof(*handles);
+ for ( i = 0; i < nr_pci; ++i )
+ {
+ EFI_PCI_IO *pci = NULL;
+ u64 attributes;
+ struct efi_pci_rom *rom, *va;
+ UINTN segment, bus, device, function;
+
+ status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
+ if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
+ continue;
+
+ status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
+ &attributes);
+ if ( EFI_ERROR(status) ||
+ !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
+ EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
+ &function)) )
+ continue;
+
+ DisplayUint(segment, 4);
+ PrintStr(L":");
+ DisplayUint(bus, 2);
+ PrintStr(L":");
+ DisplayUint(device, 2);
+ PrintStr(L".");
+ DisplayUint(function, 1);
+ PrintStr(L": ROM: ");
+ DisplayUint(pci->RomSize, 0);
+ PrintStr(L" bytes at ");
+ DisplayUint((UINTN)pci->RomImage, 0);
+ PrintStr(newline);
+
+ size = pci->RomSize + sizeof(*rom);
+ status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
+ (void **)&rom);
+ if ( EFI_ERROR(status) )
+ continue;
+
+ rom->next = NULL;
+ rom->size = pci->RomSize;
+
+ status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
+ &rom->vendor);
+ if ( !EFI_ERROR(status) )
+ status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
+ &rom->devid);
+ if ( EFI_ERROR(status) )
+ {
+ efi_bs->FreePool(rom);
+ continue;
+ }
+
+ rom->segment = segment;
+ rom->bus = bus;
+ rom->devfn = (device << 3) | function;
+ memcpy(rom->data, pci->RomImage, pci->RomSize);
+
+ va = (void *)rom + DIRECTMAP_VIRT_START;
+ if ( last )
+ last->next = va;
+ else
+ efi_pci_roms = va;
+ last = rom;
+ }
+
+ efi_bs->FreePool(handles);
+}
+
+extern const intpte_t __page_tables_start[], __page_tables_end[];
+#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
+ (intpte_t *)(v) < __page_tables_end)
+
+#define PE_BASE_RELOC_ABS 0
+#define PE_BASE_RELOC_HIGHLOW 3
+#define PE_BASE_RELOC_DIR64 10
+
+extern const struct pe_base_relocs {
+ u32 rva;
+ u32 size;
+ u16 entries[];
+} __base_relocs_start[], __base_relocs_end[];
+
+static void __init efi_arch_relocate_image(unsigned long delta)
+{
+ const struct pe_base_relocs *base_relocs;
+
+ for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
+ {
+ unsigned int i, n;
+
+ n = (base_relocs->size - sizeof(*base_relocs)) /
+ sizeof(*base_relocs->entries);
+ for ( i = 0; i < n; ++i )
+ {
+ unsigned long addr = xen_phys_start + base_relocs->rva +
+ (base_relocs->entries[i] & 0xfff);
+
+ switch ( base_relocs->entries[i] >> 12 )
+ {
+ case PE_BASE_RELOC_ABS:
+ break;
+ case PE_BASE_RELOC_HIGHLOW:
+ if ( delta )
+ {
+ *(u32 *)addr += delta;
+ if ( in_page_tables(addr) )
+ *(u32 *)addr += xen_phys_start;
+ }
+ break;
+ case PE_BASE_RELOC_DIR64:
+ if ( delta )
+ {
+ *(u64 *)addr += delta;
+ if ( in_page_tables(addr) )
+ *(intpte_t *)addr += xen_phys_start;
+ }
+ break;
+ default:
+ blexit(L"Unsupported relocation type");
+ }
+ }
+ base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
+ }
+}
+
+extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
+extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
+
+static void __init relocate_trampoline(unsigned long phys)
+{
+ const s32 *trampoline_ptr;
+
+ trampoline_phys = phys;
+ /* Apply relocations to trampoline. */
+ for ( trampoline_ptr = __trampoline_rel_start;
+ trampoline_ptr < __trampoline_rel_stop;
+ ++trampoline_ptr )
+ *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
+ for ( trampoline_ptr = __trampoline_seg_start;
+ trampoline_ptr < __trampoline_seg_stop;
+ ++trampoline_ptr )
+ *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
+}
+
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+static __init void copy_mapping(unsigned long mfn, unsigned long end,
+ bool_t (*is_valid)(unsigned long smfn,
+ unsigned long emfn))
+{
+ unsigned long next;
+
+ for ( ; mfn < end; mfn = next )
+ {
+ l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
+ l3_pgentry_t *l3src, *l3dst;
+ unsigned long va = (unsigned long)mfn_to_virt(mfn);
+
+ next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
+ if ( !is_valid(mfn, min(next, end)) )
+ continue;
+ if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+ {
+ l3dst = alloc_xen_pagetable();
+ BUG_ON(!l3dst);
+ clear_page(l3dst);
+ efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
+ l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
+ }
+ else
+ l3dst = l4e_to_l3e(l4e);
+ l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
+ l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
+ }
+}
+
+static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
+{
+ unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
+
+ return !(smfn & pfn_hole_mask) &&
+ find_next_bit(pdx_group_valid, sz,
+ pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
+}
+
+static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
+{
+ return 1;
+}
+#endif
+
+#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
+ (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
+void __init efi_init_memory(void)
+{
+ unsigned int i;
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+ struct rt_extra {
+ struct rt_extra *next;
+ unsigned long smfn, emfn;
+ unsigned int prot;
+ } *extra, *extra_head = NULL;
+#endif
+
+ printk(XENLOG_INFO "EFI memory map:\n");
+ 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;
+ unsigned long smfn, emfn;
+ unsigned int prot = PAGE_HYPERVISOR;
+
+ printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
+ " type=%u attr=%016" PRIx64 "\n",
+ desc->PhysicalStart, desc->PhysicalStart + len - 1,
+ desc->Type, desc->Attribute);
+
+ if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
+ continue;
+
+ desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
+
+ smfn = PFN_DOWN(desc->PhysicalStart);
+ emfn = PFN_UP(desc->PhysicalStart + len);
+
+ if ( desc->Attribute & EFI_MEMORY_WB )
+ /* nothing */;
+ else if ( desc->Attribute & EFI_MEMORY_WT )
+ prot |= _PAGE_PWT | MAP_SMALL_PAGES;
+ else if ( desc->Attribute & EFI_MEMORY_WC )
+ prot |= _PAGE_PAT | MAP_SMALL_PAGES;
+ else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
+ prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
+ else
+ {
+ printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
+ smfn, emfn - 1);
+ continue;
+ }
+
+ if ( desc->Attribute & EFI_MEMORY_WP )
+ prot &= _PAGE_RW;
+ if ( desc->Attribute & EFI_MEMORY_XP )
+ prot |= _PAGE_NX_BIT;
+
+ if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
+ !(smfn & pfn_hole_mask) &&
+ !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
+ {
+ if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
+ prot &= ~_PAGE_GLOBAL;
+ if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
+ smfn, emfn - smfn, prot) == 0 )
+ desc->VirtualStart =
+ (unsigned long)maddr_to_virt(desc->PhysicalStart);
+ else
+ printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
+ smfn, emfn - 1);
+ }
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+ else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
+ (extra = xmalloc(struct rt_extra)) != NULL )
+ {
+ extra->smfn = smfn;
+ extra->emfn = emfn;
+ extra->prot = prot & ~_PAGE_GLOBAL;
+ extra->next = extra_head;
+ extra_head = extra;
+ desc->VirtualStart = desc->PhysicalStart;
+ }
+#endif
+ else
+ {
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+ /* XXX allocate e.g. down from FIXADDR_START */
+#endif
+ printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
+ smfn, emfn - 1);
+ }
+ }
+
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+ efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
+ mdesc_ver, efi_memmap);
+#else
+ /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
+ efi_l4_pgtable = alloc_xen_pagetable();
+ BUG_ON(!efi_l4_pgtable);
+ clear_page(efi_l4_pgtable);
+
+ copy_mapping(0, max_page, ram_range_valid);
+
+ /* Insert non-RAM runtime mappings inside the direct map. */
+ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+ {
+ const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+
+ if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
+ desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
+ desc->VirtualStart != desc->PhysicalStart )
+ copy_mapping(PFN_DOWN(desc->PhysicalStart),
+ PFN_UP(desc->PhysicalStart +
+ (desc->NumberOfPages << EFI_PAGE_SHIFT)),
+ rt_range_valid);
+ }
+
+ /* Insert non-RAM runtime mappings outside of the direct map. */
+ while ( (extra = extra_head) != NULL )
+ {
+ unsigned long addr = extra->smfn << PAGE_SHIFT;
+ l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
+ l3_pgentry_t *pl3e;
+ l2_pgentry_t *pl2e;
+ l1_pgentry_t *l1t;
+
+ if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+ {
+ pl3e = alloc_xen_pagetable();
+ BUG_ON(!pl3e);
+ clear_page(pl3e);
+ efi_l4_pgtable[l4_table_offset(addr)] =
+ l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
+ }
+ else
+ pl3e = l4e_to_l3e(l4e);
+ pl3e += l3_table_offset(addr);
+ if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
+ {
+ pl2e = alloc_xen_pagetable();
+ BUG_ON(!pl2e);
+ clear_page(pl2e);
+ *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
+ }
+ else
+ {
+ BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
+ pl2e = l3e_to_l2e(*pl3e);
+ }
+ pl2e += l2_table_offset(addr);
+ if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
+ {
+ l1t = alloc_xen_pagetable();
+ BUG_ON(!l1t);
+ clear_page(l1t);
+ *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
+ }
+ else
+ {
+ BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
+ l1t = l2e_to_l1e(*pl2e);
+ }
+ for ( i = l1_table_offset(addr);
+ i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
+ ++i, ++extra->smfn )
+ l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
+
+ if ( extra->smfn == extra->emfn )
+ {
+ extra_head = extra->next;
+ xfree(extra);
+ }
+ }
+
+ /* Insert Xen mappings. */
+ for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
+ i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
+ efi_l4_pgtable[i] = idle_pg_table[i];
+#endif
+}
+
+static void __init place_string(u32 *addr, const char *s)
+{
+ static char *__initdata alloc = start;
+
+ if ( s && *s )
+ {
+ size_t len1 = strlen(s) + 1;
+ const char *old = (char *)(long)*addr;
+ size_t len2 = *addr ? strlen(old) + 1 : 0;
+
+ alloc -= len1 + len2;
+ /*
+ * Insert new string before already existing one. This is needed
+ * for options passed on the command line to override options from
+ * the configuration file.
+ */
+ memcpy(alloc, s, len1);
+ if ( *addr )
+ {
+ alloc[len1 - 1] = ' ';
+ memcpy(alloc + len1, old, len2);
+ }
+ }
+ *addr = (long)alloc;
+}
Move the global variables and functions that can be moved as-is from the common boot.c file to the x86 implementation header file. Signed-off-by: Roy Franz <roy.franz@linaro.org> --- xen/common/efi/boot.c | 460 ++--------------------------------------- xen/include/asm-x86/efi-boot.h | 451 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 464 insertions(+), 447 deletions(-) create mode 100644 xen/include/asm-x86/efi-boot.h