Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'efi-next-for-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI updates from Ard Biesheuvel:

- Increase the headroom in the EFI memory map allocation created by the
EFI stub. This is needed because event callbacks called during
ExitBootServices() may cause fragmentation, and reallocation is not
allowed after that.

- Drop obsolete UGA graphics code and switch to a more ergonomic API to
traverse handle buffers. Simplify some error paths using a __free()
helper while at it.

- Fix some W=1 warnings when CONFIG_EFI=n

- Rely on the dentry cache to keep track of the contents of the
efivarfs filesystem, rather than using a separate linked list.

- Improve and extend efivarfs test cases.

- Synchronize efivarfs with underlying variable store on resume from
hibernation - this is needed because the firmware itself or another
OS running on the same machine may have modified it.

- Fix x86 EFI stub build with GCC 15.

- Fix kexec/x86 false positive warning in EFI memory attributes table
sanity check.

* tag 'efi-next-for-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: (23 commits)
x86/efi: skip memattr table on kexec boot
efivarfs: add variable resync after hibernation
efivarfs: abstract initial variable creation routine
efi: libstub: Use '-std=gnu11' to fix build with GCC 15
selftests/efivarfs: add concurrent update tests
selftests/efivarfs: fix tests for failed write removal
efivarfs: fix error on write to new variable leaving remnants
efivarfs: remove unused efivarfs_list
efivarfs: move variable lifetime management into the inodes
selftests/efivarfs: add check for disallowing file truncation
efivarfs: prevent setting of zero size on the inodes in the cache
efi: sysfb_efi: fix W=1 warnings when EFI is not set
efi/libstub: Use __free() helper for pool deallocations
efi/libstub: Use cleanup helpers for freeing copies of the memory map
efi/libstub: Simplify PCI I/O handle buffer traversal
efi/libstub: Refactor and clean up GOP resolution picker code
efi/libstub: Simplify GOP handling code
efi/libstub: Use C99-style for loop to traverse handle buffer
x86/efistub: Drop long obsolete UGA support
efivarfs: make variable_is_present use dcache lookup
...

