xref: /illumos-gate/usr/src/boot/efi/loader/arch/i386/efimd.c (revision 0101d5c76fd6df416f91194bf9f36f9225bf8c52)
122028508SToomas Soome /*-
222028508SToomas Soome  * Copyright (c) 2004, 2006 Marcel Moolenaar
322028508SToomas Soome  * All rights reserved.
422028508SToomas Soome  *
522028508SToomas Soome  * Redistribution and use in source and binary forms, with or without
622028508SToomas Soome  * modification, are permitted provided that the following conditions
722028508SToomas Soome  * are met:
822028508SToomas Soome  *
922028508SToomas Soome  * 1. Redistributions of source code must retain the above copyright
1022028508SToomas Soome  *    notice, this list of conditions and the following disclaimer.
1122028508SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
1222028508SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
1322028508SToomas Soome  *    documentation and/or other materials provided with the distribution.
1422028508SToomas Soome  *
1522028508SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1622028508SToomas Soome  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1722028508SToomas Soome  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1822028508SToomas Soome  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1922028508SToomas Soome  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2022028508SToomas Soome  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2122028508SToomas Soome  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2222028508SToomas Soome  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2322028508SToomas Soome  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2422028508SToomas Soome  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2522028508SToomas Soome  */
2622028508SToomas Soome 
2722028508SToomas Soome #include <sys/cdefs.h>
2822028508SToomas Soome __FBSDID("$FreeBSD$");
2922028508SToomas Soome 
3022028508SToomas Soome #include <stand.h>
3122028508SToomas Soome 
3222028508SToomas Soome #include <efi.h>
3322028508SToomas Soome #include <efilib.h>
3422028508SToomas Soome 
3522028508SToomas Soome #include <libi386.h>
3622028508SToomas Soome #include <machine/bootinfo.h>
3722028508SToomas Soome 
3822028508SToomas Soome #define	EFI_INTEL_FPSWA		\
39*0101d5c7SToomas Soome 	{0xc41b6531, 0x97b9, 0x11d3, \
40*0101d5c7SToomas Soome 		{0x9a, 0x29, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d}}
4122028508SToomas Soome 
4222028508SToomas Soome static EFI_GUID fpswa_guid = EFI_INTEL_FPSWA;
4322028508SToomas Soome 
4422028508SToomas Soome /* DIG64 Headless Console & Debug Port Table. */
4522028508SToomas Soome #define	HCDP_TABLE_GUID		\
46*0101d5c7SToomas Soome 	{0xf951938d, 0x620b, 0x42ef, \
47*0101d5c7SToomas Soome 		{0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98}}
4822028508SToomas Soome 
4922028508SToomas Soome static EFI_GUID hcdp_guid = HCDP_TABLE_GUID;
5022028508SToomas Soome 
5122028508SToomas Soome static UINTN mapkey;
5222028508SToomas Soome 
5322028508SToomas Soome uint64_t
ldr_alloc(vm_offset_t va)5422028508SToomas Soome ldr_alloc(vm_offset_t va)
5522028508SToomas Soome {
5622028508SToomas Soome 
5722028508SToomas Soome 	return (0);
5822028508SToomas Soome }
5922028508SToomas Soome 
6022028508SToomas Soome int
ldr_bootinfo(struct bootinfo * bi,uint64_t * bi_addr)6122028508SToomas Soome ldr_bootinfo(struct bootinfo *bi, uint64_t *bi_addr)
6222028508SToomas Soome {
63*0101d5c7SToomas Soome 	void *fpswa;
6422028508SToomas Soome 	EFI_MEMORY_DESCRIPTOR *mm;
6522028508SToomas Soome 	EFI_PHYSICAL_ADDRESS addr;
6669764de3SToomas Soome 	EFI_HANDLE *handles;
6722028508SToomas Soome 	EFI_STATUS status;
6822028508SToomas Soome 	size_t bisz;
6922028508SToomas Soome 	UINTN mmsz, pages, sz;
7022028508SToomas Soome 	UINT32 mmver;
7169764de3SToomas Soome 	uint_t nhandles;
7222028508SToomas Soome 
7322028508SToomas Soome 	bi->bi_systab = (uint64_t)ST;
7422028508SToomas Soome 	bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp_guid);
7522028508SToomas Soome 
7669764de3SToomas Soome 	status = efi_get_protocol_handles(&fpswa_guid, &nhandles, &handles);
7722028508SToomas Soome 	if (status == 0)
7869764de3SToomas Soome 		status = OpenProtocolByHandle(*handles, &fpswa_guid, &fpswa);
7922028508SToomas Soome 	bi->bi_fpswa = (status == 0) ? (uint64_t)fpswa : 0;
8022028508SToomas Soome 
8122028508SToomas Soome 	bisz = (sizeof (struct bootinfo) + 0x0f) & ~0x0f;
8222028508SToomas Soome 
8322028508SToomas Soome 	/*
8422028508SToomas Soome 	 * Allocate enough pages to hold the bootinfo block and the memory
8522028508SToomas Soome 	 * map EFI will return to us. The memory map has an unknown size,
8622028508SToomas Soome 	 * so we have to determine that first. Note that the AllocatePages
8722028508SToomas Soome 	 * call can itself modify the memory map, so we have to take that
8822028508SToomas Soome 	 * into account as well. The changes to the memory map are caused
8922028508SToomas Soome 	 * by splitting a range of free memory into two (AFAICT), so that
9022028508SToomas Soome 	 * one is marked as being loader data.
9122028508SToomas Soome 	 */
9222028508SToomas Soome 	sz = 0;
9322028508SToomas Soome 	BS->GetMemoryMap(&sz, NULL, &mapkey, &mmsz, &mmver);
9422028508SToomas Soome 	sz += mmsz;
9522028508SToomas Soome 	sz = (sz + 15) & ~15;
9622028508SToomas Soome 	pages = EFI_SIZE_TO_PAGES(sz + bisz);
9722028508SToomas Soome 	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages,
9822028508SToomas Soome 	    &addr);
9922028508SToomas Soome 	if (EFI_ERROR(status)) {
10022028508SToomas Soome 		printf("%s: AllocatePages() returned 0x%lx\n", __func__,
10122028508SToomas Soome 		    (long)status);
10222028508SToomas Soome 		return (ENOMEM);
10322028508SToomas Soome 	}
10422028508SToomas Soome 
10522028508SToomas Soome 	/*
10622028508SToomas Soome 	 * Read the memory map and stash it after bootinfo. Align the
10722028508SToomas Soome 	 * memory map on a 16-byte boundary (the bootinfo block is page
10822028508SToomas Soome 	 * aligned).
10922028508SToomas Soome 	 */
11022028508SToomas Soome 	*bi_addr = addr;
11122028508SToomas Soome 	mm = (void *)(addr + bisz);
11222028508SToomas Soome 	sz = (EFI_PAGE_SIZE * pages) - bisz;
11322028508SToomas Soome 	status = BS->GetMemoryMap(&sz, mm, &mapkey, &mmsz, &mmver);
11422028508SToomas Soome 	if (EFI_ERROR(status)) {
11522028508SToomas Soome 		printf("%s: GetMemoryMap() returned 0x%lx\n", __func__,
11622028508SToomas Soome 		    (long)status);
11722028508SToomas Soome 		return (EINVAL);
11822028508SToomas Soome 	}
11922028508SToomas Soome 	bi->bi_memmap = (uint64_t)mm;
12022028508SToomas Soome 	bi->bi_memmap_size = sz;
12122028508SToomas Soome 	bi->bi_memdesc_size = mmsz;
12222028508SToomas Soome 	bi->bi_memdesc_version = mmver;
12322028508SToomas Soome 
12422028508SToomas Soome 	bcopy(bi, (void *)(*bi_addr), sizeof (*bi));
12522028508SToomas Soome 	return (0);
12622028508SToomas Soome }
12722028508SToomas Soome 
12822028508SToomas Soome int
ldr_enter(const char * kernel)12922028508SToomas Soome ldr_enter(const char *kernel)
13022028508SToomas Soome {
13122028508SToomas Soome 	EFI_STATUS status;
13222028508SToomas Soome 
13322028508SToomas Soome 	status = BS->ExitBootServices(IH, mapkey);
13422028508SToomas Soome 	if (EFI_ERROR(status)) {
13522028508SToomas Soome 		printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
13622028508SToomas Soome 		    (long)status);
13722028508SToomas Soome 		return (EINVAL);
13822028508SToomas Soome 	}
13922028508SToomas Soome 
14022028508SToomas Soome 	return (0);
14122028508SToomas Soome }
142