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

efi/libstub: Simplify GOP handling code

Use the LocateHandleBuffer() API and a __free() function to simplify the
logic that allocates a handle buffer to iterate over all GOP protocols
in the EFI database.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

+40 -74
+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 -18
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
+6 -3
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> ··· 314 313 void *close_protocol; 315 314 void *open_protocol_information; 316 315 void *protocols_per_handle; 317 - void *locate_handle_buffer; 316 + efi_status_t (__efiapi *locate_handle_buffer)(int, efi_guid_t *, 317 + void *, unsigned long *, 318 + efi_handle_t **); 318 319 efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *, 319 320 void **); 320 321 efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...); ··· 1055 1052 __printf(1, 2) int efi_printk(char const *fmt, ...); 1056 1053 1057 1054 void efi_free(unsigned long size, unsigned long addr); 1055 + DEFINE_FREE(efi_pool, void *, if (_T) efi_bs_call(free_pool, _T)); 1058 1056 1059 1057 void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size); 1060 1058 ··· 1085 1081 1086 1082 void efi_parse_option_graphics(char *option); 1087 1083 1088 - efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, 1089 - unsigned long size); 1084 + efi_status_t efi_setup_gop(struct screen_info *si); 1090 1085 1091 1086 efi_status_t handle_cmdline_files(efi_loaded_image_t *image, 1092 1087 const efi_char16_t *optstr,
+19 -38
drivers/firmware/efi/libstub/gop.c
··· 461 461 } 462 462 } 463 463 464 - static efi_graphics_output_protocol_t * 465 - 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[]) 466 466 { 467 467 efi_graphics_output_protocol_t *first_gop; 468 468 efi_handle_t h; 469 469 470 470 first_gop = NULL; 471 471 472 - for_each_efi_handle(h, handles, efi_get_handle_num(size)) { 472 + for_each_efi_handle(h, handles, num) { 473 473 efi_status_t status; 474 474 475 475 efi_graphics_output_protocol_t *gop; 476 476 efi_graphics_output_protocol_mode_t *mode; 477 477 efi_graphics_output_mode_info_t *info; 478 - 479 - efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; 480 478 void *dummy = NULL; 481 479 482 - 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); 483 483 if (status != EFI_SUCCESS) 484 484 continue; 485 485 ··· 499 499 * Once we've found a GOP supporting ConOut, 500 500 * don't bother looking any further. 501 501 */ 502 - status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy); 502 + status = efi_bs_call(handle_protocol, h, 503 + &EFI_CONSOLE_OUT_DEVICE_GUID, &dummy); 503 504 if (status == EFI_SUCCESS) 504 505 return gop; 505 506 ··· 511 510 return first_gop; 512 511 } 513 512 514 - static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, 515 - unsigned long size, void **handles) 513 + efi_status_t efi_setup_gop(struct screen_info *si) 516 514 { 517 - efi_graphics_output_protocol_t *gop; 515 + efi_handle_t *handles __free(efi_pool) = NULL; 518 516 efi_graphics_output_protocol_mode_t *mode; 519 517 efi_graphics_output_mode_info_t *info; 518 + efi_graphics_output_protocol_t *gop; 519 + efi_status_t status; 520 + unsigned long num; 520 521 521 - gop = find_gop(proto, size, handles); 522 + status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL, 523 + &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, NULL, &num, 524 + &handles); 525 + if (status != EFI_SUCCESS) 526 + return status; 522 527 523 - /* Did we find any GOPs? */ 528 + gop = find_gop(num, handles); 524 529 if (!gop) 525 530 return EFI_NOT_FOUND; 526 531 ··· 557 550 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; 558 551 559 552 return EFI_SUCCESS; 560 - } 561 - 562 - /* 563 - * See if we have Graphics Output Protocol 564 - */ 565 - efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, 566 - unsigned long size) 567 - { 568 - efi_status_t status; 569 - void **gop_handle = NULL; 570 - 571 - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, 572 - (void **)&gop_handle); 573 - if (status != EFI_SUCCESS) 574 - return status; 575 - 576 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, proto, NULL, 577 - &size, gop_handle); 578 - if (status != EFI_SUCCESS) 579 - goto free_handle; 580 - 581 - status = setup_gop(si, proto, size, gop_handle); 582 - 583 - free_handle: 584 - efi_bs_call(free_pool, gop_handle); 585 - return status; 586 553 }
+2 -15
drivers/firmware/efi/libstub/x86-stub.c
··· 406 406 407 407 static void setup_graphics(struct boot_params *boot_params) 408 408 { 409 - efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; 410 - struct screen_info *si; 411 - efi_status_t status; 412 - unsigned long size; 413 - void **gop_handle = NULL; 409 + struct screen_info *si = memset(&boot_params->screen_info, 0, sizeof(*si)); 414 410 415 - si = &boot_params->screen_info; 416 - memset(si, 0, sizeof(*si)); 417 - 418 - size = 0; 419 - status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, 420 - &graphics_proto, NULL, &size, gop_handle); 421 - if (status == EFI_BUFFER_TOO_SMALL) 422 - status = efi_setup_gop(si, &graphics_proto, size); 423 - 411 + efi_setup_gop(si); 424 412 } 425 - 426 413 427 414 static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status) 428 415 {