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

📄 elilo.c

📁 EFI(Extensible Firmware Interface)是下一代BIOS
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * elilo.c - IA-64/IA-32 EFI Linux loader * *  Copyright (C) 1999-2003 Hewlett-Packard Co. *	Contributed by David Mosberger <davidm@hpl.hp.com>. *	Contributed by Stephane Eranian <eranian@hpl.hp.com> * *  Copyright (C) 1999-2000 VA Linux Systems *       Contributed by Johannes Erdfelt <jerdfelt@valinux.com>. * * This file is part of the ELILO, the EFI Linux boot loader. * *  ELILO is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. * *  ELILO is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with ELILO; see the file COPYING.  If not, write to the Free *  Software Foundation, 59 Temple Place - Suite 330, Boston, MA *  02111-1307, USA. * * Please check out the elilo.txt for complete documentation on how * to use this program. */#include <efi.h>#include <efilib.h>#include "elilo.h"#include "vars.h"#include "getopt.h"#include "fileops.h"#include "loader.h"#include "config.h" /* for config_init() */#define ELILO_VERSION			L"3.4"#define ELILO_SHARED_CMDLINE_OPTS	L"pPMC:aDhd:i:vVc:E"elilo_config_t elilo_opt;EFI_SYSTEM_TABLE *systab;	/* pointer to EFI system table *//* * Load the Linux kernel in memory from the boot media * Output: * 	kd = address of kernel entry point * 	   + end address of kernel code+data+bss * 	   + kernel entry point * Return: * 	ELILO_LOAD_ERROR   : if something went wrong * 	ELILO_LOAD_ABORTED : user interruption while loading * 	ELILO_LOAD_SUCCESS : otherwise */static INTNdo_kernel_load(CHAR16 *kname, kdesc_t *kd){	loader_ops_t	*ldops;	EFI_STATUS status;	fops_fd_t fd;	status = fops_open(kname, &fd);	if (EFI_ERROR(status)) {		ERR_PRT((L"Kernel file  not found %s", kname));		return ELILO_LOAD_ERROR;	}	fops_close(fd);	ldops = loader_probe(kname);	if (ldops == NULL) {		ERR_PRT((L"Cannot find a loader for %s", kname));		return ELILO_LOAD_ERROR;	}	VERB_PRT(1,Print(L"Using %s loader\n", ldops->ld_name));		return ldops->ld_load_kernel(kname, kd);}INTNkernel_load(EFI_HANDLE image, CHAR16 *kname, kdesc_t *kd, memdesc_t *imem){	/*	 * Now let's try to load the kernel !	 */	switch(do_kernel_load(kname, kd)) {		case ELILO_LOAD_SUCCESS:			break;		case ELILO_LOAD_ERROR:			/* XXX: add fallback support */			return ELILO_LOAD_ERROR;				case ELILO_LOAD_ABORTED:			/* we drop initrd in case we aborted the load */			elilo_opt.initrd[0] = CHAR_NULL;			/* will go back to interactive selection */			elilo_opt.prompt  = 1; 			elilo_opt.timeout = ELILO_DEFAULT_TIMEOUT;			elilo_opt.delay   = 0;			return ELILO_LOAD_RETRY;		}	VERB_PRT(3, Print(L"kernel loaded in [0x%lx-0x%lx] entry=0x%lx\n", 			  (UINT64)kd->kstart, (UINT64)kd->kend, (UINT64)kd->kentry));	if (elilo_opt.initrd[0]) {		if (sysdeps_initrd_get_addr(kd, imem) == -1) goto exit_error;		switch(load_initrd(elilo_opt.initrd, imem)) {			case ELILO_LOAD_SUCCESS:				break;			case ELILO_LOAD_ERROR:				goto exit_error;			case ELILO_LOAD_ABORTED:				/* the free_kmem() is the responsibility of the loader */				/* we drop initrd in case we aborted the load */				elilo_opt.initrd[0] = CHAR_NULL;				elilo_opt.prompt    = 1; 				elilo_opt.timeout   = ELILO_DEFAULT_TIMEOUT;				elilo_opt.delay     = 0;				return ELILO_LOAD_RETRY;		}	}	return ELILO_LOAD_SUCCESS;exit_error:	free_kmem();	if (imem->start_addr) free(imem->start_addr);	return ELILO_LOAD_ERROR;}static INTNmain_loop(EFI_HANDLE dev, CHAR16 **argv, INTN argc, INTN index, EFI_HANDLE image){	CHAR16 kname[FILENAME_MAXLEN];	CHAR16 cmdline_tmp[CMDLINE_MAXLEN];	CHAR16 cmdline[CMDLINE_MAXLEN];	VOID *bp;	UINTN cookie;	EFI_STATUS status = EFI_SUCCESS;	kdesc_t kd;	memdesc_t imem;	INTN r;	/*	 * First place where we potentially do system dependent	 * operations. It is a one time opportunity before entering	 * the main loop	 */	if (sysdeps_preloop_actions(dev, argv, argc, index, image) == -1) return -1;	for(;;) {		kname[0] = cmdline_tmp[0] = cmdline[0] = CHAR_NULL;		imem.start_addr = 0; imem.pgcnt = 0;		elilo_opt.sys_img_opts = NULL;		if (kernel_chooser(argv, argc, index, kname, cmdline_tmp) == -1) goto exit_error;		switch (kernel_load(image, kname, &kd, &imem)) {			case ELILO_LOAD_SUCCESS: 				goto do_launch;			case ELILO_LOAD_ERROR:				goto exit_error;			/* otherwise we retry ! */		}	} do_launch:	r =subst_vars(cmdline_tmp, cmdline, CMDLINE_MAXLEN);	VERB_PRT(3, Print(L"final cmdline(%d): %s\n", r, cmdline));	/* free resources associated with file accesses (before ExitBootServices) */	close_devices();	/* No console output permitted after create_boot_params()! */	if ((bp=create_boot_params(cmdline, &imem, &cookie)) == 0) goto error;	/* terminate bootservices */	status = BS->ExitBootServices(image, cookie);	if (EFI_ERROR(status)) goto bad_exit;	start_kernel(kd.kentry, bp);	/* NOT REACHED */	ERR_PRT((L"start_kernel() return !"));bad_exit:		/*	 * we are still in BootService mode	 */	ERR_PRT((L"ExitBootServices failed %r", status));error:	free_kmem();	if (imem.start_addr) free(imem.start_addr);	if (bp) free_boot_params(bp);exit_error:	return ELILO_LOAD_ERROR;}static VOIDelilo_help(VOID){		Print(L"-d secs   timeout in 10th of second before booting\n");	Print(L"-h        this help text\n");	Print(L"-V        print version\n");	Print(L"-v        verbose level(can appear multiple times)\n");	Print(L"-a        always check for alternate kernel image\n");	Print(L"-i file   load file as the initial ramdisk\n");	Print(L"-C file   indicate the config file to use\n");	Print(L"-P        parse config file only (verify syntax)\n");	Print(L"-D        enable debug prints\n");	Print(L"-p        force interactive mode\n");	Print(L"-c name   image chooser to use\n");	Print(L"-E        do not force EDD30 variable\n");	sysdeps_print_cmdline_opts();	Print(L"\n");	print_config_options();}/* * XXX: hack to work around a problem with EFI command line argument when booted * from network. In this case, it looks like LoadOptions/LoadOptionsSize contain * garbage */static CHAR16 *default_load_options;static UINTN default_load_options_size;static INTN done_fixups;static VOIDfixupargs(EFI_LOADED_IMAGE *info){	EFI_STATUS status;	EFI_PXE_BASE_CODE *pxe;#define FAKE_ELILONAME	L"elilo-forced"	status = BS->HandleProtocol (info->DeviceHandle, &PxeBaseCodeProtocol, (VOID **)&pxe);	if (EFI_ERROR(status)) return;	default_load_options      = info->LoadOptions;	default_load_options_size = info->LoadOptionsSize;	info->LoadOptions     = FAKE_ELILONAME;	info->LoadOptionsSize = StrLen(info->LoadOptions)*sizeof(CHAR16);	done_fixups = 1;}/* * we restore the arguments in case we modified them just to make sure * we don't confuse caller. */static VOIDunfixupargs(EFI_LOADED_IMAGE *info){	if (done_fixups == 0) return;	info->LoadOptions     = default_load_options;	info->LoadOptionsSize = default_load_options_size;}/* * in order to get fully detailed EFI path names to devices, EDD3.0 specification must * be turned on. On new versions of EFI, this is the default. An environment variable * called EDD30 reflects the current settings. If true, then EDD3.0 is enabled  * and device path names show the detailed device types. If false, then a default  * generic name is used instead. This has some implications of ELILO's ability to  * provide a better naming scheme for detected devices. If EDD3.0 is enabled * then much more precise names can be used which makes it easy to use.  * If EDD3.0 is nont enabled, ELILO will still work but will use very generic names * for devices. * * ELILO will check the value of the variable. If not true, then it will force it to * true. This will require a reboot for EFI to make use of the new value. * Return: * 	EFI_SUCCESS: if variable is already true or was set to true * 	EFI error code: otherwise, like when could not forced variable or unrecognized variable content */#define EDD30_GUID \{0x964e5b21, 0x6459, 0x11d2, { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}}#define EDD30_ATTR (EFI_VARIABLE_RUNTIME_ACCESS|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_NON_VOLATILE)static EFI_GUID edd30_guid = EDD30_GUID;static INTNcheck_edd30(VOID){	EFI_STATUS	status;	UINTN		l = sizeof(BOOLEAN);	UINT8		bool = FALSE;	INTN		ret = -1;	status = RT->GetVariable(L"EDD30", &edd30_guid, NULL, &l, &bool);	if (status == EFI_BUFFER_TOO_SMALL || (bool != TRUE && bool != FALSE)) {		ERR_PRT((L"Warning: EDD30 EFI variable is not boolean value: forcing it to TRUE"));		return -1;	}	if (status == EFI_SUCCESS && bool == TRUE) {		VERB_PRT(3, Print(L"EDD30 is TRUE\n"));		elilo_opt.edd30_on = TRUE;		ret = 0;	} else {		VERB_PRT(4, 			if (status != EFI_SUCCESS) {				Print(L"EDD30 EFI variable not defined\n");			} else {				Print(L"EDD30 EFI variable is false\n");			}		);	}	return ret;}static INTN

⌨️ 快捷键说明

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