├── LICENSE ├── Makefile ├── README.md └── main.c /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Andrew Oakley 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS ?= -std=c99 -Wall -Wextra -pedantic 2 | efi-boot-to-fw-ui : main.c Makefile 3 | $(CC) $(CFLAGS) -o $@ main.c 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | You can now get to the EFI firmware UI screen with some simple shell commands. 2 | As root run: 3 | ``` 4 | $ printf "\x7\x0\x0\x0\x1\x0\x0\x0\x0\x0\x0\x0" > /sys/firmware/efi/efivars/OsIndications-8be4df61-93ca-11d2-aa0d-00e098032b8c 5 | $ reboot 6 | ``` 7 | 8 | This program uses a legacy 'efivars' sysfs interface. This was removed in 9 | Linux 6.0 so the program no longer works. 10 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define EFI_VAR_NAME_LEN 1024 11 | #define EFI_DATA_MAXLEN 1024 12 | 13 | struct guid { 14 | uint32_t a; 15 | uint16_t b; 16 | uint16_t c; 17 | uint8_t d[8]; 18 | }; 19 | 20 | #define EFI_GLOBAL_VARIABLE_GUID (struct guid){ \ 21 | 0x8be4df61, 0x93ca, 0x11d2, \ 22 | { 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } } 23 | 24 | #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 1 25 | 26 | #define EFI_VARIABLE_NON_VOLATILE 1 27 | #define EFI_VARIABLE_BOOTSERVICE_ACCESS 2 28 | #define EFI_VARIABLE_RUNTIME_ACCESS 4 29 | 30 | int main(int argc, char* argv[]) { 31 | if (argc != 1) { 32 | fprintf(stderr, "usage: %s\n", argv[0]); 33 | fprintf(stderr, "\n"); 34 | fprintf(stderr, "Sets firmware UI to open at next boot.\n"); 35 | return 1; 36 | } 37 | 38 | char * name = "OsIndications"; 39 | 40 | struct guid vendor_guid = EFI_GLOBAL_VARIABLE_GUID; 41 | 42 | uint64_t data = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; 43 | unsigned long data_size = sizeof(data); 44 | 45 | unsigned long status = 0; 46 | 47 | uint32_t attributes = 48 | EFI_VARIABLE_NON_VOLATILE | 49 | EFI_VARIABLE_BOOTSERVICE_ACCESS | 50 | EFI_VARIABLE_RUNTIME_ACCESS; 51 | 52 | uint8_t buf[ 53 | EFI_VAR_NAME_LEN + 54 | sizeof(vendor_guid) + 55 | sizeof(data_size) + 56 | EFI_DATA_MAXLEN + 57 | sizeof(status) + 58 | sizeof(attributes)] = { 0 }; 59 | 60 | char efivars_dirname[ 61 | (sizeof("/sys/firmware/efi/vars/") - 1) + 62 | (EFI_VAR_NAME_LEN / 2) + 63 | (sizeof("-") - 1) + 64 | (sizeof("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX") - 1) + 65 | (sizeof("/raw_var") - 1) + 66 | 1]; 67 | sprintf( 68 | efivars_dirname, 69 | "/sys/firmware/efi/vars/" 70 | "%s" 71 | "-" 72 | "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" 73 | "/raw_var", 74 | name, 75 | vendor_guid.a, 76 | vendor_guid.b, 77 | vendor_guid.c, 78 | vendor_guid.d[0], 79 | vendor_guid.d[1], 80 | vendor_guid.d[2], 81 | vendor_guid.d[3], 82 | vendor_guid.d[4], 83 | vendor_guid.d[5], 84 | vendor_guid.d[6], 85 | vendor_guid.d[7]); 86 | 87 | int efi_data_fd = open(efivars_dirname, O_RDWR); 88 | if (efi_data_fd == -1 && errno != ENOENT) { 89 | perror("open EFI variable failed"); 90 | return 1; 91 | } 92 | 93 | if (efi_data_fd != -1) { 94 | ssize_t ret = read(efi_data_fd, buf, sizeof(buf)); 95 | if (ret < 0 || (size_t)ret != sizeof(buf)) { 96 | perror("read EFI variable failed"); 97 | return 1; 98 | } 99 | 100 | uint8_t * buf_ptr = buf; 101 | buf_ptr += EFI_VAR_NAME_LEN; 102 | buf_ptr += sizeof(vendor_guid); 103 | memcpy(buf_ptr, &data_size, sizeof(data_size)); 104 | buf_ptr += sizeof(data_size); 105 | memcpy(buf_ptr, &data, sizeof(data)); 106 | buf_ptr += sizeof(data); 107 | memset(buf_ptr, 0, EFI_DATA_MAXLEN - sizeof(data)); 108 | buf_ptr += EFI_DATA_MAXLEN - sizeof(data); 109 | } else { 110 | efi_data_fd = open("/sys/firmware/efi/vars/new_var", O_WRONLY); 111 | if (efi_data_fd == -1) { 112 | perror("open new EFI variable failed"); 113 | return 1; 114 | } 115 | 116 | uint8_t * buf_ptr = buf; 117 | for (size_t i = 0; name[i] != '\0'; i++) { 118 | buf_ptr[i * 2] = (uint8_t)name[i]; 119 | buf_ptr[i * 2 + 1] = 0; 120 | } 121 | buf_ptr += EFI_VAR_NAME_LEN; 122 | memcpy(buf_ptr, &vendor_guid, sizeof(vendor_guid)); 123 | buf_ptr += sizeof(vendor_guid); 124 | memcpy(buf_ptr, &data_size, sizeof(data_size)); 125 | buf_ptr += sizeof(data_size); 126 | memcpy(buf_ptr, &data, sizeof(data)); 127 | buf_ptr += EFI_DATA_MAXLEN; 128 | memcpy(buf_ptr, &status, sizeof(status)); 129 | buf_ptr += sizeof(status); 130 | memcpy(buf_ptr, &attributes, sizeof(attributes)); 131 | buf_ptr += sizeof(attributes); 132 | } 133 | 134 | ssize_t ret = write(efi_data_fd, buf, sizeof(buf)); 135 | if (ret < 0 || (size_t)ret != sizeof(buf)) { 136 | perror("write EFI variable failed"); 137 | return 1; 138 | } 139 | 140 | fprintf(stdout, "set EFI variable, now reboot to access firmware UI\n"); 141 | return 0; 142 | } 143 | --------------------------------------------------------------------------------