Skip to content

Commit 60a3408

Browse files
committed
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 <[email protected]>
1 parent c14bca3 commit 60a3408

File tree

5 files changed

+40
-74
lines changed

5 files changed

+40
-74
lines changed

arch/x86/include/asm/efi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ static inline u32 efi64_convert_status(efi_status_t status)
250250
#define __efi64_argmap_allocate_pool(type, size, buffer) \
251251
((type), (size), efi64_zero_upper(buffer))
252252

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+
253256
#define __efi64_argmap_create_event(type, tpl, f, c, event) \
254257
((type), (tpl), (f), (c), efi64_zero_upper(event))
255258

drivers/firmware/efi/libstub/efi-stub.c

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
#include <linux/efi.h>
13+
#include <linux/screen_info.h>
1314
#include <asm/efi.h>
1415

1516
#include "efistub.h"
@@ -53,25 +54,16 @@ void __weak free_screen_info(struct screen_info *si)
5354

5455
static struct screen_info *setup_graphics(void)
5556
{
56-
efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
57-
efi_status_t status;
58-
unsigned long size;
59-
void **gop_handle = NULL;
60-
struct screen_info *si = NULL;
57+
struct screen_info *si, tmp = {};
6158

62-
size = 0;
63-
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
64-
&gop_proto, NULL, &size, gop_handle);
65-
if (status == EFI_BUFFER_TOO_SMALL) {
66-
si = alloc_screen_info();
67-
if (!si)
68-
return NULL;
69-
status = efi_setup_gop(si, &gop_proto, size);
70-
if (status != EFI_SUCCESS) {
71-
free_screen_info(si);
72-
return NULL;
73-
}
74-
}
59+
if (efi_setup_gop(&tmp) != EFI_SUCCESS)
60+
return NULL;
61+
62+
si = alloc_screen_info();
63+
if (!si)
64+
return NULL;
65+
66+
*si = tmp;
7567
return si;
7668
}
7769

drivers/firmware/efi/libstub/efistub.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
55

66
#include <linux/compiler.h>
7+
#include <linux/cleanup.h>
78
#include <linux/efi.h>
89
#include <linux/kernel.h>
910
#include <linux/kern_levels.h>
@@ -313,7 +314,9 @@ union efi_boot_services {
313314
void *close_protocol;
314315
void *open_protocol_information;
315316
void *protocols_per_handle;
316-
void *locate_handle_buffer;
317+
efi_status_t (__efiapi *locate_handle_buffer)(int, efi_guid_t *,
318+
void *, unsigned long *,
319+
efi_handle_t **);
317320
efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *,
318321
void **);
319322
efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...);
@@ -1052,6 +1055,7 @@ void efi_puts(const char *str);
10521055
__printf(1, 2) int efi_printk(char const *fmt, ...);
10531056

10541057
void efi_free(unsigned long size, unsigned long addr);
1058+
DEFINE_FREE(efi_pool, void *, if (_T) efi_bs_call(free_pool, _T));
10551059

10561060
void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size);
10571061

@@ -1081,8 +1085,7 @@ efi_status_t efi_parse_options(char const *cmdline);
10811085

10821086
void efi_parse_option_graphics(char *option);
10831087

1084-
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
1085-
unsigned long size);
1088+
efi_status_t efi_setup_gop(struct screen_info *si);
10861089

10871090
efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
10881091
const efi_char16_t *optstr,

drivers/firmware/efi/libstub/gop.c

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -461,25 +461,25 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
461461
}
462462
}
463463

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[])
466466
{
467467
efi_graphics_output_protocol_t *first_gop;
468468
efi_handle_t h;
469469

470470
first_gop = NULL;
471471

472-
for_each_efi_handle(h, handles, efi_get_handle_num(size)) {
472+
for_each_efi_handle(h, handles, num) {
473473
efi_status_t status;
474474

475475
efi_graphics_output_protocol_t *gop;
476476
efi_graphics_output_protocol_mode_t *mode;
477477
efi_graphics_output_mode_info_t *info;
478-
479-
efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
480478
void *dummy = NULL;
481479

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);
483483
if (status != EFI_SUCCESS)
484484
continue;
485485

@@ -499,7 +499,8 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
499499
* Once we've found a GOP supporting ConOut,
500500
* don't bother looking any further.
501501
*/
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);
503504
if (status == EFI_SUCCESS)
504505
return gop;
505506

@@ -510,16 +511,22 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
510511
return first_gop;
511512
}
512513

513-
static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
514-
unsigned long size, void **handles)
514+
efi_status_t efi_setup_gop(struct screen_info *si)
515515
{
516-
efi_graphics_output_protocol_t *gop;
516+
efi_handle_t *handles __free(efi_pool) = NULL;
517517
efi_graphics_output_protocol_mode_t *mode;
518518
efi_graphics_output_mode_info_t *info;
519+
efi_graphics_output_protocol_t *gop;
520+
efi_status_t status;
521+
unsigned long num;
519522

520-
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;
521528

522-
/* Did we find any GOPs? */
529+
gop = find_gop(num, handles);
523530
if (!gop)
524531
return EFI_NOT_FOUND;
525532

@@ -551,29 +558,3 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
551558

552559
return EFI_SUCCESS;
553560
}
554-
555-
/*
556-
* See if we have Graphics Output Protocol
557-
*/
558-
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
559-
unsigned long size)
560-
{
561-
efi_status_t status;
562-
void **gop_handle = NULL;
563-
564-
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
565-
(void **)&gop_handle);
566-
if (status != EFI_SUCCESS)
567-
return status;
568-
569-
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, proto, NULL,
570-
&size, gop_handle);
571-
if (status != EFI_SUCCESS)
572-
goto free_handle;
573-
574-
status = setup_gop(si, proto, size, gop_handle);
575-
576-
free_handle:
577-
efi_bs_call(free_pool, gop_handle);
578-
return status;
579-
}

drivers/firmware/efi/libstub/x86-stub.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -406,24 +406,11 @@ static void setup_quirks(struct boot_params *boot_params)
406406

407407
static void setup_graphics(struct boot_params *boot_params)
408408
{
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;
414-
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);
409+
struct screen_info *si = memset(&boot_params->screen_info, 0, sizeof(*si));
423410

411+
efi_setup_gop(si);
424412
}
425413

426-
427414
static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
428415
{
429416
efi_bs_call(exit, handle, status, 0, NULL);

0 commit comments

Comments
 (0)