⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 efi.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "efi/efi.h"#include "etherboot.h"#include "elf.h"#include "sal.h"#include "pal.h"#warning "Place a declaration of lookup_efi_nic somewhere useful"EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE *lookup_efi_nic(int index);#warning "Place the declaraction of __call someplace more appropriate\n"extern EFI_STATUS __call(void *,...);/* Keep 16M free in case EFI needs to allocate some memory.  * In the worst case this is only 1/8 the memory on an Itanium. */#define EFI_RESERVE_LOW_PAGES  ((8*1024*1024)/EFI_PAGE_SIZE)#define EFI_RESERVE_HIGH_PAGES ((8*1024*1024)/EFI_PAGE_SIZE)struct console_info {	uint16_t num_cols;	uint16_t num_rows;	uint16_t orig_x;	uint16_t orig_y;};struct efi_mem_map {	uint64_t	map_size;	uint64_t	map_key;	uint64_t	descriptor_size;	uint32_t              descriptor_version;	uint32_t              pad;	EFI_MEMORY_DESCRIPTOR map[64];};struct efi_info {	int flags;#define READ_SYSTAB  1#define READ_FPSWA   2#define READ_MEMMAP  4	#define READ_CONINFO 8	EFI_SYSTEM_TABLE *systab;	void *fpswa;	struct efi_mem_map mem_map;	struct console_info coninfo;};unsigned long io_base;/* local globals */static struct efi_info efi_info;static EFI_HANDLE etherboot_handle;static EFI_BOOT_SERVICES *boot_services;static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;static SIMPLE_INPUT_INTERFACE *conin;static void *mps_table;static void *acpi20_table;static void *smbios_table;static void *nii_table;/* local functions */static EFI_STATUS efi_locate_handle(	EFI_LOCATE_SEARCH_TYPE search_type, 	EFI_GUID *protocol, void *search_key, 	UINTN *buffer_size, EFI_HANDLE *buffer){	if (!boot_services)		return EFI_NOT_FOUND;	return __call(boot_services->LocateHandle, 		search_type, protocol, search_key, buffer_size, buffer);}static EFI_STATUS efi_handle_protocol(EFI_HANDLE handle, EFI_GUID *protocol, void **interface){	if (!boot_services)		return EFI_UNSUPPORTED;	return __call(boot_services->HandleProtocol, handle, protocol, interface);}static EFI_STATUS efi_locate_device_path(EFI_GUID *protocol, EFI_DEVICE_PATH **device_path,	EFI_HANDLE *device){	if (!boot_services)		return EFI_NOT_FOUND;	return __call(boot_services->LocateDevicePath, protocol, device_path, device);}static EFI_STATUS efi_allocate_pages(EFI_ALLOCATE_TYPE type, EFI_MEMORY_TYPE memory_type, 	UINTN pages, EFI_PHYSICAL_ADDRESS *memory){	if (!boot_services)		return EFI_OUT_OF_RESOURCES;	return __call(boot_services->AllocatePages,		type, memory_type, pages, memory);}static EFI_STATUS efi_free_pages(EFI_PHYSICAL_ADDRESS memory, UINTN pages){	if(pages == 0)		return EFI_SUCCESS;	if (!boot_services)		return EFI_INVALID_PARAMETER;	return __call(boot_services->FreePages, memory, pages);}static EFI_STATUS efi_get_memory_map(UINTN *map_size, EFI_MEMORY_DESCRIPTOR *map,	UINTN *map_key, UINTN *descriptor_size, UINT32 *descriptor_version){	if (!boot_services)		return EFI_INVALID_PARAMETER;	return __call(boot_services->GetMemoryMap,		map_size, map, map_key, descriptor_size, descriptor_version);}static EFI_STATUS efi_free_pool(void *buffer){	if (!boot_services)		return EFI_INVALID_PARAMETER;	return __call(boot_services->FreePool, buffer);}static EFI_STATUS efi_stall(UINTN microseconds){	if (!boot_services)		return EFI_UNSUPPORTED;	return __call(boot_services->Stall, microseconds);}static EFI_STATUS efi_set_watchdog_timer(	UINTN timeout, UINT64 watchdog_code, UINTN data_size, CHAR16 *watchdog_data){	if (!boot_services)		return EFI_UNSUPPORTED;	return __call(boot_services->SetWatchdogTimer,		timeout, watchdog_code, data_size, watchdog_data);}static void efi_exit_boot_services(struct efi_mem_map *map){	EFI_STATUS status;	if (!boot_services)		return;	status = __call(boot_services->ExitBootServices, 		etherboot_handle, map->map_key);	if (status != EFI_SUCCESS) {		printf("ExitBootServices failed: %lx\n", status);	}	conout = 0;	conin = 0;	boot_services = 0;}static void efi_free_memory(struct efi_mem_map *map){	EFI_MEMORY_DESCRIPTOR *desc, *tail;#define next_desc(desc, size) ((EFI_MEMORY_DESCRIPTOR *)(((char *)(desc)) + (size)))	tail = next_desc(map->map, map->map_size);	for(desc = map->map; desc < tail; desc = next_desc(desc, map->descriptor_size)) {		EFI_STATUS status;		EFI_PHYSICAL_ADDRESS start, end;		UINTN pages;		int may_free;		start = desc->PhysicalStart;		pages = desc->NumberOfPages;		end = start + pages * EFI_PAGE_SIZE;		may_free = 0;		/* The only canidates are Loader Code and Data */		if ((desc->Type == EfiLoaderData) ||			(desc->Type == EfiLoaderCode))			may_free = 1;			/* Don't free anything etherboot lives in */		if ((may_free) &&			(start < virt_to_phys(_end)) &&			(end > virt_to_phys(_text)))			may_free = 0;		/* Continue if it is not memory we want to free */		if (!may_free)			continue;		status = efi_free_pages(start, pages);		if (status != EFI_SUCCESS) {			printf("free_pages: %lx\n", status);		}	}#undef next_desc}static void read_efi_mem_map(struct efi_mem_map *map){	EFI_STATUS status;	map->map_size = sizeof(map->map);	status = efi_get_memory_map(		&map->map_size, map->map, &map->map_key,		&map->descriptor_size, &map->descriptor_version);	if (status != EFI_SUCCESS) {		printf("read_efi_mem_map failed: %lx\n", status);		map->map_size = 0;	}	/* map->descriptor_size should only grow larger */	/* map->descriptor_version should only increase and retain	 * a backward compatible format.	 */}#if 0static const char *efi_mem_type_name(uint32_t type){	const char *type_name;	if (type == EfiReservedMemoryType)		type_name = "EfiReservedMemoryType     ";	else if (type == EfiLoaderCode)		type_name = "EfiLoaderCode             ";	else if (type == EfiLoaderData)		type_name = "EfiLoaderData             ";	else if (type == EfiBootServicesCode)		type_name = "EfiBootServicesCode       ";	else if (type == EfiBootServicesData)		type_name = "EfiBootServicesData       ";	else if (type == EfiRuntimeServicesCode)		type_name = "EfiRuntimeServicesCode    ";	else if (type == EfiRuntimeServicesData)		type_name = "EfiRuntimeServicesData    ";	else if (type == EfiConventionalMemory)		type_name = "EfiConventionalMemory     ";	else if (type == EfiUnusableMemory)		type_name = "EfiUnusableMemory         ";	else if (type == EfiACPIReclaimMemory)		type_name = "EfiACPIReclaimMemory      ";	else if (type == EfiACPIMemoryNVS)		type_name = "EfiACPIMemoryNVS          ";	else if (type == EfiMemoryMappedIO)		type_name = "EfiMemoryMappedIO         ";	else if (type == EfiMemoryMappedIOPortSpace)		type_name = "EfiMemoryMappedIOPortSpace";	else if (type == EfiPalCode)		type_name = "EfiPalCode                ";	else		type_name = "????                      ";	return type_name;}static void print_efi_mem_map(struct efi_mem_map *map){	EFI_MEMORY_DESCRIPTOR *desc, *end;#define next_desc(desc, size) ((EFI_MEMORY_DESCRIPTOR *)(((char *)(desc)) + (size)))	end = next_desc(map->map, map->map_size);	for(desc = map->map; desc < end ; desc = next_desc(desc, map->descriptor_size)) {		const char *mem_type;		unsigned long start, end, virt, virt_end;		uint64_t attr;		mem_type = efi_mem_type_name(desc->Type);		start = desc->PhysicalStart;		end   = start + desc->NumberOfPages*EFI_PAGE_SIZE;		virt  = desc->VirtualStart;		virt_end = virt + desc->NumberOfPages*EFI_PAGE_SIZE;		attr = desc->Attribute;		printf(	"mem: %hhx %s @ %#lx-%#lx",			desc->Type, mem_type, start, end);		if (attr & EFI_MEMORY_UC)			printf("UC ");		if (attr & EFI_MEMORY_WC)			printf("WC ");		if (attr & EFI_MEMORY_WT)			printf("WT ");		if (attr & EFI_MEMORY_WB)			printf("WB ");		if (attr & EFI_MEMORY_UCE)			printf("UCE ");		if (attr & EFI_MEMORY_WP)			printf("WP ");		if (attr & EFI_MEMORY_RP)			printf("RP ");		if (attr & EFI_MEMORY_XP)			printf("XP ");				if (attr & EFI_MEMORY_RUNTIME)			printf("RUNTIME ");		printf("\n");	}#undef next_desc}#endifstatic void efi_allocate_memory(struct efi_mem_map *map){	EFI_MEMORY_DESCRIPTOR *desc, *end;	unsigned long low_free, high_free;#define next_desc(desc, size) ((EFI_MEMORY_DESCRIPTOR *)(((char *)(desc)) + (size)))	end = next_desc(map->map, map->map_size);	/* Find out how much memory is free */	low_free = high_free = 0;	for(desc = map->map; desc < end ; desc = next_desc(desc, map->descriptor_size)) {		unsigned long start, middle, end;		if (desc->Type != EfiConventionalMemory)			continue;		start = desc->PhysicalStart;		end = desc->PhysicalStart + (desc->NumberOfPages*EFI_PAGE_SIZE);		if (start < 0x100000000UL) {			if (end > 0x100000000UL) {				middle = 0x10000000UL;			} else {				middle = end;			}		} else {			middle = start;		}		low_free += (middle - start)/EFI_PAGE_SIZE;		high_free += (end - middle)/EFI_PAGE_SIZE;	}	/* O.k. Now allocate all of the conventional memory, reserving only a tiny	 * fraction for efi.	 */	for(desc = map->map; desc < end ; desc = next_desc(desc, map->descriptor_size)) {		EFI_STATUS status;		EFI_PHYSICAL_ADDRESS address;		UINTN pages;		unsigned long start, middle, end;		unsigned long low_pages, high_pages;		if (desc->Type != EfiConventionalMemory)			continue;		start = desc->PhysicalStart;		end = desc->PhysicalStart + (desc->NumberOfPages*EFI_PAGE_SIZE);		if (start < 0x100000000UL) {			if (end > 0x100000000UL) {				middle = 0x10000000UL;			} else {				middle = end;			}		} else {			middle = start;		}		low_pages  = (middle - start)/EFI_PAGE_SIZE;		high_pages = (end - middle)/EFI_PAGE_SIZE;		if (low_pages && (low_free > EFI_RESERVE_LOW_PAGES)) {			address = start;			pages = low_pages;			if ((low_free - pages) < EFI_RESERVE_LOW_PAGES) {				pages = low_free - EFI_RESERVE_LOW_PAGES;			}			status = efi_allocate_pages(				AllocateAddress, EfiLoaderData, pages, &address);			if (status != EFI_SUCCESS) {				printf("allocate_pages @%lx for %ld pages failed: %ld\n", 					desc->PhysicalStart, pages, status);			}			low_free -= pages;		}		if (high_pages && (high_free > EFI_RESERVE_HIGH_PAGES)) {			address = middle;			pages = high_pages;			if ((high_free - pages) < EFI_RESERVE_HIGH_PAGES) {				pages = high_free - EFI_RESERVE_HIGH_PAGES;			}			status = efi_allocate_pages(				AllocateAddress, EfiLoaderData, pages, &address);			if (status != EFI_SUCCESS) {				printf("allocate_pages @%lx for %ld pages failed: %ld\n", 					desc->PhysicalStart, pages, status);			}			high_free -= pages;		}	}#undef next_desc}static void set_io_base(struct efi_mem_map *map){	EFI_MEMORY_DESCRIPTOR *desc, *end;	io_base = ia64_get_kr0(); /* Default to ar.kr0 */#define next_desc(desc, size) ((EFI_MEMORY_DESCRIPTOR *)(((char *)(desc)) + (size)))	end = next_desc(map->map, map->map_size);	for(desc = map->map; desc < end ; desc = next_desc(desc, map->descriptor_size)) {		if (desc->Type == EfiMemoryMappedIOPortSpace) {			io_base = desc->PhysicalStart;			break;		}	}#undef next_desc}#define MAX_EFI_DEVICES 32static void efi_stop_nics(void){	static EFI_GUID simple_net_protocol = EFI_SIMPLE_NETWORK_PROTOCOL;	EFI_SIMPLE_NETWORK *simple;	EFI_STATUS status;	EFI_HANDLE handles[MAX_EFI_DEVICES];	EFI_HANDLE handle;	UINTN devices;	unsigned i;	if (!boot_services)		return;		devices = sizeof(handles);	status = efi_locate_handle(		ByProtocol, &simple_net_protocol, 0, &devices, handles);	if (status != EFI_SUCCESS)		return;	devices /= sizeof(handles[0]);	for(i = 0; i < devices; i++) {		void *that;		handle = handles[i];		status = efi_handle_protocol(handle, &simple_net_protocol, &that);		if (status != EFI_SUCCESS)			continue;		simple = that;		if ((simple->Mode->State == EfiSimpleNetworkInitialized)) {			status = __call(simple->Shutdown, simple);			status = __call(simple->Stop, simple);		}		else if (simple->Mode->State == EfiSimpleNetworkStarted) {			status = __call(simple->Stop, simple);		}	}}static void efi_get_coninfo(struct console_info *info){	EFI_STATUS status;	UINTN cols, rows;	/* Initialize with some silly safe values */	info->num_cols = 80;	info->num_rows = 24;	info->orig_x   = 0;	info->orig_y   = 0;	status = EFI_UNSUPPORTED;	if (conout) {		status = __call(conout->QueryMode, conout, conout->Mode->Mode, &cols, &rows);		if (status) {			printf("QueryMode Failed cannout get console parameters: %ld\n", status);		} else {			info->num_cols = cols;			info->num_rows = rows;			info->orig_x   = conout->Mode->CursorColumn;			info->orig_y   = conout->Mode->CursorRow;		}	}}static void *efi_get_fpswa(void){	static EFI_GUID fpswa_protocol = FPSWA_PROTOCOL;	EFI_STATUS status;	EFI_HANDLE fpswa_handle;	UINTN devices;	void *result;	/* The FPSWA is the Floating Point Software Assist driver,	 * to some extent it makes sense but it has one large flaw.	 * It fails to install an EFI Configuration table, so the	 * OS does not need assistance from the bootloader to find it.	 */	devices = sizeof(fpswa_handle);	status = efi_locate_handle(		ByProtocol, &fpswa_protocol, 0, &devices, &fpswa_handle);	if (status != EFI_SUCCESS)		return 0;		status = efi_handle_protocol(		fpswa_handle, &fpswa_protocol, &result);	if (status != EFI_SUCCESS)		return 0;	return result;}/* Exported functions */void arch_main(struct Elf_Bhdr *bhdr){	EFI_STATUS status;	unsigned char *note, *end;	memset(&efi_info, 0, sizeof(efi_info));	note = ((char *)bhdr) + sizeof(*bhdr);	end  = ((char *)bhdr) + bhdr->b_size;	if (bhdr->b_signature != 0x0E1FB007) {		printf("Bad bhdr(%lx) signature(%x)!\n",			(unsigned long) bhdr, bhdr->b_signature);		note = end = 0;	}	while(note < end) {		Elf_Nhdr *hdr;		unsigned char *n_name, *n_desc, *next;		hdr = (Elf_Nhdr *)note;		n_name = note + sizeof(*hdr);		n_desc = n_name + ((hdr->n_namesz + 3) & ~3);		next = n_desc + ((hdr->n_descsz + 3) & ~3);		if (next > end) 			break;#if 0		printf("n_type: %x n_name(%d): n_desc(%d): \n", 

⌨️ 快捷键说明

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