efimd.c revision 339210
1/*- 2 * Copyright (c) 2004, 2006 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/stand/efi/loader/arch/i386/efimd.c 339210 2018-10-05 21:10:03Z jhb $"); 29 30#include <stand.h> 31 32#include <efi.h> 33#include <efilib.h> 34 35#include <libi386.h> 36#include <machine/bootinfo.h> 37 38#define EFI_INTEL_FPSWA \ 39 {0xc41b6531,0x97b9,0x11d3,{0x9a,0x29,0x00,0x90,0x27,0x3f,0xc1,0x4d}} 40 41static EFI_GUID fpswa_guid = EFI_INTEL_FPSWA; 42 43/* DIG64 Headless Console & Debug Port Table. */ 44#define HCDP_TABLE_GUID \ 45 {0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}} 46 47static EFI_GUID hcdp_guid = HCDP_TABLE_GUID; 48 49static UINTN mapkey; 50 51int ldr_bootinfo(struct bootinfo *, uint64_t *); 52int ldr_enter(const char *); 53 54static uint64_t 55ldr_alloc(vm_offset_t va) 56{ 57 58 return (0); 59} 60 61int 62ldr_bootinfo(struct bootinfo *bi, uint64_t *bi_addr) 63{ 64 VOID *fpswa; 65 EFI_MEMORY_DESCRIPTOR *mm; 66 EFI_PHYSICAL_ADDRESS addr; 67 EFI_HANDLE handle; 68 EFI_STATUS status; 69 size_t bisz; 70 UINTN mmsz, pages, sz; 71 UINT32 mmver; 72 73 bi->bi_systab = (uintptr_t)ST; 74 bi->bi_hcdp = (uintptr_t)efi_get_table(&hcdp_guid); 75 76 sz = sizeof(EFI_HANDLE); 77 status = BS->LocateHandle(ByProtocol, &fpswa_guid, 0, &sz, &handle); 78 if (status == 0) 79 status = BS->HandleProtocol(handle, &fpswa_guid, &fpswa); 80 bi->bi_fpswa = (status == 0) ? (uintptr_t)fpswa : 0; 81 82 bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; 83 84 /* 85 * Allocate enough pages to hold the bootinfo block and the memory 86 * map EFI will return to us. The memory map has an unknown size, 87 * so we have to determine that first. Note that the AllocatePages 88 * call can itself modify the memory map, so we have to take that 89 * into account as well. The changes to the memory map are caused 90 * by splitting a range of free memory into two (AFAICT), so that 91 * one is marked as being loader data. 92 */ 93 sz = 0; 94 BS->GetMemoryMap(&sz, NULL, &mapkey, &mmsz, &mmver); 95 sz += mmsz; 96 sz = (sz + 15) & ~15; 97 pages = EFI_SIZE_TO_PAGES(sz + bisz); 98 status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, 99 &addr); 100 if (EFI_ERROR(status)) { 101 printf("%s: AllocatePages() returned 0x%lx\n", __func__, 102 (long)status); 103 return (ENOMEM); 104 } 105 106 /* 107 * Read the memory map and stash it after bootinfo. Align the 108 * memory map on a 16-byte boundary (the bootinfo block is page 109 * aligned). 110 */ 111 *bi_addr = addr; 112 mm = (void *)(uintptr_t)(addr + bisz); 113 sz = (EFI_PAGE_SIZE * pages) - bisz; 114 status = BS->GetMemoryMap(&sz, mm, &mapkey, &mmsz, &mmver); 115 if (EFI_ERROR(status)) { 116 printf("%s: GetMemoryMap() returned 0x%lx\n", __func__, 117 (long)status); 118 return (EINVAL); 119 } 120 bi->bi_memmap = (uintptr_t)mm; 121 bi->bi_memmap_size = sz; 122 bi->bi_memdesc_size = mmsz; 123 bi->bi_memdesc_version = mmver; 124 125 bcopy(bi, (void *)(uintptr_t)(*bi_addr), sizeof(*bi)); 126 return (0); 127} 128 129int 130ldr_enter(const char *kernel) 131{ 132 EFI_STATUS status; 133 134 status = BS->ExitBootServices(IH, mapkey); 135 if (EFI_ERROR(status)) { 136 printf("%s: ExitBootServices() returned 0x%lx\n", __func__, 137 (long)status); 138 return (EINVAL); 139 } 140 141 return (0); 142} 143