+737 -703
+3
arch/x86/include/asm/efi.h
··· 250 250 #define __efi64_argmap_allocate_pool(type, size, buffer) \ 251 251 ((type), (size), efi64_zero_upper(buffer)) 252 252 253 + #define __efi64_argmap_locate_handle_buffer(type, proto, key, num, buf) \ 254 + ((type), (proto), (key), efi64_zero_upper(num), efi64_zero_upper(buf)) 255 + 253 256 #define __efi64_argmap_create_event(type, tpl, f, c, event) \ 254 257 ((type), (tpl), (f), (c), efi64_zero_upper(event)) 255 258
-10
arch/x86/platform/efi/efi.c
··· 54 54 #include <asm/uv/uv.h> 55 55 56 56 static unsigned long efi_systab_phys __initdata; 57 - static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR; 58 57 static unsigned long efi_runtime, efi_nr_tables; 59 58 60 59 unsigned long efi_fw_vendor, efi_config_table; 61 60 62 61 static const efi_config_table_type_t arch_tables[] __initconst = { 63 - {UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" }, 64 62 #ifdef CONFIG_X86_UV 65 63 {UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" }, 66 64 #endif ··· 70 72 &efi.acpi20, 71 73 &efi.smbios, 72 74 &efi.smbios3, 73 - &uga_phys, 74 75 #ifdef CONFIG_X86_UV 75 76 &uv_systab_phys, 76 77 #endif ··· 886 889 return true; 887 890 888 891 return false; 889 - } 890 - 891 - char *efi_systab_show_arch(char *str) 892 - { 893 - if (uga_phys != EFI_INVALID_TABLE_ADDR) 894 - str += sprintf(str, "UGA=0x%lx\n", uga_phys); 895 - return str; 896 892 } 897 893 898 894 #define EFI_FIELD(var) efi_ ## var
+5
arch/x86/platform/efi/quirks.c
··· 561 561 562 562 if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) 563 563 ((efi_config_table_64_t *)p)->table = data->smbios; 564 + 565 + /* Do not bother to play with mem attr table across kexec */ 566 + if (!efi_guidcmp(guid, EFI_MEMORY_ATTRIBUTES_TABLE_GUID)) 567 + ((efi_config_table_64_t *)p)->table = EFI_INVALID_TABLE_ADDR; 568 + 564 569 p += sz; 565 570 } 566 571 early_memunmap(tablep, nr_tables * sz);
-3
drivers/firmware/efi/efi.c
··· 148 148 if (efi.smbios != EFI_INVALID_TABLE_ADDR) 149 149 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 150 150 151 - if (IS_ENABLED(CONFIG_X86)) 152 - str = efi_systab_show_arch(str); 153 - 154 151 return str - buf; 155 152 } 156 153
+1 -1
drivers/firmware/efi/libstub/Makefile
··· 11 11 12 12 cflags-$(CONFIG_X86_32) := -march=i386 13 13 cflags-$(CONFIG_X86_64) := -mcmodel=small 14 - cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \ 14 + cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -std=gnu11 \ 15 15 -fPIC -fno-strict-aliasing -mno-red-zone \ 16 16 -mno-mmx -mno-sse -fshort-wchar \ 17 17 -Wno-pointer-sign \
+4 -5
drivers/firmware/efi/libstub/efi-stub-helper.c
··· 47 47 */ 48 48 efi_status_t efi_parse_options(char const *cmdline) 49 49 { 50 - size_t len; 50 + char *buf __free(efi_pool) = NULL; 51 51 efi_status_t status; 52 - char *str, *buf; 52 + size_t len; 53 + char *str; 53 54 54 55 if (!cmdline) 55 56 return EFI_SUCCESS; ··· 103 102 efi_parse_option_graphics(val + strlen("efifb:")); 104 103 } 105 104 } 106 - efi_bs_call(free_pool, buf); 107 105 return EFI_SUCCESS; 108 106 } 109 107 ··· 250 250 u64, const union efistub_event *); 251 251 struct { u32 hash_log_extend_event; } mixed_mode; 252 252 } method; 253 - struct efistub_measured_event *evt; 253 + struct efistub_measured_event *evt __free(efi_pool) = NULL; 254 254 int size = struct_size(evt, tagged_event.tagged_event_data, 255 255 events[event].event_data_len); 256 256 efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; ··· 312 312 313 313 status = efi_fn_call(&method, hash_log_extend_event, protocol, 0, 314 314 load_addr, load_size, &evt->event_data); 315 - efi_bs_call(free_pool, evt); 316 315 317 316 if (status == EFI_SUCCESS) 318 317 return EFI_SUCCESS;
+20 -29
drivers/firmware/efi/libstub/efi-stub.c
··· 10 10 */ 11 11 12 12 #include <linux/efi.h> 13 + #include <linux/screen_info.h> 13 14 #include <asm/efi.h> 14 15 15 16 #include "efistub.h" ··· 54 53 55 54 static struct screen_info *setup_graphics(void) 56 55 { 57 - efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; 58 - efi_status_t status; 59 - unsigned long size; 60 - void **gop_handle = NULL; 61 - struct screen_info *si = NULL; 56 + struct screen_info *si, tmp = {}; 62 57 63 - size = 0; 64 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, 65 - &gop_proto, NULL, &size, gop_handle); 66 - if (status == EFI_BUFFER_TOO_SMALL) { 67 - si = alloc_screen_info(); 68 - if (!si) 69 - return NULL; 70 - status = efi_setup_gop(si, &gop_proto, size); 71 - if (status != EFI_SUCCESS) { 72 - free_screen_info(si); 73 - return NULL; 74 - } 75 - } 58 + if (efi_setup_gop(&tmp) != EFI_SUCCESS) 59 + return NULL; 60 + 61 + si = alloc_screen_info(); 62 + if (!si) 63 + return NULL; 64 + 65 + *si = tmp; 76 66 return si; 77 67 } 78 68 ··· 104 112 105 113 efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr) 106 114 { 115 + char *cmdline __free(efi_pool) = NULL; 107 116 efi_status_t status; 108 - char *cmdline; 109 117 110 118 /* 111 119 * Get the command line from EFI, using the LOADED_IMAGE ··· 120 128 121 129 if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) { 122 130 status = efi_parse_options(cmdline); 123 - if (status != EFI_SUCCESS) 124 - goto fail_free_cmdline; 131 + if (status != EFI_SUCCESS) { 132 + efi_err("Failed to parse EFI load options\n"); 133 + return status; 134 + } 125 135 } 126 136 127 137 if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || 128 138 IS_ENABLED(CONFIG_CMDLINE_FORCE) || 129 139 cmdline[0] == 0) { 130 140 status = efi_parse_options(CONFIG_CMDLINE); 131 - if (status != EFI_SUCCESS) 132 - goto fail_free_cmdline; 141 + if (status != EFI_SUCCESS) { 142 + efi_err("Failed to parse built-in command line\n"); 143 + return status; 144 + } 133 145 } 134 146 135 - *cmdline_ptr = cmdline; 147 + *cmdline_ptr = no_free_ptr(cmdline); 136 148 return EFI_SUCCESS; 137 - 138 - fail_free_cmdline: 139 - efi_err("Failed to parse options\n"); 140 - efi_bs_call(free_pool, cmdline); 141 - return status; 142 149 } 143 150 144 151 efi_status_t efi_stub_common(efi_handle_t handle,
+11 -9
drivers/firmware/efi/libstub/efistub.h
··· 4 4 #define _DRIVERS_FIRMWARE_EFI_EFISTUB_H 5 5 6 6 #include <linux/compiler.h> 7 + #include <linux/cleanup.h> 7 8 #include <linux/efi.h> 8 9 #include <linux/kernel.h> 9 10 #include <linux/kern_levels.h> ··· 123 122 #define efi_get_handle_num(size) \ 124 123 ((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32))) 125 124 126 - #define for_each_efi_handle(handle, array, size, i) \ 127 - for (i = 0; \ 128 - i < efi_get_handle_num(size) && \ 129 - ((handle = efi_get_handle_at((array), i)) || true); \ 130 - i++) 125 + #define for_each_efi_handle(handle, array, num) \ 126 + for (int __i = 0; __i < (num) && \ 127 + ((handle = efi_get_handle_at((array), __i)) || true); \ 128 + __i++) 131 129 132 130 static inline 133 131 void efi_set_u64_split(u64 data, u32 *lo, u32 *hi) ··· 171 171 * the EFI memory map. Other related structures, e.g. x86 e820ext, need 172 172 * to factor in this headroom requirement as well. 173 173 */ 174 - #define EFI_MMAP_NR_SLACK_SLOTS 8 174 + #define EFI_MMAP_NR_SLACK_SLOTS 32 175 175 176 176 typedef struct efi_generic_dev_path efi_device_path_protocol_t; 177 177 ··· 314 314 void *close_protocol; 315 315 void *open_protocol_information; 316 316 void *protocols_per_handle; 317 - void *locate_handle_buffer; 317 + efi_status_t (__efiapi *locate_handle_buffer)(int, efi_guid_t *, 318 + void *, unsigned long *, 319 + efi_handle_t **); 318 320 efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *, 319 321 void **); 320 322 efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...); ··· 1055 1053 __printf(1, 2) int efi_printk(char const *fmt, ...); 1056 1054 1057 1055 void efi_free(unsigned long size, unsigned long addr); 1056 + DEFINE_FREE(efi_pool, void *, if (_T) efi_bs_call(free_pool, _T)); 1058 1057 1059 1058 void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size); 1060 1059 ··· 1085 1082 1086 1083 void efi_parse_option_graphics(char *option); 1087 1084 1088 - efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, 1089 - unsigned long size); 1085 + efi_status_t efi_setup_gop(struct screen_info *si); 1090 1086 1091 1087 efi_status_t handle_cmdline_files(efi_loaded_image_t *image, 1092 1088 const efi_char16_t *optstr,
+124 -203
drivers/firmware/efi/libstub/gop.c
··· 133 133 134 134 static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop) 135 135 { 136 - efi_status_t status; 137 - 136 + efi_graphics_output_mode_info_t *info __free(efi_pool) = NULL; 138 137 efi_graphics_output_protocol_mode_t *mode; 139 - efi_graphics_output_mode_info_t *info; 140 138 unsigned long info_size; 141 - 142 139 u32 max_mode, cur_mode; 140 + efi_status_t status; 143 141 int pf; 144 142 145 143 mode = efi_table_attr(gop, mode); ··· 152 154 return cur_mode; 153 155 } 154 156 155 - status = efi_call_proto(gop, query_mode, cmdline.mode, 156 - &info_size, &info); 157 + status = efi_call_proto(gop, query_mode, cmdline.mode, &info_size, &info); 157 158 if (status != EFI_SUCCESS) { 158 159 efi_err("Couldn't get mode information\n"); 159 160 return cur_mode; 160 161 } 161 162 162 163 pf = info->pixel_format; 163 - 164 - efi_bs_call(free_pool, info); 165 - 166 164 if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) { 167 165 efi_err("Invalid PixelFormat\n"); 168 166 return cur_mode; 169 167 } 170 168 171 169 return cmdline.mode; 170 + } 171 + 172 + static u32 choose_mode(efi_graphics_output_protocol_t *gop, 173 + bool (*match)(const efi_graphics_output_mode_info_t *, u32, void *), 174 + void *ctx) 175 + { 176 + efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode); 177 + u32 max_mode = efi_table_attr(mode, max_mode); 178 + 179 + for (u32 m = 0; m < max_mode; m++) { 180 + efi_graphics_output_mode_info_t *info __free(efi_pool) = NULL; 181 + unsigned long info_size; 182 + efi_status_t status; 183 + 184 + status = efi_call_proto(gop, query_mode, m, &info_size, &info); 185 + if (status != EFI_SUCCESS) 186 + continue; 187 + 188 + if (match(info, m, ctx)) 189 + return m; 190 + } 191 + return (unsigned long)ctx; 172 192 } 173 193 174 194 static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info) ··· 201 185 return 32; 202 186 } 203 187 188 + static bool match_res(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx) 189 + { 190 + efi_pixel_bitmask_t pi = info->pixel_information; 191 + int pf = info->pixel_format; 192 + 193 + if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) 194 + return false; 195 + 196 + return cmdline.res.width == info->horizontal_resolution && 197 + cmdline.res.height == info->vertical_resolution && 198 + (cmdline.res.format < 0 || cmdline.res.format == pf) && 199 + (!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)); 200 + } 201 + 204 202 static u32 choose_mode_res(efi_graphics_output_protocol_t *gop) 205 203 { 206 - efi_status_t status; 204 + efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode); 205 + unsigned long cur_mode = efi_table_attr(mode, mode); 207 206 208 - efi_graphics_output_protocol_mode_t *mode; 209 - efi_graphics_output_mode_info_t *info; 210 - unsigned long info_size; 211 - 212 - u32 max_mode, cur_mode; 213 - int pf; 214 - efi_pixel_bitmask_t pi; 215 - u32 m, w, h; 216 - 217 - mode = efi_table_attr(gop, mode); 218 - 219 - cur_mode = efi_table_attr(mode, mode); 220 - info = efi_table_attr(mode, info); 221 - pf = info->pixel_format; 222 - pi = info->pixel_information; 223 - w = info->horizontal_resolution; 224 - h = info->vertical_resolution; 225 - 226 - if (w == cmdline.res.width && h == cmdline.res.height && 227 - (cmdline.res.format < 0 || cmdline.res.format == pf) && 228 - (!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi))) 207 + if (match_res(efi_table_attr(mode, info), cur_mode, NULL)) 229 208 return cur_mode; 230 209 231 - max_mode = efi_table_attr(mode, max_mode); 210 + return choose_mode(gop, match_res, (void *)cur_mode); 211 + } 232 212 233 - for (m = 0; m < max_mode; m++) { 234 - if (m == cur_mode) 235 - continue; 213 + struct match { 214 + u32 mode; 215 + u32 area; 216 + u8 depth; 217 + }; 236 218 237 - status = efi_call_proto(gop, query_mode, m, 238 - &info_size, &info); 239 - if (status != EFI_SUCCESS) 240 - continue; 219 + static bool match_auto(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx) 220 + { 221 + u32 area = info->horizontal_resolution * info->vertical_resolution; 222 + efi_pixel_bitmask_t pi = info->pixel_information; 223 + int pf = info->pixel_format; 224 + u8 depth = pixel_bpp(pf, pi); 225 + struct match *m = ctx; 241 226 242 - pf = info->pixel_format; 243 - pi = info->pixel_information; 244 - w = info->horizontal_resolution; 245 - h = info->vertical_resolution; 227 + if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) 228 + return false; 246 229 247 - efi_bs_call(free_pool, info); 230 + if (area > m->area || (area == m->area && depth > m->depth)) 231 + *m = (struct match){ mode, area, depth }; 248 232 249 - if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) 250 - continue; 251 - if (w == cmdline.res.width && h == cmdline.res.height && 252 - (cmdline.res.format < 0 || cmdline.res.format == pf) && 253 - (!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi))) 254 - return m; 255 - } 256 - 257 - efi_err("Couldn't find requested mode\n"); 258 - 259 - return cur_mode; 233 + return false; 260 234 } 261 235 262 236 static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop) 263 237 { 264 - efi_status_t status; 238 + struct match match = {}; 265 239 266 - efi_graphics_output_protocol_mode_t *mode; 267 - efi_graphics_output_mode_info_t *info; 268 - unsigned long info_size; 240 + choose_mode(gop, match_auto, &match); 269 241 270 - u32 max_mode, cur_mode, best_mode, area; 271 - u8 depth; 272 - int pf; 273 - efi_pixel_bitmask_t pi; 274 - u32 m, w, h, a; 275 - u8 d; 242 + return match.mode; 243 + } 276 244 277 - mode = efi_table_attr(gop, mode); 245 + static bool match_list(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx) 246 + { 247 + efi_pixel_bitmask_t pi = info->pixel_information; 248 + u32 cur_mode = (unsigned long)ctx; 249 + int pf = info->pixel_format; 250 + const char *dstr; 251 + u8 depth = 0; 252 + bool valid; 278 253 279 - cur_mode = efi_table_attr(mode, mode); 280 - max_mode = efi_table_attr(mode, max_mode); 254 + valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX); 281 255 282 - info = efi_table_attr(mode, info); 283 - 284 - pf = info->pixel_format; 285 - pi = info->pixel_information; 286 - w = info->horizontal_resolution; 287 - h = info->vertical_resolution; 288 - 289 - best_mode = cur_mode; 290 - area = w * h; 291 - depth = pixel_bpp(pf, pi); 292 - 293 - for (m = 0; m < max_mode; m++) { 294 - if (m == cur_mode) 295 - continue; 296 - 297 - status = efi_call_proto(gop, query_mode, m, 298 - &info_size, &info); 299 - if (status != EFI_SUCCESS) 300 - continue; 301 - 302 - pf = info->pixel_format; 303 - pi = info->pixel_information; 304 - w = info->horizontal_resolution; 305 - h = info->vertical_resolution; 306 - 307 - efi_bs_call(free_pool, info); 308 - 309 - if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) 310 - continue; 311 - a = w * h; 312 - if (a < area) 313 - continue; 314 - d = pixel_bpp(pf, pi); 315 - if (a > area || d > depth) { 316 - best_mode = m; 317 - area = a; 318 - depth = d; 319 - } 256 + switch (pf) { 257 + case PIXEL_RGB_RESERVED_8BIT_PER_COLOR: 258 + dstr = "rgb"; 259 + break; 260 + case PIXEL_BGR_RESERVED_8BIT_PER_COLOR: 261 + dstr = "bgr"; 262 + break; 263 + case PIXEL_BIT_MASK: 264 + dstr = ""; 265 + depth = pixel_bpp(pf, pi); 266 + break; 267 + case PIXEL_BLT_ONLY: 268 + dstr = "blt"; 269 + break; 270 + default: 271 + dstr = "xxx"; 272 + break; 320 273 } 321 274 322 - return best_mode; 275 + efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n", 276 + mode, 277 + (mode == cur_mode) ? '*' : ' ', 278 + !valid ? '-' : ' ', 279 + info->horizontal_resolution, 280 + info->vertical_resolution, 281 + dstr, depth); 282 + 283 + return false; 323 284 } 324 285 325 286 static u32 choose_mode_list(efi_graphics_output_protocol_t *gop) 326 287 { 327 - efi_status_t status; 328 - 329 - efi_graphics_output_protocol_mode_t *mode; 330 - efi_graphics_output_mode_info_t *info; 331 - unsigned long info_size; 332 - 333 - u32 max_mode, cur_mode; 334 - int pf; 335 - efi_pixel_bitmask_t pi; 336 - u32 m, w, h; 337 - u8 d; 338 - const char *dstr; 339 - bool valid; 288 + efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode); 289 + unsigned long cur_mode = efi_table_attr(mode, mode); 290 + u32 max_mode = efi_table_attr(mode, max_mode); 340 291 efi_input_key_t key; 341 - 342 - mode = efi_table_attr(gop, mode); 343 - 344 - cur_mode = efi_table_attr(mode, mode); 345 - max_mode = efi_table_attr(mode, max_mode); 292 + efi_status_t status; 346 293 347 294 efi_printk("Available graphics modes are 0-%u\n", max_mode-1); 348 295 efi_puts(" * = current mode\n" 349 296 " - = unusable mode\n"); 350 - for (m = 0; m < max_mode; m++) { 351 - status = efi_call_proto(gop, query_mode, m, 352 - &info_size, &info); 353 - if (status != EFI_SUCCESS) 354 - continue; 355 297 356 - pf = info->pixel_format; 357 - pi = info->pixel_information; 358 - w = info->horizontal_resolution; 359 - h = info->vertical_resolution; 360 - 361 - efi_bs_call(free_pool, info); 362 - 363 - valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX); 364 - d = 0; 365 - switch (pf) { 366 - case PIXEL_RGB_RESERVED_8BIT_PER_COLOR: 367 - dstr = "rgb"; 368 - break; 369 - case PIXEL_BGR_RESERVED_8BIT_PER_COLOR: 370 - dstr = "bgr"; 371 - break; 372 - case PIXEL_BIT_MASK: 373 - dstr = ""; 374 - d = pixel_bpp(pf, pi); 375 - break; 376 - case PIXEL_BLT_ONLY: 377 - dstr = "blt"; 378 - break; 379 - default: 380 - dstr = "xxx"; 381 - break; 382 - } 383 - 384 - efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n", 385 - m, 386 - m == cur_mode ? '*' : ' ', 387 - !valid ? '-' : ' ', 388 - w, h, dstr, d); 389 - } 298 + choose_mode(gop, match_list, (void *)cur_mode); 390 299 391 300 efi_puts("\nPress any key to continue (or wait 10 seconds)\n"); 392 301 status = efi_wait_for_key(10 * EFI_USEC_PER_SEC, &key); ··· 402 461 } 403 462 } 404 463 405 - static efi_graphics_output_protocol_t * 406 - find_gop(efi_guid_t *proto, unsigned long size, void **handles) 464 + static efi_graphics_output_protocol_t *find_gop(unsigned long num, 465 + const efi_handle_t handles[]) 407 466 { 408 467 efi_graphics_output_protocol_t *first_gop; 409 468 efi_handle_t h; 410 - int i; 411 469 412 470 first_gop = NULL; 413 471 414 - for_each_efi_handle(h, handles, size, i) { 472 + for_each_efi_handle(h, handles, num) { 415 473 efi_status_t status; 416 474 417 475 efi_graphics_output_protocol_t *gop; 418 476 efi_graphics_output_protocol_mode_t *mode; 419 477 efi_graphics_output_mode_info_t *info; 420 - 421 - efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; 422 478 void *dummy = NULL; 423 479 424 - status = efi_bs_call(handle_protocol, h, proto, (void **)&gop); 480 + status = efi_bs_call(handle_protocol, h, 481 + &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, 482 + (void **)&gop); 425 483 if (status != EFI_SUCCESS) 426 484 continue; 427 485 ··· 440 500 * Once we've found a GOP supporting ConOut, 441 501 * don't bother looking any further. 442 502 */ 443 - status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy); 503 + status = efi_bs_call(handle_protocol, h, 504 + &EFI_CONSOLE_OUT_DEVICE_GUID, &dummy); 444 505 if (status == EFI_SUCCESS) 445 506 return gop; 446 507 ··· 452 511 return first_gop; 453 512 } 454 513 455 - static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, 456 - unsigned long size, void **handles) 514 + efi_status_t efi_setup_gop(struct screen_info *si) 457 515 { 458 - efi_graphics_output_protocol_t *gop; 516 + efi_handle_t *handles __free(efi_pool) = NULL; 459 517 efi_graphics_output_protocol_mode_t *mode; 460 518 efi_graphics_output_mode_info_t *info; 519 + efi_graphics_output_protocol_t *gop; 520 + efi_status_t status; 521 + unsigned long num; 461 522 462 - gop = find_gop(proto, size, handles); 523 + status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL, 524 + &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, NULL, &num, 525 + &handles); 526 + if (status != EFI_SUCCESS) 527 + return status; 463 528 464 - /* Did we find any GOPs? */ 529 + gop = find_gop(num, handles); 465 530 if (!gop) 466 531 return EFI_NOT_FOUND; 467 532 ··· 498 551 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; 499 552 500 553 return EFI_SUCCESS; 501 - } 502 - 503 - /* 504 - * See if we have Graphics Output Protocol 505 - */ 506 - efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, 507 - unsigned long size) 508 - { 509 - efi_status_t status; 510 - void **gop_handle = NULL; 511 - 512 - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, 513 - (void **)&gop_handle); 514 - if (status != EFI_SUCCESS) 515 - return status; 516 - 517 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, proto, NULL, 518 - &size, gop_handle); 519 - if (status != EFI_SUCCESS) 520 - goto free_handle; 521 - 522 - status = setup_gop(si, proto, size, gop_handle); 523 - 524 - free_handle: 525 - efi_bs_call(free_pool, gop_handle); 526 - return status; 527 554 }
+1 -3
drivers/firmware/efi/libstub/kaslr.c
··· 57 57 */ 58 58 static bool check_image_region(u64 base, u64 size) 59 59 { 60 - struct efi_boot_memmap *map; 60 + struct efi_boot_memmap *map __free(efi_pool) = NULL; 61 61 efi_status_t status; 62 62 bool ret = false; 63 63 int map_offset; ··· 79 79 break; 80 80 } 81 81 } 82 - 83 - efi_bs_call(free_pool, map); 84 82 85 83 return ret; 86 84 }
+8 -12
drivers/firmware/efi/libstub/mem.c
··· 20 20 efi_status_t efi_get_memory_map(struct efi_boot_memmap **map, 21 21 bool install_cfg_tbl) 22 22 { 23 + struct efi_boot_memmap tmp, *m __free(efi_pool) = NULL; 23 24 int memtype = install_cfg_tbl ? EFI_ACPI_RECLAIM_MEMORY 24 25 : EFI_LOADER_DATA; 25 26 efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID; 26 - struct efi_boot_memmap *m, tmp; 27 27 efi_status_t status; 28 28 unsigned long size; 29 29 ··· 48 48 */ 49 49 status = efi_bs_call(install_configuration_table, &tbl_guid, m); 50 50 if (status != EFI_SUCCESS) 51 - goto free_map; 51 + return status; 52 52 } 53 53 54 54 m->buff_size = m->map_size = size; 55 55 status = efi_bs_call(get_memory_map, &m->map_size, m->map, &m->map_key, 56 56 &m->desc_size, &m->desc_ver); 57 - if (status != EFI_SUCCESS) 58 - goto uninstall_table; 57 + if (status != EFI_SUCCESS) { 58 + if (install_cfg_tbl) 59 + efi_bs_call(install_configuration_table, &tbl_guid, NULL); 60 + return status; 61 + } 59 62 60 - *map = m; 63 + *map = no_free_ptr(m); 61 64 return EFI_SUCCESS; 62 - 63 - uninstall_table: 64 - if (install_cfg_tbl) 65 - efi_bs_call(install_configuration_table, &tbl_guid, NULL); 66 - free_map: 67 - efi_bs_call(free_pool, m); 68 - return status; 69 65 } 70 66 71 67 /**
+8 -28
drivers/firmware/efi/libstub/pci.c
··· 16 16 void efi_pci_disable_bridge_busmaster(void) 17 17 { 18 18 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; 19 - unsigned long pci_handle_size = 0; 20 - efi_handle_t *pci_handle = NULL; 19 + efi_handle_t *pci_handle __free(efi_pool) = NULL; 20 + unsigned long pci_handle_num; 21 21 efi_handle_t handle; 22 22 efi_status_t status; 23 23 u16 class, command; 24 - int i; 25 24 26 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto, 27 - NULL, &pci_handle_size, NULL); 28 - 29 - if (status != EFI_BUFFER_TOO_SMALL) { 30 - if (status != EFI_SUCCESS && status != EFI_NOT_FOUND) 31 - efi_err("Failed to locate PCI I/O handles'\n"); 25 + status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL, 26 + &pci_proto, NULL, &pci_handle_num, &pci_handle); 27 + if (status != EFI_SUCCESS) { 28 + efi_err("Failed to locate PCI I/O handles\n"); 32 29 return; 33 30 } 34 31 35 - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, pci_handle_size, 36 - (void **)&pci_handle); 37 - if (status != EFI_SUCCESS) { 38 - efi_err("Failed to allocate memory for 'pci_handle'\n"); 39 - return; 40 - } 41 - 42 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto, 43 - NULL, &pci_handle_size, pci_handle); 44 - if (status != EFI_SUCCESS) { 45 - efi_err("Failed to locate PCI I/O handles'\n"); 46 - goto free_handle; 47 - } 48 - 49 - for_each_efi_handle(handle, pci_handle, pci_handle_size, i) { 32 + for_each_efi_handle(handle, pci_handle, pci_handle_num) { 50 33 efi_pci_io_protocol_t *pci; 51 34 unsigned long segment_nr, bus_nr, device_nr, func_nr; 52 35 ··· 65 82 efi_bs_call(disconnect_controller, handle, NULL, NULL); 66 83 } 67 84 68 - for_each_efi_handle(handle, pci_handle, pci_handle_size, i) { 85 + for_each_efi_handle(handle, pci_handle, pci_handle_num) { 69 86 efi_pci_io_protocol_t *pci; 70 87 71 88 status = efi_bs_call(handle_protocol, handle, &pci_proto, ··· 91 108 if (status != EFI_SUCCESS) 92 109 efi_err("Failed to disable PCI busmastering\n"); 93 110 } 94 - 95 - free_handle: 96 - efi_bs_call(free_pool, pci_handle); 97 111 }
+1 -3
drivers/firmware/efi/libstub/randomalloc.c
··· 59 59 unsigned long alloc_min, 60 60 unsigned long alloc_max) 61 61 { 62 + struct efi_boot_memmap *map __free(efi_pool) = NULL; 62 63 unsigned long total_slots = 0, target_slot; 63 64 unsigned long total_mirrored_slots = 0; 64 - struct efi_boot_memmap *map; 65 65 efi_status_t status; 66 66 int map_offset; 67 67 ··· 129 129 *addr = target; 130 130 break; 131 131 } 132 - 133 - efi_bs_call(free_pool, map); 134 132 135 133 return status; 136 134 }
+4 -6
drivers/firmware/efi/libstub/relocate.c
··· 23 23 efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, 24 24 unsigned long *addr, unsigned long min) 25 25 { 26 - struct efi_boot_memmap *map; 26 + struct efi_boot_memmap *map __free(efi_pool) = NULL; 27 27 efi_status_t status; 28 28 unsigned long nr_pages; 29 29 int i; 30 30 31 31 status = efi_get_memory_map(&map, false); 32 32 if (status != EFI_SUCCESS) 33 - goto fail; 33 + return status; 34 34 35 35 /* 36 36 * Enforce minimum alignment that EFI or Linux requires when ··· 79 79 } 80 80 81 81 if (i == map->map_size / map->desc_size) 82 - status = EFI_NOT_FOUND; 82 + return EFI_NOT_FOUND; 83 83 84 - efi_bs_call(free_pool, map); 85 - fail: 86 - return status; 84 + return EFI_SUCCESS; 87 85 } 88 86 89 87 /**
+20 -144
drivers/firmware/efi/libstub/x86-stub.c
··· 42 42 static efi_status_t 43 43 preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) 44 44 { 45 - struct pci_setup_rom *rom = NULL; 45 + struct pci_setup_rom *rom __free(efi_pool) = NULL; 46 46 efi_status_t status; 47 47 unsigned long size; 48 48 uint64_t romsize; ··· 75 75 rom->data.len = size - sizeof(struct setup_data); 76 76 rom->data.next = 0; 77 77 rom->pcilen = romsize; 78 - *__rom = rom; 79 78 80 79 status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16, 81 80 PCI_VENDOR_ID, 1, &rom->vendor); 82 81 83 82 if (status != EFI_SUCCESS) { 84 83 efi_err("Failed to read rom->vendor\n"); 85 - goto free_struct; 84 + return status; 86 85 } 87 86 88 87 status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16, ··· 89 90 90 91 if (status != EFI_SUCCESS) { 91 92 efi_err("Failed to read rom->devid\n"); 92 - goto free_struct; 93 + return status; 93 94 } 94 95 95 96 status = efi_call_proto(pci, get_location, &rom->segment, &rom->bus, 96 97 &rom->device, &rom->function); 97 98 98 99 if (status != EFI_SUCCESS) 99 - goto free_struct; 100 + return status; 100 101 101 102 memcpy(rom->romdata, romimage, romsize); 102 - return status; 103 - 104 - free_struct: 105 - efi_bs_call(free_pool, rom); 106 - return status; 103 + *__rom = no_free_ptr(rom); 104 + return EFI_SUCCESS; 107 105 } 108 106 109 107 /* ··· 115 119 static void setup_efi_pci(struct boot_params *params) 116 120 { 117 121 efi_status_t status; 118 - void **pci_handle = NULL; 122 + efi_handle_t *pci_handle __free(efi_pool) = NULL; 119 123 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; 120 - unsigned long size = 0; 121 124 struct setup_data *data; 125 + unsigned long num; 122 126 efi_handle_t h; 123 - int i; 124 127 125 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, 126 - &pci_proto, NULL, &size, pci_handle); 127 - 128 - if (status == EFI_BUFFER_TOO_SMALL) { 129 - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, 130 - (void **)&pci_handle); 131 - 132 - if (status != EFI_SUCCESS) { 133 - efi_err("Failed to allocate memory for 'pci_handle'\n"); 134 - return; 135 - } 136 - 137 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, 138 - &pci_proto, NULL, &size, pci_handle); 139 - } 140 - 128 + status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL, 129 + &pci_proto, NULL, &num, &pci_handle); 141 130 if (status != EFI_SUCCESS) 142 - goto free_handle; 131 + return; 143 132 144 133 data = (struct setup_data *)(unsigned long)params->hdr.setup_data; 145 134 146 135 while (data && data->next) 147 136 data = (struct setup_data *)(unsigned long)data->next; 148 137 149 - for_each_efi_handle(h, pci_handle, size, i) { 138 + for_each_efi_handle(h, pci_handle, num) { 150 139 efi_pci_io_protocol_t *pci = NULL; 151 140 struct pci_setup_rom *rom; 152 141 ··· 151 170 152 171 data = (struct setup_data *)rom; 153 172 } 154 - 155 - free_handle: 156 - efi_bs_call(free_pool, pci_handle); 157 173 } 158 174 159 175 static void retrieve_apple_device_properties(struct boot_params *boot_params) ··· 383 405 } 384 406 } 385 407 386 - /* 387 - * See if we have Universal Graphics Adapter (UGA) protocol 388 - */ 389 - static efi_status_t 390 - setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size) 391 - { 392 - efi_status_t status; 393 - u32 width, height; 394 - void **uga_handle = NULL; 395 - efi_uga_draw_protocol_t *uga = NULL, *first_uga; 396 - efi_handle_t handle; 397 - int i; 398 - 399 - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, 400 - (void **)&uga_handle); 401 - if (status != EFI_SUCCESS) 402 - return status; 403 - 404 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, 405 - uga_proto, NULL, &size, uga_handle); 406 - if (status != EFI_SUCCESS) 407 - goto free_handle; 408 - 409 - height = 0; 410 - width = 0; 411 - 412 - first_uga = NULL; 413 - for_each_efi_handle(handle, uga_handle, size, i) { 414 - efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; 415 - u32 w, h, depth, refresh; 416 - void *pciio; 417 - 418 - status = efi_bs_call(handle_protocol, handle, uga_proto, 419 - (void **)&uga); 420 - if (status != EFI_SUCCESS) 421 - continue; 422 - 423 - pciio = NULL; 424 - efi_bs_call(handle_protocol, handle, &pciio_proto, &pciio); 425 - 426 - status = efi_call_proto(uga, get_mode, &w, &h, &depth, &refresh); 427 - if (status == EFI_SUCCESS && (!first_uga || pciio)) { 428 - width = w; 429 - height = h; 430 - 431 - /* 432 - * Once we've found a UGA supporting PCIIO, 433 - * don't bother looking any further. 434 - */ 435 - if (pciio) 436 - break; 437 - 438 - first_uga = uga; 439 - } 440 - } 441 - 442 - if (!width && !height) 443 - goto free_handle; 444 - 445 - /* EFI framebuffer */ 446 - si->orig_video_isVGA = VIDEO_TYPE_EFI; 447 - 448 - si->lfb_depth = 32; 449 - si->lfb_width = width; 450 - si->lfb_height = height; 451 - 452 - si->red_size = 8; 453 - si->red_pos = 16; 454 - si->green_size = 8; 455 - si->green_pos = 8; 456 - si->blue_size = 8; 457 - si->blue_pos = 0; 458 - si->rsvd_size = 8; 459 - si->rsvd_pos = 24; 460 - 461 - free_handle: 462 - efi_bs_call(free_pool, uga_handle); 463 - 464 - return status; 465 - } 466 - 467 408 static void setup_graphics(struct boot_params *boot_params) 468 409 { 469 - efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; 470 - struct screen_info *si; 471 - efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; 472 - efi_status_t status; 473 - unsigned long size; 474 - void **gop_handle = NULL; 475 - void **uga_handle = NULL; 410 + struct screen_info *si = memset(&boot_params->screen_info, 0, sizeof(*si)); 476 411 477 - si = &boot_params->screen_info; 478 - memset(si, 0, sizeof(*si)); 479 - 480 - size = 0; 481 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, 482 - &graphics_proto, NULL, &size, gop_handle); 483 - if (status == EFI_BUFFER_TOO_SMALL) 484 - status = efi_setup_gop(si, &graphics_proto, size); 485 - 486 - if (status != EFI_SUCCESS) { 487 - size = 0; 488 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, 489 - &uga_proto, NULL, &size, uga_handle); 490 - if (status == EFI_BUFFER_TOO_SMALL) 491 - setup_uga(si, &uga_proto, size); 492 - } 412 + efi_setup_gop(si); 493 413 } 494 - 495 414 496 415 static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status) 497 416 { ··· 612 737 struct setup_data **e820ext, 613 738 u32 *e820ext_size) 614 739 { 615 - struct efi_boot_memmap *map; 740 + struct efi_boot_memmap *map __free(efi_pool) = NULL; 616 741 efi_status_t status; 617 742 __u32 nr_desc; 618 743 ··· 626 751 EFI_MMAP_NR_SLACK_SLOTS; 627 752 628 753 status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size); 754 + if (status != EFI_SUCCESS) 755 + return status; 629 756 } 630 757 631 - if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) && status == EFI_SUCCESS) 632 - status = allocate_unaccepted_bitmap(nr_desc, map); 758 + if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY)) 759 + return allocate_unaccepted_bitmap(nr_desc, map); 633 760 634 - efi_bs_call(free_pool, map); 635 - return status; 761 + return EFI_SUCCESS; 636 762 } 637 763 638 764 struct exit_boot_struct {
+1 -1
drivers/firmware/efi/sysfb_efi.c
··· 91 91 _ret_; \ 92 92 }) 93 93 94 + #ifdef CONFIG_EFI 94 95 static int __init efifb_set_system(const struct dmi_system_id *id) 95 96 { 96 97 struct efifb_dmi_info *info = id->driver_data; ··· 347 346 .add_links = efifb_add_links, 348 347 }; 349 348 350 - #ifdef CONFIG_EFI 351 349 static struct fwnode_handle efifb_fwnode; 352 350 353 351 __init void sysfb_apply_efi_quirks(void)
+50 -9
fs/efivarfs/file.c
··· 36 36 if (IS_ERR(data)) 37 37 return PTR_ERR(data); 38 38 39 + inode_lock(inode); 40 + if (var->removed) { 41 + /* 42 + * file got removed; don't allow a set. Caused by an 43 + * unsuccessful create or successful delete write 44 + * racing with us. 45 + */ 46 + bytes = -EIO; 47 + goto out; 48 + } 49 + 39 50 bytes = efivar_entry_set_get_size(var, attributes, &datasize, 40 51 data, &set); 41 - if (!set && bytes) { 52 + if (!set) { 42 53 if (bytes == -ENOENT) 43 54 bytes = -EIO; 44 55 goto out; 45 56 } 46 57 47 58 if (bytes == -ENOENT) { 48 - drop_nlink(inode); 49 - d_delete(file->f_path.dentry); 50 - dput(file->f_path.dentry); 59 + /* 60 + * zero size signals to release that the write deleted 61 + * the variable 62 + */ 63 + i_size_write(inode, 0); 51 64 } else { 52 - inode_lock(inode); 53 65 i_size_write(inode, datasize + sizeof(attributes)); 54 66 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); 55 - inode_unlock(inode); 56 67 } 57 68 58 69 bytes = count; 59 70 60 71 out: 72 + inode_unlock(inode); 73 + 61 74 kfree(data); 62 75 63 76 return bytes; ··· 119 106 return size; 120 107 } 121 108 109 + static int efivarfs_file_release(struct inode *inode, struct file *file) 110 + { 111 + struct efivar_entry *var = inode->i_private; 112 + 113 + inode_lock(inode); 114 + var->removed = (--var->open_count == 0 && i_size_read(inode) == 0); 115 + inode_unlock(inode); 116 + 117 + if (var->removed) 118 + simple_recursive_removal(file->f_path.dentry, NULL); 119 + 120 + return 0; 121 + } 122 + 123 + static int efivarfs_file_open(struct inode *inode, struct file *file) 124 + { 125 + struct efivar_entry *entry = inode->i_private; 126 + 127 + file->private_data = entry; 128 + 129 + inode_lock(inode); 130 + entry->open_count++; 131 + inode_unlock(inode); 132 + 133 + return 0; 134 + } 135 + 122 136 const struct file_operations efivarfs_file_operations = { 123 - .open = simple_open, 124 - .read = efivarfs_file_read, 125 - .write = efivarfs_file_write, 137 + .open = efivarfs_file_open, 138 + .read = efivarfs_file_read, 139 + .write = efivarfs_file_write, 140 + .release = efivarfs_file_release, 126 141 };
+30 -28
fs/efivarfs/inode.c
··· 77 77 static int efivarfs_create(struct mnt_idmap *idmap, struct inode *dir, 78 78 struct dentry *dentry, umode_t mode, bool excl) 79 79 { 80 - struct efivarfs_fs_info *info = dir->i_sb->s_fs_info; 81 80 struct inode *inode = NULL; 82 81 struct efivar_entry *var; 83 82 int namelen, i = 0, err = 0; 84 83 bool is_removable = false; 84 + efi_guid_t vendor; 85 85 86 86 if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len)) 87 87 return -EINVAL; 88 88 89 - var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); 90 - if (!var) 91 - return -ENOMEM; 92 - 93 89 /* length of the variable name itself: remove GUID and separator */ 94 90 namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1; 95 91 96 - err = guid_parse(dentry->d_name.name + namelen + 1, &var->var.VendorGuid); 92 + err = guid_parse(dentry->d_name.name + namelen + 1, &vendor); 97 93 if (err) 98 - goto out; 99 - if (guid_equal(&var->var.VendorGuid, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) { 100 - err = -EPERM; 101 - goto out; 102 - } 94 + return err; 95 + if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) 96 + return -EPERM; 103 97 104 - if (efivar_variable_is_removable(var->var.VendorGuid, 98 + if (efivar_variable_is_removable(vendor, 105 99 dentry->d_name.name, namelen)) 106 100 is_removable = true; 107 101 108 102 inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0, is_removable); 109 - if (!inode) { 110 - err = -ENOMEM; 111 - goto out; 112 - } 103 + if (!inode) 104 + return -ENOMEM; 105 + var = efivar_entry(inode); 106 + 107 + var->var.VendorGuid = vendor; 113 108 114 109 for (i = 0; i < namelen; i++) 115 110 var->var.VariableName[i] = dentry->d_name.name[i]; ··· 112 117 var->var.VariableName[i] = '\0'; 113 118 114 119 inode->i_private = var; 115 - kmemleak_ignore(var); 116 - 117 - err = efivar_entry_add(var, &info->efivarfs_list); 118 - if (err) 119 - goto out; 120 120 121 121 d_instantiate(dentry, inode); 122 122 dget(dentry); 123 - out: 124 - if (err) { 125 - kfree(var); 126 - if (inode) 127 - iput(inode); 128 - } 129 - return err; 123 + 124 + return 0; 130 125 } 131 126 132 127 static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) ··· 172 187 return 0; 173 188 } 174 189 190 + /* copy of simple_setattr except that it doesn't do i_size updates */ 191 + static int efivarfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 192 + struct iattr *iattr) 193 + { 194 + struct inode *inode = d_inode(dentry); 195 + int error; 196 + 197 + error = setattr_prepare(idmap, dentry, iattr); 198 + if (error) 199 + return error; 200 + 201 + setattr_copy(idmap, inode, iattr); 202 + mark_inode_dirty(inode); 203 + return 0; 204 + } 205 + 175 206 static const struct inode_operations efivarfs_file_inode_operations = { 176 207 .fileattr_get = efivarfs_fileattr_get, 177 208 .fileattr_set = efivarfs_fileattr_set, 209 + .setattr = efivarfs_setattr, 178 210 };
+14 -13
fs/efivarfs/internal.h
··· 6 6 #ifndef EFIVAR_FS_INTERNAL_H 7 7 #define EFIVAR_FS_INTERNAL_H 8 8 9 - #include <linux/list.h> 10 9 #include <linux/efi.h> 11 10 12 11 struct efivarfs_mount_opts { ··· 15 16 16 17 struct efivarfs_fs_info { 17 18 struct efivarfs_mount_opts mount_opts; 18 - struct list_head efivarfs_list; 19 19 struct super_block *sb; 20 20 struct notifier_block nb; 21 + struct notifier_block pm_nb; 21 22 }; 22 23 23 24 struct efi_variable { 24 25 efi_char16_t VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)]; 25 26 efi_guid_t VendorGuid; 26 - __u32 Attributes; 27 27 }; 28 28 29 29 struct efivar_entry { 30 30 struct efi_variable var; 31 - struct list_head list; 32 - struct kobject kobj; 31 + struct inode vfs_inode; 32 + unsigned long open_count; 33 + bool removed; 33 34 }; 34 35 35 - int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *, 36 - struct list_head *), 37 - void *data, struct list_head *head); 36 + static inline struct efivar_entry *efivar_entry(struct inode *inode) 37 + { 38 + return container_of(inode, struct efivar_entry, vfs_inode); 39 + } 38 40 39 - int efivar_entry_add(struct efivar_entry *entry, struct list_head *head); 40 - void __efivar_entry_add(struct efivar_entry *entry, struct list_head *head); 41 - void efivar_entry_remove(struct efivar_entry *entry); 41 + int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), 42 + void *data, bool duplicate_check); 43 + 42 44 int efivar_entry_delete(struct efivar_entry *entry); 43 45 44 46 int efivar_entry_size(struct efivar_entry *entry, unsigned long *size); ··· 50 50 int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes, 51 51 unsigned long *size, void *data, bool *set); 52 52 53 - int efivar_entry_iter(int (*func)(struct efivar_entry *, void *), 54 - struct list_head *head, void *data); 55 53 56 54 bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data, 57 55 unsigned long data_size); 58 56 bool efivar_variable_is_removable(efi_guid_t vendor, const char *name, 59 57 size_t len); 58 + char *efivar_get_utf8name(const efi_char16_t *name16, efi_guid_t *vendor); 59 + bool efivarfs_variable_is_present(efi_char16_t *variable_name, 60 + efi_guid_t *vendor, void *data); 60 61 61 62 extern const struct file_operations efivarfs_file_operations; 62 63 extern const struct inode_operations efivarfs_dir_inode_operations;
+225 -50
fs/efivarfs/super.c
··· 13 13 #include <linux/pagemap.h> 14 14 #include <linux/ucs2_string.h> 15 15 #include <linux/slab.h> 16 + #include <linux/suspend.h> 16 17 #include <linux/magic.h> 17 18 #include <linux/statfs.h> 18 19 #include <linux/notifier.h> ··· 40 39 return NOTIFY_OK; 41 40 } 42 41 43 - static void efivarfs_evict_inode(struct inode *inode) 42 + static struct inode *efivarfs_alloc_inode(struct super_block *sb) 44 43 { 45 - clear_inode(inode); 44 + struct efivar_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL); 45 + 46 + if (!entry) 47 + return NULL; 48 + 49 + inode_init_once(&entry->vfs_inode); 50 + entry->removed = false; 51 + 52 + return &entry->vfs_inode; 53 + } 54 + 55 + static void efivarfs_free_inode(struct inode *inode) 56 + { 57 + struct efivar_entry *entry = efivar_entry(inode); 58 + 59 + kfree(entry); 46 60 } 47 61 48 62 static int efivarfs_show_options(struct seq_file *m, struct dentry *root) ··· 122 106 static const struct super_operations efivarfs_ops = { 123 107 .statfs = efivarfs_statfs, 124 108 .drop_inode = generic_delete_inode, 125 - .evict_inode = efivarfs_evict_inode, 109 + .alloc_inode = efivarfs_alloc_inode, 110 + .free_inode = efivarfs_free_inode, 126 111 .show_options = efivarfs_show_options, 127 112 }; 128 113 ··· 198 181 return ERR_PTR(-ENOMEM); 199 182 } 200 183 201 - static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, 202 - unsigned long name_size, void *data, 203 - struct list_head *list) 184 + bool efivarfs_variable_is_present(efi_char16_t *variable_name, 185 + efi_guid_t *vendor, void *data) 204 186 { 205 - struct super_block *sb = (struct super_block *)data; 187 + char *name = efivar_get_utf8name(variable_name, vendor); 188 + struct super_block *sb = data; 189 + struct dentry *dentry; 190 + struct qstr qstr; 191 + 192 + if (!name) 193 + /* 194 + * If the allocation failed there'll already be an 195 + * error in the log (and likely a huge and growing 196 + * number of them since they system will be under 197 + * extreme memory pressure), so simply assume 198 + * collision for safety but don't add to the log 199 + * flood. 200 + */ 201 + return true; 202 + 203 + qstr.name = name; 204 + qstr.len = strlen(name); 205 + dentry = d_hash_and_lookup(sb->s_root, &qstr); 206 + kfree(name); 207 + if (!IS_ERR_OR_NULL(dentry)) 208 + dput(dentry); 209 + 210 + return dentry != NULL; 211 + } 212 + 213 + static int efivarfs_create_dentry(struct super_block *sb, efi_char16_t *name16, 214 + unsigned long name_size, efi_guid_t vendor, 215 + char *name) 216 + { 206 217 struct efivar_entry *entry; 207 - struct inode *inode = NULL; 218 + struct inode *inode; 208 219 struct dentry *dentry, *root = sb->s_root; 209 220 unsigned long size = 0; 210 - char *name; 211 221 int len; 212 222 int err = -ENOMEM; 213 223 bool is_removable = false; 214 224 215 - if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) 216 - return 0; 225 + /* length of the variable name itself: remove GUID and separator */ 226 + len = strlen(name) - EFI_VARIABLE_GUID_LEN - 1; 217 227 218 - entry = kzalloc(sizeof(*entry), GFP_KERNEL); 219 - if (!entry) 220 - return err; 221 - 222 - memcpy(entry->var.VariableName, name16, name_size); 223 - memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 224 - 225 - len = ucs2_utf8size(entry->var.VariableName); 226 - 227 - /* name, plus '-', plus GUID, plus NUL*/ 228 - name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL); 229 - if (!name) 230 - goto fail; 231 - 232 - ucs2_as_utf8(name, entry->var.VariableName, len); 233 - 234 - if (efivar_variable_is_removable(entry->var.VendorGuid, name, len)) 228 + if (efivar_variable_is_removable(vendor, name, len)) 235 229 is_removable = true; 236 - 237 - name[len] = '-'; 238 - 239 - efi_guid_to_str(&entry->var.VendorGuid, name + len + 1); 240 - 241 - name[len + EFI_VARIABLE_GUID_LEN+1] = '\0'; 242 - 243 - /* replace invalid slashes like kobject_set_name_vargs does for /sys/firmware/efi/vars. */ 244 - strreplace(name, '/', '!'); 245 230 246 231 inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0, 247 232 is_removable); 248 233 if (!inode) 249 234 goto fail_name; 235 + 236 + entry = efivar_entry(inode); 237 + 238 + memcpy(entry->var.VariableName, name16, name_size); 239 + memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 250 240 251 241 dentry = efivarfs_alloc_dentry(root, name); 252 242 if (IS_ERR(dentry)) { ··· 262 238 } 263 239 264 240 __efivar_entry_get(entry, NULL, &size, NULL); 265 - __efivar_entry_add(entry, list); 266 241 267 242 /* copied by the above to local storage in the dentry. */ 268 243 kfree(name); 269 244 270 245 inode_lock(inode); 271 246 inode->i_private = entry; 272 - i_size_write(inode, size + sizeof(entry->var.Attributes)); 247 + i_size_write(inode, size + sizeof(__u32)); /* attributes + data */ 273 248 inode_unlock(inode); 274 249 d_add(dentry, inode); 275 250 ··· 278 255 iput(inode); 279 256 fail_name: 280 257 kfree(name); 281 - fail: 282 - kfree(entry); 258 + 283 259 return err; 284 260 } 285 261 286 - static int efivarfs_destroy(struct efivar_entry *entry, void *data) 262 + static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, 263 + unsigned long name_size, void *data) 287 264 { 288 - efivar_entry_remove(entry); 289 - kfree(entry); 290 - return 0; 265 + struct super_block *sb = (struct super_block *)data; 266 + char *name; 267 + 268 + if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) 269 + return 0; 270 + 271 + name = efivar_get_utf8name(name16, &vendor); 272 + if (!name) 273 + return -ENOMEM; 274 + 275 + return efivarfs_create_dentry(sb, name16, name_size, vendor, name); 291 276 } 292 277 293 278 enum { ··· 367 336 if (err) 368 337 return err; 369 338 370 - return efivar_init(efivarfs_callback, sb, &sfi->efivarfs_list); 339 + return efivar_init(efivarfs_callback, sb, true); 371 340 } 372 341 373 342 static int efivarfs_get_tree(struct fs_context *fc) ··· 391 360 .reconfigure = efivarfs_reconfigure, 392 361 }; 393 362 363 + struct efivarfs_ctx { 364 + struct dir_context ctx; 365 + struct super_block *sb; 366 + struct dentry *dentry; 367 + }; 368 + 369 + static bool efivarfs_actor(struct dir_context *ctx, const char *name, int len, 370 + loff_t offset, u64 ino, unsigned mode) 371 + { 372 + unsigned long size; 373 + struct efivarfs_ctx *ectx = container_of(ctx, struct efivarfs_ctx, ctx); 374 + struct qstr qstr = { .name = name, .len = len }; 375 + struct dentry *dentry = d_hash_and_lookup(ectx->sb->s_root, &qstr); 376 + struct inode *inode; 377 + struct efivar_entry *entry; 378 + int err; 379 + 380 + if (IS_ERR_OR_NULL(dentry)) 381 + return true; 382 + 383 + inode = d_inode(dentry); 384 + entry = efivar_entry(inode); 385 + 386 + err = efivar_entry_size(entry, &size); 387 + size += sizeof(__u32); /* attributes */ 388 + if (err) 389 + size = 0; 390 + 391 + inode_lock(inode); 392 + i_size_write(inode, size); 393 + inode_unlock(inode); 394 + 395 + if (!size) { 396 + ectx->dentry = dentry; 397 + return false; 398 + } 399 + 400 + dput(dentry); 401 + 402 + return true; 403 + } 404 + 405 + static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor, 406 + unsigned long name_size, void *data) 407 + { 408 + char *name; 409 + struct super_block *sb = data; 410 + struct dentry *dentry; 411 + struct qstr qstr; 412 + int err; 413 + 414 + if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) 415 + return 0; 416 + 417 + name = efivar_get_utf8name(name16, &vendor); 418 + if (!name) 419 + return -ENOMEM; 420 + 421 + qstr.name = name; 422 + qstr.len = strlen(name); 423 + dentry = d_hash_and_lookup(sb->s_root, &qstr); 424 + if (IS_ERR(dentry)) { 425 + err = PTR_ERR(dentry); 426 + goto out; 427 + } 428 + 429 + if (!dentry) { 430 + /* found missing entry */ 431 + pr_info("efivarfs: creating variable %s\n", name); 432 + return efivarfs_create_dentry(sb, name16, name_size, vendor, name); 433 + } 434 + 435 + dput(dentry); 436 + err = 0; 437 + 438 + out: 439 + kfree(name); 440 + 441 + return err; 442 + } 443 + 444 + static int efivarfs_pm_notify(struct notifier_block *nb, unsigned long action, 445 + void *ptr) 446 + { 447 + struct efivarfs_fs_info *sfi = container_of(nb, struct efivarfs_fs_info, 448 + pm_nb); 449 + struct path path = { .mnt = NULL, .dentry = sfi->sb->s_root, }; 450 + struct efivarfs_ctx ectx = { 451 + .ctx = { 452 + .actor = efivarfs_actor, 453 + }, 454 + .sb = sfi->sb, 455 + }; 456 + struct file *file; 457 + static bool rescan_done = true; 458 + 459 + if (action == PM_HIBERNATION_PREPARE) { 460 + rescan_done = false; 461 + return NOTIFY_OK; 462 + } else if (action != PM_POST_HIBERNATION) { 463 + return NOTIFY_DONE; 464 + } 465 + 466 + if (rescan_done) 467 + return NOTIFY_DONE; 468 + 469 + pr_info("efivarfs: resyncing variable state\n"); 470 + 471 + /* O_NOATIME is required to prevent oops on NULL mnt */ 472 + file = kernel_file_open(&path, O_RDONLY | O_DIRECTORY | O_NOATIME, 473 + current_cred()); 474 + if (IS_ERR(file)) 475 + return NOTIFY_DONE; 476 + 477 + rescan_done = true; 478 + 479 + /* 480 + * First loop over the directory and verify each entry exists, 481 + * removing it if it doesn't 482 + */ 483 + file->f_pos = 2; /* skip . and .. */ 484 + do { 485 + ectx.dentry = NULL; 486 + iterate_dir(file, &ectx.ctx); 487 + if (ectx.dentry) { 488 + pr_info("efivarfs: removing variable %pd\n", 489 + ectx.dentry); 490 + simple_recursive_removal(ectx.dentry, NULL); 491 + dput(ectx.dentry); 492 + } 493 + } while (ectx.dentry); 494 + fput(file); 495 + 496 + /* 497 + * then loop over variables, creating them if there's no matching 498 + * dentry 499 + */ 500 + efivar_init(efivarfs_check_missing, sfi->sb, false); 501 + 502 + return NOTIFY_OK; 503 + } 504 + 394 505 static int efivarfs_init_fs_context(struct fs_context *fc) 395 506 { 396 507 struct efivarfs_fs_info *sfi; ··· 544 371 if (!sfi) 545 372 return -ENOMEM; 546 373 547 - INIT_LIST_HEAD(&sfi->efivarfs_list); 548 - 549 374 sfi->mount_opts.uid = GLOBAL_ROOT_UID; 550 375 sfi->mount_opts.gid = GLOBAL_ROOT_GID; 551 376 552 377 fc->s_fs_info = sfi; 553 378 fc->ops = &efivarfs_context_ops; 379 + 380 + sfi->pm_nb.notifier_call = efivarfs_pm_notify; 381 + sfi->pm_nb.priority = 0; 382 + register_pm_notifier(&sfi->pm_nb); 383 + 554 384 return 0; 555 385 } 556 386 ··· 563 387 564 388 blocking_notifier_chain_unregister(&efivar_ops_nh, &sfi->nb); 565 389 kill_litter_super(sb); 390 + unregister_pm_notifier(&sfi->pm_nb); 566 391 567 - /* Remove all entries and destroy */ 568 - efivar_entry_iter(efivarfs_destroy, &sfi->efivarfs_list, NULL); 569 392 kfree(sfi); 570 393 } 571 394
+43 -138
fs/efivarfs/vars.c
··· 225 225 } 226 226 } 227 227 228 + char * 229 + efivar_get_utf8name(const efi_char16_t *name16, efi_guid_t *vendor) 230 + { 231 + int len = ucs2_utf8size(name16); 232 + char *name; 233 + 234 + /* name, plus '-', plus GUID, plus NUL*/ 235 + name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL); 236 + if (!name) 237 + return NULL; 238 + 239 + ucs2_as_utf8(name, name16, len); 240 + 241 + name[len] = '-'; 242 + 243 + efi_guid_to_str(vendor, name + len + 1); 244 + 245 + name[len + EFI_VARIABLE_GUID_LEN+1] = '\0'; 246 + 247 + /* replace invalid slashes like kobject_set_name_vargs does for /sys/firmware/efi/vars. */ 248 + strreplace(name, '/', '!'); 249 + 250 + return name; 251 + } 252 + 228 253 bool 229 254 efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data, 230 255 unsigned long data_size) ··· 313 288 return found; 314 289 } 315 290 316 - static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor, 317 - struct list_head *head) 318 - { 319 - struct efivar_entry *entry, *n; 320 - unsigned long strsize1, strsize2; 321 - bool found = false; 322 - 323 - strsize1 = ucs2_strsize(variable_name, EFI_VAR_NAME_LEN); 324 - list_for_each_entry_safe(entry, n, head, list) { 325 - strsize2 = ucs2_strsize(entry->var.VariableName, EFI_VAR_NAME_LEN); 326 - if (strsize1 == strsize2 && 327 - !memcmp(variable_name, &(entry->var.VariableName), 328 - strsize2) && 329 - !efi_guidcmp(entry->var.VendorGuid, 330 - *vendor)) { 331 - found = true; 332 - break; 333 - } 334 - } 335 - return found; 336 - } 337 - 338 291 /* 339 292 * Returns the size of variable_name, in bytes, including the 340 293 * terminating NULL character, or variable_name_size if no NULL ··· 364 361 * efivar_init - build the initial list of EFI variables 365 362 * @func: callback function to invoke for every variable 366 363 * @data: function-specific data to pass to @func 367 - * @head: initialised head of variable list 364 + * @duplicate_check: fail if a duplicate variable is found 368 365 * 369 366 * Get every EFI variable from the firmware and invoke @func. @func 370 - * should call efivar_entry_add() to build the list of variables. 367 + * should populate the initial dentry and inode tree. 371 368 * 372 369 * Returns 0 on success, or a kernel error code on failure. 373 370 */ 374 - int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *, 375 - struct list_head *), 376 - void *data, struct list_head *head) 371 + int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), 372 + void *data, bool duplicate_check) 377 373 { 378 374 unsigned long variable_name_size = 512; 379 375 efi_char16_t *variable_name; ··· 416 414 * we'll ever see a different variable name, 417 415 * and may end up looping here forever. 418 416 */ 419 - if (variable_is_present(variable_name, &vendor_guid, 420 - head)) { 417 + if (duplicate_check && 418 + efivarfs_variable_is_present(variable_name, 419 + &vendor_guid, data)) { 421 420 dup_variable_bug(variable_name, &vendor_guid, 422 421 variable_name_size); 423 422 status = EFI_NOT_FOUND; 424 423 } else { 425 424 err = func(variable_name, vendor_guid, 426 - variable_name_size, data, head); 425 + variable_name_size, data); 427 426 if (err) 428 427 status = EFI_NOT_FOUND; 429 428 } ··· 456 453 } 457 454 458 455 /** 459 - * efivar_entry_add - add entry to variable list 460 - * @entry: entry to add to list 461 - * @head: list head 462 - * 463 - * Returns 0 on success, or a kernel error code on failure. 464 - */ 465 - int efivar_entry_add(struct efivar_entry *entry, struct list_head *head) 466 - { 467 - int err; 468 - 469 - err = efivar_lock(); 470 - if (err) 471 - return err; 472 - list_add(&entry->list, head); 473 - efivar_unlock(); 474 - 475 - return 0; 476 - } 477 - 478 - /** 479 - * __efivar_entry_add - add entry to variable list 480 - * @entry: entry to add to list 481 - * @head: list head 482 - */ 483 - void __efivar_entry_add(struct efivar_entry *entry, struct list_head *head) 484 - { 485 - list_add(&entry->list, head); 486 - } 487 - 488 - /** 489 - * efivar_entry_remove - remove entry from variable list 490 - * @entry: entry to remove from list 491 - * 492 - * Returns 0 on success, or a kernel error code on failure. 493 - */ 494 - void efivar_entry_remove(struct efivar_entry *entry) 495 - { 496 - list_del(&entry->list); 497 - } 498 - 499 - /* 500 - * efivar_entry_list_del_unlock - remove entry from variable list 501 - * @entry: entry to remove 502 - * 503 - * Remove @entry from the variable list and release the list lock. 504 - * 505 - * NOTE: slightly weird locking semantics here - we expect to be 506 - * called with the efivars lock already held, and we release it before 507 - * returning. This is because this function is usually called after 508 - * set_variable() while the lock is still held. 509 - */ 510 - static void efivar_entry_list_del_unlock(struct efivar_entry *entry) 511 - { 512 - list_del(&entry->list); 513 - efivar_unlock(); 514 - } 515 - 516 - /** 517 - * efivar_entry_delete - delete variable and remove entry from list 456 + * efivar_entry_delete - delete variable 518 457 * @entry: entry containing variable to delete 519 458 * 520 - * Delete the variable from the firmware and remove @entry from the 521 - * variable list. It is the caller's responsibility to free @entry 522 - * once we return. 459 + * Delete the variable from the firmware. It is the caller's 460 + * responsibility to free @entry (by deleting the dentry/inode) once 461 + * we return. 523 462 * 524 463 * Returns 0 on success, -EINTR if we can't grab the semaphore, 525 464 * converted EFI status code if set_variable() fails. ··· 478 533 status = efivar_set_variable_locked(entry->var.VariableName, 479 534 &entry->var.VendorGuid, 480 535 0, 0, NULL, false); 481 - if (!(status == EFI_SUCCESS || status == EFI_NOT_FOUND)) { 482 - efivar_unlock(); 536 + efivar_unlock(); 537 + if (!(status == EFI_SUCCESS || status == EFI_NOT_FOUND)) 483 538 return efi_status_to_err(status); 484 - } 485 539 486 - efivar_entry_list_del_unlock(entry); 487 540 return 0; 488 541 } 489 542 ··· 575 632 * get_variable() fail. 576 633 * 577 634 * If the EFI variable does not exist when calling set_variable() 578 - * (EFI_NOT_FOUND), @entry is removed from the variable list. 635 + * (EFI_NOT_FOUND). 579 636 */ 580 637 int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes, 581 638 unsigned long *size, void *data, bool *set) ··· 591 648 return -EINVAL; 592 649 593 650 /* 594 - * The lock here protects the get_variable call, the conditional 595 - * set_variable call, and removal of the variable from the efivars 596 - * list (in the case of an authenticated delete). 651 + * The lock here protects the get_variable call and the 652 + * conditional set_variable call 597 653 */ 598 654 err = efivar_lock(); 599 655 if (err) ··· 618 676 &entry->var.VendorGuid, 619 677 NULL, size, NULL); 620 678 621 - if (status == EFI_NOT_FOUND) 622 - efivar_entry_list_del_unlock(entry); 623 - else 624 - efivar_unlock(); 679 + efivar_unlock(); 625 680 626 681 if (status && status != EFI_BUFFER_TOO_SMALL) 627 682 return efi_status_to_err(status); ··· 629 690 efivar_unlock(); 630 691 return err; 631 692 632 - } 633 - 634 - /** 635 - * efivar_entry_iter - iterate over variable list 636 - * @func: callback function 637 - * @head: head of variable list 638 - * @data: function-specific data to pass to callback 639 - * 640 - * Iterate over the list of EFI variables and call @func with every 641 - * entry on the list. It is safe for @func to remove entries in the 642 - * list via efivar_entry_delete() while iterating. 643 - * 644 - * Some notes for the callback function: 645 - * - a non-zero return value indicates an error and terminates the loop 646 - * - @func is called from atomic context 647 - */ 648 - int efivar_entry_iter(int (*func)(struct efivar_entry *, void *), 649 - struct list_head *head, void *data) 650 - { 651 - struct efivar_entry *entry, *n; 652 - int err = 0; 653 - 654 - err = efivar_lock(); 655 - if (err) 656 - return err; 657 - 658 - list_for_each_entry_safe(entry, n, head, list) { 659 - err = func(entry, data); 660 - if (err) 661 - break; 662 - } 663 - efivar_unlock(); 664 - 665 - return err; 666 693 }
-4
include/linux/efi.h
··· 363 363 #define ACPI_20_TABLE_GUID EFI_GUID(0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81) 364 364 #define SMBIOS_TABLE_GUID EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) 365 365 #define SMBIOS3_TABLE_GUID EFI_GUID(0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94) 366 - #define UGA_IO_PROTOCOL_GUID EFI_GUID(0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0x0b, 0x07, 0xa2) 367 366 #define EFI_GLOBAL_VARIABLE_GUID EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c) 368 367 #define UV_SYSTEM_TABLE_GUID EFI_GUID(0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93) 369 368 #define LINUX_EFI_CRASH_GUID EFI_GUID(0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0) ··· 372 373 #define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID EFI_GUID(0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c) 373 374 #define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID EFI_GUID(0x05c99a21, 0xc70f, 0x4ad2, 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e) 374 375 #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) 375 - #define EFI_UGA_PROTOCOL_GUID EFI_GUID(0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39) 376 376 #define EFI_PCI_IO_PROTOCOL_GUID EFI_GUID(0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a) 377 377 #define EFI_FILE_INFO_ID EFI_GUID(0x09576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) 378 378 #define EFI_SYSTEM_RESOURCE_TABLE_GUID EFI_GUID(0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80) ··· 1283 1285 / sizeof_field(struct linux_efi_memreserve, entry[0])) 1284 1286 1285 1287 void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size); 1286 - 1287 - char *efi_systab_show_arch(char *str); 1288 1288 1289 1289 /* 1290 1290 * The LINUX_EFI_MOK_VARIABLE_TABLE_GUID config table can be provided
+164 -4
tools/testing/selftests/efivarfs/efivarfs.sh
··· 76 76 77 77 : > $file 78 78 79 - if [ ! -e $file ]; then 80 - echo "$file can not be created without writing" >&2 79 + if [ -e $file ]; then 80 + echo "$file can be created without writing" >&2 81 + file_cleanup $file 81 82 exit 1 82 83 fi 83 - file_cleanup $file 84 84 } 85 85 86 86 test_create_read() ··· 89 89 ./create-read $file 90 90 if [ $? -ne 0 ]; then 91 91 echo "create and read $file failed" 92 + exit 1 93 + fi 94 + if [ -e $file ]; then 95 + echo "file still exists and should not" 92 96 file_cleanup $file 93 97 exit 1 94 98 fi 95 - file_cleanup $file 96 99 } 97 100 98 101 test_delete() ··· 205 202 exit $ret 206 203 } 207 204 205 + test_no_set_size() 206 + { 207 + local attrs='\x07\x00\x00\x00' 208 + local file=$efivarfs_mount/$FUNCNAME-$test_guid 209 + local ret=0 210 + 211 + printf "$attrs\x00" > $file 212 + [ -e $file -a -s $file ] || exit 1 213 + chattr -i $file 214 + : > $file 215 + if [ $? != 0 ]; then 216 + echo "variable file failed to accept truncation" 217 + ret=1 218 + elif [ -e $file -a ! -s $file ]; then 219 + echo "file can be truncated to zero size" 220 + ret=1 221 + fi 222 + rm $file || exit 1 223 + 224 + exit $ret 225 + } 226 + 227 + setup_test_multiple() 228 + { 229 + ## 230 + # we're going to do multi-threaded tests, so create a set of 231 + # pipes for synchronization. We use pipes 1..3 to start the 232 + # stalled shell job and pipes 4..6 as indicators that the job 233 + # has started. If you need more than 3 jobs the two +3's below 234 + # need increasing 235 + ## 236 + 237 + declare -ag p 238 + 239 + # empty is because arrays number from 0 but jobs number from 1 240 + p[0]="" 241 + 242 + for f in 1 2 3 4 5 6; do 243 + p[$f]=/tmp/efivarfs_pipe${f} 244 + mknod ${p[$f]} p 245 + done 246 + 247 + declare -g var=$efivarfs_mount/test_multiple-$test_guid 248 + 249 + cleanup() { 250 + for f in ${p[@]}; do 251 + rm -f ${f} 252 + done 253 + if [ -e $var ]; then 254 + file_cleanup $var 255 + fi 256 + } 257 + trap cleanup exit 258 + 259 + waitstart() { 260 + cat ${p[$[$1+3]]} > /dev/null 261 + } 262 + 263 + waitpipe() { 264 + echo 1 > ${p[$[$1+3]]} 265 + cat ${p[$1]} > /dev/null 266 + } 267 + 268 + endjob() { 269 + echo 1 > ${p[$1]} 270 + wait -n %$1 271 + } 272 + } 273 + 274 + test_multiple_zero_size() 275 + { 276 + ## 277 + # check for remove on last close, set up three threads all 278 + # holding the variable (one write and two reads) and then 279 + # close them sequentially (waiting for completion) and check 280 + # the state of the variable 281 + ## 282 + 283 + { waitpipe 1; echo 1; } > $var 2> /dev/null & 284 + waitstart 1 285 + # zero length file should exist 286 + [ -e $var ] || exit 1 287 + # second and third delayed close 288 + { waitpipe 2; } < $var & 289 + waitstart 2 290 + { waitpipe 3; } < $var & 291 + waitstart 3 292 + # close first fd 293 + endjob 1 294 + # var should only be deleted on last close 295 + [ -e $var ] || exit 1 296 + # close second fd 297 + endjob 2 298 + [ -e $var ] || exit 1 299 + # file should go on last close 300 + endjob 3 301 + [ ! -e $var ] || exit 1 302 + } 303 + 304 + test_multiple_create() 305 + { 306 + ## 307 + # set multiple threads to access the variable but delay 308 + # the final write to check the close of 2 and 3. The 309 + # final write should succeed in creating the variable 310 + ## 311 + { waitpipe 1; printf '\x07\x00\x00\x00\x54'; } > $var & 312 + waitstart 1 313 + [ -e $var -a ! -s $var ] || exit 1 314 + { waitpipe 2; } < $var & 315 + waitstart 2 316 + { waitpipe 3; } < $var & 317 + waitstart 3 318 + # close second and third fds 319 + endjob 2 320 + # var should only be created (have size) on last close 321 + [ -e $var -a ! -s $var ] || exit 1 322 + endjob 3 323 + [ -e $var -a ! -s $var ] || exit 1 324 + # close first fd 325 + endjob 1 326 + # variable should still exist 327 + [ -s $var ] || exit 1 328 + file_cleanup $var 329 + } 330 + 331 + test_multiple_delete_on_write() { 332 + ## 333 + # delete the variable on final write; seqencing similar 334 + # to test_multiple_create() 335 + ## 336 + printf '\x07\x00\x00\x00\x54' > $var 337 + chattr -i $var 338 + { waitpipe 1; printf '\x07\x00\x00\x00'; } > $var & 339 + waitstart 1 340 + [ -e $var -a -s $var ] || exit 1 341 + { waitpipe 2; } < $var & 342 + waitstart 2 343 + { waitpipe 3; } < $var & 344 + waitstart 3 345 + # close first fd; write should set variable size to zero 346 + endjob 1 347 + # var should only be deleted on last close 348 + [ -e $var -a ! -s $var ] || exit 1 349 + endjob 2 350 + [ -e $var ] || exit 1 351 + # close last fd 352 + endjob 3 353 + # variable should now be removed 354 + [ ! -e $var ] || exit 1 355 + } 356 + 208 357 check_prereqs 209 358 210 359 rc=0 ··· 369 214 run_test test_open_unlink 370 215 run_test test_valid_filenames 371 216 run_test test_invalid_filenames 217 + run_test test_no_set_size 218 + setup_test_multiple 219 + run_test test_multiple_zero_size 220 + run_test test_multiple_create 221 + run_test test_multiple_delete_on_write 372 222 373 223 exit $rc