📄 elilo.c
字号:
force_edd30(VOID){ EFI_STATUS status; UINTN l = sizeof(BOOLEAN); UINT8 bool; bool = TRUE; status = RT->SetVariable(L"EDD30", &edd30_guid, EDD30_ATTR, l, &bool); if (EFI_ERROR(status)) { ERR_PRT((L"can't set EDD30 variable: ignoring it")); return -1; } VERB_PRT(3, Print(L"EDD30 variable forced to TRUE. You should reboot to take advantage of EDD3.0.\n")); return 0;}/* * That's equivalent of main(): main entry point */EFI_STATUSefi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *system_tab){ CHAR16 *argv[MAX_ARGS]; CHAR16 optstring[MAX_ARGS]; EFI_LOADED_IMAGE *info; EFI_STATUS status, ret = EFI_LOAD_ERROR; INTN argc = 0, c; INTN edd30_status, retry; CHAR16 *ptr, *arglist = NULL; BOOLEAN devices_initialized = FALSE; CHAR16 dpath[FILENAME_MAXLEN]; CHAR16 *devpath; elilo_opt.verbose=0; elilo_opt.debug=0; /* initialize global variable */ systab = system_tab; /* initialize EFI library */ InitializeLib(image, systab); /* * disable the platform watchdog timer if we go interactive * XXX: we should reinstate it once we're done * It seems like with PXE, the timer is set to a few minutes * and sometimes triggers if we stay too long in interactive * mode. * XXX: clean this up ! */ BS->SetWatchdogTimer(0, 0x0, 0, NULL); /* initialize memory allocator */ if (alloc_init() == -1) return EFI_LOAD_ERROR; status = BS->HandleProtocol(image, &LoadedImageProtocol, (VOID **) &info); if (EFI_ERROR(status)) { ERR_PRT((L"image handle does not support LOADED_IMAGE protocol")); return EFI_LOAD_ERROR; } VERB_PRT(5,Print(L"Loaded at 0x%lx size=%d bytes code=%d data=%d\n", info->ImageBase, info->ImageSize, info->ImageCodeType, info->ImageDataType)); /* * verify EDD3.0 status. Users may have to reboot */ edd30_status = check_edd30(); /* * initialize configuration empire */ if (config_init() == -1) goto do_exit; /* * architecture-specific initializations */ if (sysdeps_init(info->DeviceHandle) == -1) goto do_exit; if (sysdeps_register_options() == -1) goto do_exit; /* * This may be required in case Elilo was booted with absolutely no arguments * Elilo's logic is that just like normal Linux programs at least one argument * (argv[0]) exists at all times and that it usually gives the name of the program * (the command used to start it). ERR_PRT((L"LoadOptions=%x OpenSize=%d", info->LoadOptions, info->LoadOptionsSize)); */ /* * in case there is something wrong with the default boot_device * we default to basic fixups and we need to force interactive * mode to make sure the user has a chance of specifying a kernel */ fixupargs(info);#if 0 Print(L"LoadOptions=%x OpenSize=%d\n", info->LoadOptions, info->LoadOptionsSize); { INTN i; for (i=0; i< info->LoadOptionsSize>>1; i++) Print(L"options[%d]=%d (%c)\n", i, ((CHAR16 *)info->LoadOptions)[i], ((CHAR16 *)info->LoadOptions)[i]); }#endif /* * we must copy argument because argify modifies the string. * This caused problems when arguments are coming from NVRAM * as passed by the EFI boot manager * * We add an extra character to the buffer in case the LoadOptions is not * NULL terminated. The extra space will be used to ADD the extra terminator. */ arglist = alloc(info->LoadOptionsSize+sizeof(CHAR16), EfiLoaderData); if (arglist == NULL) { ERR_PRT((L"cannot copy argument list")); return EFI_OUT_OF_RESOURCES; } Memcpy(arglist, info->LoadOptions, info->LoadOptionsSize); argc = argify(arglist,info->LoadOptionsSize, argv); StrCpy(optstring, ELILO_SHARED_CMDLINE_OPTS); StrCat(optstring, sysdeps_get_cmdline_opts()); while ((c=Getopt(argc, argv, optstring)) != -1 ) { switch(c) { case 'a': elilo_opt.alt_check = 1; break; case 'D': elilo_opt.debug = 1; break; case 'p': elilo_opt.prompt = 1; break; case 'v': elilo_opt.verbose++; if (elilo_opt.verbose > 5) elilo_opt.verbose = 5; break; case 'h': elilo_help(); ret = EFI_SUCCESS; goto do_exit; case 'd': /* * zero is a valid value here, so we use the delay-set to mark the * fact that the user specified a value on cmdline. See config.c */ elilo_opt.delay = Atoi(Optarg); elilo_opt.delay_set = 1; break; case 'E': /* don't force EDD30 EFI variable if not already set */ elilo_opt.edd30_no_force = 1; break; case 'i': if (StrLen(Optarg) >= FILENAME_MAXLEN-1) { Print(L"initrd filename is limited to %d characters\n", FILENAME_MAXLEN); goto do_exit; } StrCpy(elilo_opt.initrd, Optarg); break; case 'C': if (StrLen(Optarg) >= FILENAME_MAXLEN-1) { Print(L"config filename is limited to %d characters\n", FILENAME_MAXLEN); goto do_exit; } StrCpy(elilo_opt.config, Optarg); break; case 'M': /* builtin debug tool */ { mmap_desc_t mdesc; if (get_memmap(&mdesc) == -1) { Print(L"Cannot get memory map\n"); return EFI_LOAD_ERROR; } print_memmap(&mdesc); ret = EFI_SUCCESS; goto do_exit; } case 'V': Print(L"ELILO v%s for EFI/%a\n", ELILO_VERSION, ELILO_ARCH); ret = EFI_SUCCESS; goto do_exit; case 'P': /* cmdline only option */ elilo_opt.parse_only = 1; break; case 'c': if (StrLen(Optarg) >= FILENAME_MAXLEN-1) { Print(L"chooser name is limited to %d characters\n", FILENAME_MAXLEN); goto do_exit; } StrCpy(elilo_opt.chooser, Optarg); break; default: /* * try system dependent options before declaring error */ if (sysdeps_getopt(c, Optind, Optarg) == 0) continue; Print(L"Unknown option -%c\n", (CHAR16)c); goto do_exit; } } DBG_PRT((L"Optind=%d optarg=%x argc=%d", Optind, Optarg, argc)); /* * we can't defer this phase any longer... * Must be done after the elilo_opt are initialized (at least partially) */ if (init_devices(info->DeviceHandle) == -1) goto do_exit; devices_initialized = TRUE; devpath = DevicePathToStr(info->FilePath); /* * set per fileops defaults files for configuration and kernel */ fops_setdefaults(elilo_opt.default_configs, elilo_opt.default_kernel, FILENAME_MAXLEN, devpath); /* * XXX: won't be visible if verbose not required from command line */ VERB_PRT(2,Print(L"Default config: %s\nDefault_kernel: %s\n", elilo_opt.default_configs[0].fname, elilo_opt.default_kernel)); /* * use default config file if not specified by user */ ptr = elilo_opt.config[0] == CHAR_NULL ? (retry=1,elilo_opt.default_configs[0].fname) : (retry=0,elilo_opt.config); /* * parse config file (verbose becomes visible if set) */ ret = read_config(ptr); VERB_PRT(1,Print(L"read_config=%r\n", ret)); /* Only try the default config filenames if user did not specify a * config filename on the command line */ if (elilo_opt.config[0] == CHAR_NULL) { while ((ret != EFI_SUCCESS) && (retry < MAX_DEFAULT_CONFIGS) && (elilo_opt.default_configs[retry].fname[0] != CHAR_NULL)) { ptr = elilo_opt.default_configs[retry].fname; ret = read_config(ptr); VERB_PRT(1,Print(L"read_config=%r\n", ret)); retry += 1; } } /* * when the config file is not found, we fail only if: * - the user did not specified interactive mode * - the user did not explicitely specify the config file */ if (ret == EFI_NOT_FOUND || ret == EFI_TFTP_ERROR) { if (elilo_opt.prompt == 0 && elilo_opt.config[0] != CHAR_NULL) { Print(L"config file %s not found\n", ptr); goto do_exit; } fops_getdefault_path(dpath, FILENAME_MAXLEN); if (ret == EFI_TFTP_ERROR) Print(L"no config file found on TFTP server in %s\n", dpath); else Print(L"no config file found in %s\n", dpath); } /* * stop if just doing parsing */ if (elilo_opt.parse_only) { if (ret == EFI_SUCCESS) Print(L"Config file %s parsed successfully\n", ptr); goto do_exit; } /* * if there was an error when parsing the config file, then * we force interactive mode to give a chance to the user. * We also clear the error. */ if (ret && argc == 1) { Print(L"forcing interactive mode because of errors\n"); elilo_opt.prompt = 1; } /* * If EDD30 EFI variable was not set to TRUE (or not defined), we * we try to force it. This will take effect at the next reboot. * * Some controllers don't have EDD30 support, in this case forcing it * may cause problems, therefore we check the edd_no_force option * before making the call. */ if (edd30_status == -1 && elilo_opt.edd30_no_force == 0) { force_edd30(); } ret = EFI_LOAD_ERROR; /* * if the user specified a kernel on the command line * then we don't go to interactive mode even if it * was set in the config file or set because of an * error parsing the config file. */ if (argc > Optind) elilo_opt.prompt = 0; /* set default timeout if going interactive */ if ((elilo_opt.prompt && elilo_opt.timeout == 0)) { elilo_opt.timeout = ELILO_DEFAULT_TIMEOUT; } /* * which chooser we will use */ if (init_chooser(info->DeviceHandle) == -1) { ERR_PRT((L"Cannot find a decent chooser\n")); goto do_exit; } //if (elilo_opt.prompt == 0) VERB_PRT(1, print_devices()); main_loop(info->DeviceHandle, argv, argc, Optind, image); /* should not return */do_exit: unfixupargs(info); //if (arglist) free(arglist); /* free all resources assiocated with file accesses */ if (devices_initialized) close_devices(); /* garbage collect all remaining allocations */ free_all_memory(); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -