efi.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 238 行

C
238
字号
/* * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> * The code is partly taken from FreeBSD. * *************************************************************************** * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#include "os.h"#include "efi.h"#include "page.h"#include "lib.h"#include "console.h"/* The implementation is in fw.S. */extern uint64_tia64_call_efi_func(uint64_t funcP,uint64_t a,uint64_t b,uint64_t c,uint64_t d);intefi_get_time(efi_time_t* tmP){	memset(tmP, 0, sizeof(efi_time_t));	if (ia64_call_efi_func((uint64_t)machineFwG.efi.getTimeF,			       (uint64_t)tmP,			       (uint64_t)NULL, 0, 0) != EFI_SUCCESS) {		printk("efi.getTime() failed\n");		return 0;	}#if defined(BIG_ENDIAN)	tmP->Year = SWAP(tmP->Year);	tmP->TimeZone = SWAP(tmP->TimeZone);	tmP->Nanosecond = SWAP(tmP->Nanosecond);#endif	return 1;}/* * The function compares two efi_guid_t and returns 0 on equality, otherwise 1. */static intefi_guid_cmp(efi_guid_t* a_le, efi_guid_t* b){#if defined(BIG_ENDIAN)	if(SWAP(a_le->Data1) != b->Data1)		return 1;	if(SWAP(a_le->Data2) != b->Data2)		return 1;	if(SWAP(a_le->Data3) != b->Data3)		return 1;	return memcmp(a_le->Data4, b->Data4, sizeof(uint8_t)*8);#else	return memcmp(a_le, b, sizeof(efi_guid_t));#endif}voidinit_efi(void){	efi_system_table_t* efiSysTableP;	int mdcnt, i, numConvMem;	efi_memory_descriptor_t *memdP, *mdP;	efi_status_t status;	char fwVendor[100] = "unknown";	efi_char16_t* fwP;	efi_runtime_services_t* rsP;	efi_configuration_table_t* confP = (efi_configuration_table_t*)0;	efi_guid_t sal = SAL_SYSTEM_TABLE_GUID;	efi_guid_t acpi = ACPI_TABLE_GUID;	efi_guid_t acpi20 = ACPI_20_TABLE_GUID;		memset(&machineFwG, 0, sizeof(machineFwG));	/* Read the efi_system_table.  */	efiSysTableP = (efi_system_table_t*)__va(ia64BootParamG.efi_systab);	machineFwG.efi.efiSysTableP = efiSysTableP;	PRINT_BV("EfiSystemTable at: %p\n", efiSysTableP);	fwP = (uint16_t*) __va(SWAP(efiSysTableP->FirmwareVendor));	if (fwP) {		for (i = 0; i < (int)sizeof(fwVendor) - 1 && *fwP; ++i)			fwVendor[i] = SWAP(*fwP++);		fwVendor[i] = '\0';	}	PRINT_BV("  EFI-FirmwareVendor        : %s\n", fwVendor);	PRINT_BV("  EFI-FirmwareRevision      : %d\n",		 SWAP(efiSysTableP->FirmwareRevision));	PRINT_BV("  EFI-SystemTable-Revision  : %d.%d\n",		 SWAP(efiSysTableP->Hdr.Revision)>>16,		 SWAP(efiSysTableP->Hdr.Revision)&0xffff);	rsP = (efi_runtime_services_t*)		__va(SWAP(efiSysTableP->RuntimeServices));	mdcnt = ia64BootParamG.efi_memmap_size /		ia64BootParamG.efi_memdesc_size;	memdP = (efi_memory_descriptor_t*) __va(ia64BootParamG.efi_memmap);	PRINT_BV("EFI-Memorydescriptors: %d\n", mdcnt);	for (i = numConvMem = 0, mdP = memdP; i < mdcnt; i++,	     mdP = NextMemoryDescriptor(mdP, ia64BootParamG.efi_memdesc_size)) {		/* Relocate runtime memory segments for firmware. */		PRINT_BV("  %d. Type: %x  Attributes: 0x%lx\n",			 i, SWAP(mdP->Type), SWAP(mdP->Attribute));		PRINT_BV("     PhysStart: 0x%lx  NumPages: 0x%lx\n",			 SWAP(mdP->PhysicalStart), SWAP(mdP->NumberOfPages));		switch (SWAP(mdP->Type)) {			case EfiRuntimeServicesData:				PRINT_BV("     -> EfiRuntimeServicesData\n");				break;			case EfiACPIReclaimMemory:				PRINT_BV("     -> EfiACPIReclaimMemory\n");				break;			case EfiACPIMemoryNVS:				PRINT_BV("     -> EfiACPIMemoryNVS\n");				break;			case EfiConventionalMemory:				PRINT_BV("     -> EfiConventionalMemory\n");				PRINT_BV("        start: 0x%lx end: 0x%lx\n",					SWAP(mdP->PhysicalStart),					SWAP(mdP->PhysicalStart)+					SWAP(mdP->NumberOfPages)*EFI_PAGE_SIZE);				if (numConvMem) {					printk("     Currently only one efi "						"memory chunk supported !!!\n");					break;				}				machineFwG.mach_mem_start =					SWAP(mdP->PhysicalStart);				machineFwG.mach_mem_size =					SWAP(mdP->NumberOfPages)*EFI_PAGE_SIZE;				numConvMem++;				break;			case EfiMemoryMappedIOPortSpace:				PRINT_BV("     -> EfiMemMappedIOPortSpace\n");				break;			case EfiPalCode:                       		machineFwG.ia64_pal_base =					__va(SWAP(mdP->PhysicalStart));				PRINT_BV("     -> EfiPalCode\n"					 "        start : %p\n",					 machineFwG.ia64_pal_base);				break;		}		/* I have to setup the VirtualStart address of every		 * RUNTIME-area in preparing the later call of		 * SetVirtualAddressMap() therewidth the efi stuff uses		 * virtual addressing and the efi runtime functions		 * may be called directly.		 */		if (SWAP(mdP->Attribute) & EFI_MEMORY_RUNTIME) {			if (SWAP(mdP->Attribute) & EFI_MEMORY_WB)				mdP->VirtualStart =					SWAP(__va(mdP->PhysicalStart));			else {				if (SWAP(mdP->Attribute) & EFI_MEMORY_UC)					printk("efi_init: RuntimeMemory with "						"UC attribute !!!!!!\n");					/*					mdP->VirtualStart =					IA64_PHYS_TO_RR6(mdP->PhysicalStart);					*/			}		}	}	/* Now switch efi runtime stuff to virtual addressing. */	status = ia64_call_efi_physical(			(void*)__va(SWAP((uint64_t)rsP->SetVirtualAddressMap)),			ia64BootParamG.efi_memmap_size,			ia64BootParamG.efi_memdesc_size,			ia64BootParamG.efi_memdesc_version,			ia64BootParamG.efi_memmap);	status = EFI_SUCCESS;	if (status != EFI_SUCCESS) {		printk("warning: unable to switch EFI into virtual "		       "(status=%lu)\n", status);		return;	}	/* Getting efi function pointer for getEfiTime. */	machineFwG.efi.getTimeF =		(efi_get_time_t)__va(SWAP((uint64_t)rsP->GetTime));	/* Getting efi function pointer for resetSystem. */	machineFwG.efi.resetSystemF =		(efi_reset_system_t)__va(SWAP((uint64_t)rsP->ResetSystem));	/* Scanning the Configuration table of the EfiSystemTable. */	PRINT_BV("NumberOfConfigTableEntries: %ld\n",		 SWAP(efiSysTableP->NumberOfTableEntries));	confP = (efi_configuration_table_t*)			__va(SWAP(efiSysTableP->ConfigurationTable));	for (i = 0; i < SWAP(efiSysTableP->NumberOfTableEntries); i++) {		if (!efi_guid_cmp(&confP[i].VendorGuid, &sal)) {			machineFwG.ia64_sal_tableP = (sal_system_table_t*)				__va(SWAP((uint64_t) confP[i].VendorTable));			PRINT_BV("  Found SalSystemTable at: 0x%lx\n",				 (uint64_t) machineFwG.ia64_sal_tableP);			continue;		}		if (!efi_guid_cmp(&confP[i].VendorGuid, &acpi)) {			machineFwG.ia64_efi_acpi_table =				__va(SWAP((uint64_t) confP[i].VendorTable));			PRINT_BV("  Found AcpiTable at:      0x%lx\n",				 (uint64_t) machineFwG.ia64_efi_acpi_table);			continue;		}		if (!efi_guid_cmp(&confP[i].VendorGuid, &acpi20)) {			machineFwG.ia64_efi_acpi20_table =				__va(SWAP((uint64_t) confP[i].VendorTable));			PRINT_BV("  Found Acpi20Table at:    0x%lx\n",				 (uint64_t) machineFwG.ia64_efi_acpi20_table);			continue;		}	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?