📄 eliloalt.c
字号:
/* * eliloalt.c * * Copyright (C) 2002-2003 Hewlett-Packard Co * Contributed by Stephane Eranian <eranian@hpl.hp.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. * *//* * This program is used to set the EliloAlt EFI variable to influence * how elilo will behave at the next reboot. This variable is used * to boot a certain kernel/configuration only once (debug, for instance). * * This is is supposed to be installed in /usr/sbin/eliloalt and must only * be run by root. */#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <fcntl.h>#include <unistd.h>#include <getopt.h>#include <errno.h>#include <stdint.h>#include <string.h>#include <dirent.h>#define ELILOALT_VERSION "0.02"#define ELILO_ALT_NAME "EliloAlt"#define EFIVAR_DIR "/proc/efi/vars"#define ELILO_ALTVAR EFIVAR_DIR"/"ELILO_ALT_NAME"-00000000-0000-0000-0000-000000000000"#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004typedef unsigned long efi_status_t;typedef uint8_t efi_bool_t;typedef uint16_t efi_char16_t; /* UNICODE character *//* * EFI GUID type definition */typedef struct { uint32_t data1; uint16_t data2; uint16_t data3; uint8_t data4[8];} efi_guid_t;/* * EFI variable structure */typedef struct _efi_variable_t { efi_char16_t variablename[1024/sizeof(efi_char16_t)]; efi_guid_t vendorguid; uint64_t datasize; uint8_t data[1024]; efi_status_t status; uint32_t attributes;} __attribute__((packed)) efi_variable_t;static char *elilo_alt_name = ELILO_ALT_NAME;static struct option cmd_options[]={ { "version", 0, 0, 1}, { "help", 0, 0, 2}, { "delete", 0, 0, 3}, { "print", 0, 0, 4}, { "set", 1, 0, 5}, { 0, 0, 0, 0}};static void fatal_error(char *fmt,...) __attribute__((noreturn));static voidfatal_error(char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); exit(1);}static voidusage(char **argv){ printf("Usage: %s [OPTIONS] cmdline\n", argv[0]); printf( "-h, --help\t\tdisplay this help and exit\n" "--version\t\toutput version information and exit\n" "-s, --set cmdline\tset elilo alternate variable to cmdline\n" "-p, --print\t\tprint elilo alternate variable\n" "-d, --delete\t\tprint elilo alternate variable\n" );}static char *check_proc_efi(int find_entry){ DIR *efi_vars; struct dirent *entry; static char name[1024]; if (getuid() != 0) { fatal_error("This program must be run as root\n"); } efi_vars = opendir(EFIVAR_DIR); if (efi_vars == NULL) { fatal_error("Cannot access %s\n", EFIVAR_DIR); } if (!find_entry) { closedir(efi_vars); return NULL; } /* Find one entry we can open */ while ((entry = readdir(efi_vars)) != NULL) { if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) break; } if (entry == NULL) { fatal_error("Cannot find entry in %s\n", EFIVAR_DIR); } sprintf(name, "%s/%s", EFIVAR_DIR, entry->d_name); closedir(efi_vars); return name;}static voiddelete_var(void){ efi_variable_t var; int fd, r, i; check_proc_efi(0); fd = open(ELILO_ALTVAR, O_WRONLY); if (fd == -1) { fatal_error("variable not defined\n"); } memset(&var, 0, sizeof(var)); for (i=0; i < sizeof(elilo_alt_name); i++) { var.variablename[i] = (efi_char16_t)elilo_alt_name[i]; } /* * we use NULL GUID so no need to initialize it now memset() did it * writing with a datasize=0 will effectively delete the variable. */ r = write(fd, &var, sizeof(var)); if (r != sizeof(var)) { fatal_error("Variable %s defined but invalid content\n", ELILO_ALTVAR); } close(fd);}static voidprint_var(void){ efi_variable_t var; int fd, r, i; check_proc_efi(0); fd = open(ELILO_ALTVAR, O_RDONLY); if (fd == -1) { fatal_error("variable not defined\n"); } memset(&var, 0, sizeof(var)); r = read(fd, &var, sizeof(var)); if (r != sizeof(var)) { fatal_error("Variable %s defined but invalid content\n", ELILO_ALTVAR); } printf("EliloAlt=\""); for(i=0; i < var.datasize; i+=1){ printf("%c", var.data[i]); } printf("\"\n"); close(fd);}static voidset_var(char *cmdline){ efi_variable_t var; int fd, r, i, j, l; char *name; name = check_proc_efi(1); if (cmdline == NULL) { fatal_error("invalid cmdline argument\n"); } l = strlen(cmdline); if (l >= 1024) { fatal_error("Variable content is too long, must be <= 512 characters\n"); } fd = open(name, O_WRONLY); if (fd == -1) { fatal_error("can't open %s: %s\n", ELILO_ALTVAR, strerror(errno)); } memset(&var, 0, sizeof(var)); for (i=0; i < sizeof(elilo_alt_name); i++) { var.variablename[i] = (efi_char16_t)elilo_alt_name[i]; } for (i=0, j=0; i < l; i++, j+=2) { var.data[j] = (efi_char16_t)cmdline[i]; } /* +2 = include char16 for null termination */ var.datasize = j+2; var.attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; /* * we use NULL GUID so no need to initialize it now memset() did it * writing with a datasize=0 will effectively delete the variable. */ r = write(fd, &var, sizeof(var)); if (r != sizeof(var)) { fatal_error("Variable %s defined but invalid content %d\n", ELILO_ALTVAR, r); } close(fd);}intmain(int argc, char **argv){ int c; while ((c=getopt_long(argc, argv,"hdps:", cmd_options, 0)) != -1) { switch(c) { case 0: continue; /* fast path for options */ case 1: printf("Version %s Date: %s\n", ELILOALT_VERSION, __DATE__); exit(0); case 2: case 'h': usage(argv); exit(0); case 3: case 'd': delete_var(); exit(0); case 4: case 'p': print_var(); exit(0); case 5: case 's': set_var(optarg); exit(0); default: fatal_error("Unknown option\n"); } } print_var(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -