diff options
Diffstat (limited to 'sys/boot/ia64/efi')
-rw-r--r-- | sys/boot/ia64/efi/conf.c | 11 | ||||
-rw-r--r-- | sys/boot/ia64/efi/efimd.c | 188 | ||||
-rw-r--r-- | sys/boot/ia64/efi/version | 1 |
3 files changed, 139 insertions, 61 deletions
diff --git a/sys/boot/ia64/efi/conf.c b/sys/boot/ia64/efi/conf.c index 69d0927..0e0d129 100644 --- a/sys/boot/ia64/efi/conf.c +++ b/sys/boot/ia64/efi/conf.c @@ -69,17 +69,6 @@ struct netif_driver *netif_drivers[] = { }; /* - * Sort formats so that those that can detect based on arguments - * rather than reading the file go first. - */ -extern struct file_format ia64_elf; - -struct file_format *file_formats[] = { - &ia64_elf, - NULL -}; - -/* * Consoles * * We don't prototype these in efiboot.h because they require diff --git a/sys/boot/ia64/efi/efimd.c b/sys/boot/ia64/efi/efimd.c index 8a1e0c7..7454117 100644 --- a/sys/boot/ia64/efi/efimd.c +++ b/sys/boot/ia64/efi/efimd.c @@ -45,26 +45,147 @@ static EFI_GUID fpswa_guid = EFI_INTEL_FPSWA; static EFI_GUID hcdp_guid = HCDP_TABLE_GUID; +static EFI_MEMORY_DESCRIPTOR *memmap; +static UINTN memmapsz; static UINTN mapkey; +static UINTN descsz; +static UINT32 descver; -uint64_t -ldr_alloc(vm_offset_t va) +#define IA64_EFI_CHUNK_SIZE (32 * 1048576) +static vm_paddr_t ia64_efi_chunk; + +#define IA64_EFI_PGTBLSZ_MAX 1048576 +static vm_paddr_t ia64_efi_pgtbl; +static vm_size_t ia64_efi_pgtblsz; + +/* Don't allocate memory below the boundary */ +#define IA64_EFI_ALLOC_BOUNDARY 1048576 + +static int +ia64_efi_memmap_update(void) +{ + EFI_STATUS status; + + if (memmap != NULL) { + free(memmap); + memmap = NULL; + } + + memmapsz = 0; + BS->GetMemoryMap(&memmapsz, NULL, &mapkey, &descsz, &descver); + if (memmapsz == 0) + return (FALSE); + memmap = malloc(memmapsz); + if (memmap == NULL) + return (FALSE); + + status = BS->GetMemoryMap(&memmapsz, memmap, &mapkey, &descsz, + &descver); + if (EFI_ERROR(status)) { + free(memmap); + memmap = NULL; + return (FALSE); + } + + return (TRUE); +} + +static vm_paddr_t +ia64_efi_alloc(vm_size_t sz) { + EFI_PHYSICAL_ADDRESS pa; + EFI_MEMORY_DESCRIPTOR *mm; + uint8_t *mmiter, *mmiterend; + vm_size_t memsz; + UINTN npgs; + EFI_STATUS status; + + /* We can't allocate less than a page */ + if (sz < EFI_PAGE_SIZE) + return (0); + + /* The size must be a power of 2. */ + if (sz & (sz - 1)) + return (0); + + if (!ia64_efi_memmap_update()) + return (0); + + mmiter = (void *)memmap; + mmiterend = mmiter + memmapsz; + for (; mmiter < mmiterend; mmiter += descsz) { + mm = (void *)mmiter; + if (mm->Type != EfiConventionalMemory) + continue; + memsz = mm->NumberOfPages * EFI_PAGE_SIZE; + if (mm->PhysicalStart + memsz <= IA64_EFI_ALLOC_BOUNDARY) + continue; + /* + * XXX We really should make sure the memory is local to the + * BSP. + */ + pa = (mm->PhysicalStart < IA64_EFI_ALLOC_BOUNDARY) ? + IA64_EFI_ALLOC_BOUNDARY : mm->PhysicalStart; + pa = (pa + sz - 1) & ~(sz - 1); + if (pa + sz > mm->PhysicalStart + memsz) + continue; + + npgs = EFI_SIZE_TO_PAGES(sz); + status = BS->AllocatePages(AllocateAddress, EfiLoaderData, + npgs, &pa); + if (!EFI_ERROR(status)) + return (pa); + } + printf("%s: unable to allocate %lx bytes\n", __func__, sz); return (0); } +vm_paddr_t +ia64_platform_alloc(vm_offset_t va, vm_size_t sz) +{ + + if (va == 0) { + /* Page table itself. */ + if (sz > IA64_EFI_PGTBLSZ_MAX) + return (0); + if (ia64_efi_pgtbl == 0) + ia64_efi_pgtbl = ia64_efi_alloc(IA64_EFI_PGTBLSZ_MAX); + if (ia64_efi_pgtbl != 0) + ia64_efi_pgtblsz = sz; + return (ia64_efi_pgtbl); + } else if (va < IA64_PBVM_BASE) { + /* Should not happen. */ + return (0); + } + + /* Loader virtual memory page. */ + va -= IA64_PBVM_BASE; + + /* Allocate a big chunk that can be wired with a single PTE. */ + if (ia64_efi_chunk == 0) + ia64_efi_chunk = ia64_efi_alloc(IA64_EFI_CHUNK_SIZE); + if (va < IA64_EFI_CHUNK_SIZE) + return (ia64_efi_chunk + va); + + /* Allocate a page at a time when we go beyond the chunk. */ + return (ia64_efi_alloc(sz)); +} + +void +ia64_platform_free(vm_offset_t va, vm_paddr_t pa, vm_size_t sz) +{ + + BS->FreePages(pa, sz >> EFI_PAGE_SHIFT); +} + int -ldr_bootinfo(struct bootinfo *bi, uint64_t *bi_addr) +ia64_platform_bootinfo(struct bootinfo *bi, struct bootinfo **res) { VOID *fpswa; - EFI_MEMORY_DESCRIPTOR *mm; - EFI_PHYSICAL_ADDRESS addr; EFI_HANDLE handle; EFI_STATUS status; - size_t bisz; - UINTN mmsz, pages, sz; - UINT32 mmver; + UINTN sz; bi->bi_systab = (uint64_t)ST; bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp_guid); @@ -75,55 +196,22 @@ ldr_bootinfo(struct bootinfo *bi, uint64_t *bi_addr) status = BS->HandleProtocol(handle, &fpswa_guid, &fpswa); bi->bi_fpswa = (status == 0) ? (uint64_t)fpswa : 0; - bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; - - /* - * Allocate enough pages to hold the bootinfo block and the memory - * map EFI will return to us. The memory map has an unknown size, - * so we have to determine that first. Note that the AllocatePages - * call can itself modify the memory map, so we have to take that - * into account as well. The changes to the memory map are caused - * by splitting a range of free memory into two (AFAICT), so that - * one is marked as being loader data. - */ - sz = 0; - BS->GetMemoryMap(&sz, NULL, &mapkey, &mmsz, &mmver); - sz += mmsz; - sz = (sz + 15) & ~15; - pages = EFI_SIZE_TO_PAGES(sz + bisz); - status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, - &addr); - if (EFI_ERROR(status)) { - printf("%s: AllocatePages() returned 0x%lx\n", __func__, - (long)status); + if (!ia64_efi_memmap_update()) return (ENOMEM); - } - /* - * Read the memory map and stash it after bootinfo. Align the - * memory map on a 16-byte boundary (the bootinfo block is page - * aligned). - */ - *bi_addr = addr; - mm = (void *)(addr + bisz); - sz = (EFI_PAGE_SIZE * pages) - bisz; - status = BS->GetMemoryMap(&sz, mm, &mapkey, &mmsz, &mmver); - if (EFI_ERROR(status)) { - printf("%s: GetMemoryMap() returned 0x%lx\n", __func__, - (long)status); - return (EINVAL); - } - bi->bi_memmap = (uint64_t)mm; - bi->bi_memmap_size = sz; - bi->bi_memdesc_size = mmsz; - bi->bi_memdesc_version = mmver; + bi->bi_memmap = (uint64_t)memmap; + bi->bi_memmap_size = memmapsz; + bi->bi_memdesc_size = descsz; + bi->bi_memdesc_version = descver; + + if (IS_LEGACY_KERNEL()) + *res = malloc(sizeof(**res)); - bcopy(bi, (void *)(*bi_addr), sizeof(*bi)); return (0); } int -ldr_enter(const char *kernel) +ia64_platform_enter(const char *kernel) { EFI_STATUS status; diff --git a/sys/boot/ia64/efi/version b/sys/boot/ia64/efi/version index a31d87d..3a947c8 100644 --- a/sys/boot/ia64/efi/version +++ b/sys/boot/ia64/efi/version @@ -3,6 +3,7 @@ $FreeBSD$ NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this file is important. Make sure the current version number is on line 6. +3.0: Add support for PBVM. 2.2: Create direct mapping based on start address instead of mapping first 256M. 2.1: Add support for "-dev <part>" argument parsing. |