14febfb8dSArd Biesheuvel // SPDX-License-Identifier: GPL-2.0 2fc372064SArd Biesheuvel /* ----------------------------------------------------------------------- 3fc372064SArd Biesheuvel * 4fc372064SArd Biesheuvel * Copyright 2011 Intel Corporation; author Matt Fleming 5fc372064SArd Biesheuvel * 6fc372064SArd Biesheuvel * ----------------------------------------------------------------------- */ 7fc372064SArd Biesheuvel 89867fc9dSArvind Sankar #include <linux/bitops.h> 9d9ff0323SArvind Sankar #include <linux/ctype.h> 10fc372064SArd Biesheuvel #include <linux/efi.h> 11fc372064SArd Biesheuvel #include <linux/screen_info.h> 12fffb6804SArvind Sankar #include <linux/string.h> 13fc372064SArd Biesheuvel #include <asm/efi.h> 14fc372064SArd Biesheuvel #include <asm/setup.h> 15fc372064SArd Biesheuvel 162fcdad2aSArd Biesheuvel #include "efistub.h" 172fcdad2aSArd Biesheuvel 18fffb6804SArvind Sankar enum efi_cmdline_option { 19fffb6804SArvind Sankar EFI_CMDLINE_NONE, 20fffb6804SArvind Sankar EFI_CMDLINE_MODE_NUM, 21d9ff0323SArvind Sankar EFI_CMDLINE_RES 22fffb6804SArvind Sankar }; 23fffb6804SArvind Sankar 24fffb6804SArvind Sankar static struct { 25fffb6804SArvind Sankar enum efi_cmdline_option option; 26d9ff0323SArvind Sankar union { 27fffb6804SArvind Sankar u32 mode; 28d9ff0323SArvind Sankar struct { 29d9ff0323SArvind Sankar u32 width, height; 309a1663bcSArvind Sankar int format; 319a1663bcSArvind Sankar u8 depth; 32d9ff0323SArvind Sankar } res; 33d9ff0323SArvind Sankar }; 34fffb6804SArvind Sankar } cmdline __efistub_global = { .option = EFI_CMDLINE_NONE }; 35fffb6804SArvind Sankar 36fffb6804SArvind Sankar static bool parse_modenum(char *option, char **next) 37fffb6804SArvind Sankar { 38fffb6804SArvind Sankar u32 m; 39fffb6804SArvind Sankar 40fffb6804SArvind Sankar if (!strstarts(option, "mode=")) 41fffb6804SArvind Sankar return false; 42fffb6804SArvind Sankar option += strlen("mode="); 43fffb6804SArvind Sankar m = simple_strtoull(option, &option, 0); 44fffb6804SArvind Sankar if (*option && *option++ != ',') 45fffb6804SArvind Sankar return false; 46fffb6804SArvind Sankar cmdline.option = EFI_CMDLINE_MODE_NUM; 47fffb6804SArvind Sankar cmdline.mode = m; 48fffb6804SArvind Sankar 49fffb6804SArvind Sankar *next = option; 50fffb6804SArvind Sankar return true; 51fffb6804SArvind Sankar } 52fffb6804SArvind Sankar 53d9ff0323SArvind Sankar static bool parse_res(char *option, char **next) 54d9ff0323SArvind Sankar { 559a1663bcSArvind Sankar u32 w, h, d = 0; 569a1663bcSArvind Sankar int pf = -1; 57d9ff0323SArvind Sankar 58d9ff0323SArvind Sankar if (!isdigit(*option)) 59d9ff0323SArvind Sankar return false; 60d9ff0323SArvind Sankar w = simple_strtoull(option, &option, 10); 61d9ff0323SArvind Sankar if (*option++ != 'x' || !isdigit(*option)) 62d9ff0323SArvind Sankar return false; 63d9ff0323SArvind Sankar h = simple_strtoull(option, &option, 10); 649a1663bcSArvind Sankar if (*option == '-') { 659a1663bcSArvind Sankar option++; 669a1663bcSArvind Sankar if (strstarts(option, "rgb")) { 679a1663bcSArvind Sankar option += strlen("rgb"); 689a1663bcSArvind Sankar pf = PIXEL_RGB_RESERVED_8BIT_PER_COLOR; 699a1663bcSArvind Sankar } else if (strstarts(option, "bgr")) { 709a1663bcSArvind Sankar option += strlen("bgr"); 719a1663bcSArvind Sankar pf = PIXEL_BGR_RESERVED_8BIT_PER_COLOR; 729a1663bcSArvind Sankar } else if (isdigit(*option)) 739a1663bcSArvind Sankar d = simple_strtoull(option, &option, 10); 749a1663bcSArvind Sankar else 759a1663bcSArvind Sankar return false; 769a1663bcSArvind Sankar } 77d9ff0323SArvind Sankar if (*option && *option++ != ',') 78d9ff0323SArvind Sankar return false; 79d9ff0323SArvind Sankar cmdline.option = EFI_CMDLINE_RES; 80d9ff0323SArvind Sankar cmdline.res.width = w; 81d9ff0323SArvind Sankar cmdline.res.height = h; 829a1663bcSArvind Sankar cmdline.res.format = pf; 839a1663bcSArvind Sankar cmdline.res.depth = d; 84d9ff0323SArvind Sankar 85d9ff0323SArvind Sankar *next = option; 86d9ff0323SArvind Sankar return true; 87d9ff0323SArvind Sankar } 88d9ff0323SArvind Sankar 89fffb6804SArvind Sankar void efi_parse_option_graphics(char *option) 90fffb6804SArvind Sankar { 91fffb6804SArvind Sankar while (*option) { 92fffb6804SArvind Sankar if (parse_modenum(option, &option)) 93fffb6804SArvind Sankar continue; 94d9ff0323SArvind Sankar if (parse_res(option, &option)) 95d9ff0323SArvind Sankar continue; 96fffb6804SArvind Sankar 97fffb6804SArvind Sankar while (*option && *option++ != ',') 98fffb6804SArvind Sankar ; 99fffb6804SArvind Sankar } 100fffb6804SArvind Sankar } 101fffb6804SArvind Sankar 102fffb6804SArvind Sankar static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop) 103fffb6804SArvind Sankar { 104fffb6804SArvind Sankar efi_status_t status; 105fffb6804SArvind Sankar 106fffb6804SArvind Sankar efi_graphics_output_protocol_mode_t *mode; 107fffb6804SArvind Sankar efi_graphics_output_mode_info_t *info; 108fffb6804SArvind Sankar unsigned long info_size; 109fffb6804SArvind Sankar 110fffb6804SArvind Sankar u32 max_mode, cur_mode; 111fffb6804SArvind Sankar int pf; 112fffb6804SArvind Sankar 113fffb6804SArvind Sankar mode = efi_table_attr(gop, mode); 114fffb6804SArvind Sankar 115fffb6804SArvind Sankar cur_mode = efi_table_attr(mode, mode); 116fffb6804SArvind Sankar if (cmdline.mode == cur_mode) 117fffb6804SArvind Sankar return cur_mode; 118fffb6804SArvind Sankar 119fffb6804SArvind Sankar max_mode = efi_table_attr(mode, max_mode); 120fffb6804SArvind Sankar if (cmdline.mode >= max_mode) { 121fffb6804SArvind Sankar efi_printk("Requested mode is invalid\n"); 122fffb6804SArvind Sankar return cur_mode; 123fffb6804SArvind Sankar } 124fffb6804SArvind Sankar 125fffb6804SArvind Sankar status = efi_call_proto(gop, query_mode, cmdline.mode, 126fffb6804SArvind Sankar &info_size, &info); 127fffb6804SArvind Sankar if (status != EFI_SUCCESS) { 128fffb6804SArvind Sankar efi_printk("Couldn't get mode information\n"); 129fffb6804SArvind Sankar return cur_mode; 130fffb6804SArvind Sankar } 131fffb6804SArvind Sankar 132fffb6804SArvind Sankar pf = info->pixel_format; 133fffb6804SArvind Sankar 134fffb6804SArvind Sankar efi_bs_call(free_pool, info); 135fffb6804SArvind Sankar 136fffb6804SArvind Sankar if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) { 137fffb6804SArvind Sankar efi_printk("Invalid PixelFormat\n"); 138fffb6804SArvind Sankar return cur_mode; 139fffb6804SArvind Sankar } 140fffb6804SArvind Sankar 141fffb6804SArvind Sankar return cmdline.mode; 142fffb6804SArvind Sankar } 143fffb6804SArvind Sankar 1449a1663bcSArvind Sankar static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info) 1459a1663bcSArvind Sankar { 1469a1663bcSArvind Sankar if (pixel_format == PIXEL_BIT_MASK) { 1479a1663bcSArvind Sankar u32 mask = pixel_info.red_mask | pixel_info.green_mask | 1489a1663bcSArvind Sankar pixel_info.blue_mask | pixel_info.reserved_mask; 1499a1663bcSArvind Sankar if (!mask) 1509a1663bcSArvind Sankar return 0; 1519a1663bcSArvind Sankar return __fls(mask) - __ffs(mask) + 1; 1529a1663bcSArvind Sankar } else 1539a1663bcSArvind Sankar return 32; 1549a1663bcSArvind Sankar } 1559a1663bcSArvind Sankar 156d9ff0323SArvind Sankar static u32 choose_mode_res(efi_graphics_output_protocol_t *gop) 157d9ff0323SArvind Sankar { 158d9ff0323SArvind Sankar efi_status_t status; 159d9ff0323SArvind Sankar 160d9ff0323SArvind Sankar efi_graphics_output_protocol_mode_t *mode; 161d9ff0323SArvind Sankar efi_graphics_output_mode_info_t *info; 162d9ff0323SArvind Sankar unsigned long info_size; 163d9ff0323SArvind Sankar 164d9ff0323SArvind Sankar u32 max_mode, cur_mode; 165d9ff0323SArvind Sankar int pf; 1669a1663bcSArvind Sankar efi_pixel_bitmask_t pi; 167d9ff0323SArvind Sankar u32 m, w, h; 168d9ff0323SArvind Sankar 169d9ff0323SArvind Sankar mode = efi_table_attr(gop, mode); 170d9ff0323SArvind Sankar 171d9ff0323SArvind Sankar cur_mode = efi_table_attr(mode, mode); 172d9ff0323SArvind Sankar info = efi_table_attr(mode, info); 1739a1663bcSArvind Sankar pf = info->pixel_format; 1749a1663bcSArvind Sankar pi = info->pixel_information; 175d9ff0323SArvind Sankar w = info->horizontal_resolution; 176d9ff0323SArvind Sankar h = info->vertical_resolution; 177d9ff0323SArvind Sankar 1789a1663bcSArvind Sankar if (w == cmdline.res.width && h == cmdline.res.height && 1799a1663bcSArvind Sankar (cmdline.res.format < 0 || cmdline.res.format == pf) && 1809a1663bcSArvind Sankar (!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi))) 181d9ff0323SArvind Sankar return cur_mode; 182d9ff0323SArvind Sankar 183d9ff0323SArvind Sankar max_mode = efi_table_attr(mode, max_mode); 184d9ff0323SArvind Sankar 185d9ff0323SArvind Sankar for (m = 0; m < max_mode; m++) { 186d9ff0323SArvind Sankar if (m == cur_mode) 187d9ff0323SArvind Sankar continue; 188d9ff0323SArvind Sankar 189d9ff0323SArvind Sankar status = efi_call_proto(gop, query_mode, m, 190d9ff0323SArvind Sankar &info_size, &info); 191d9ff0323SArvind Sankar if (status != EFI_SUCCESS) 192d9ff0323SArvind Sankar continue; 193d9ff0323SArvind Sankar 194d9ff0323SArvind Sankar pf = info->pixel_format; 1959a1663bcSArvind Sankar pi = info->pixel_information; 196d9ff0323SArvind Sankar w = info->horizontal_resolution; 197d9ff0323SArvind Sankar h = info->vertical_resolution; 198d9ff0323SArvind Sankar 199d9ff0323SArvind Sankar efi_bs_call(free_pool, info); 200d9ff0323SArvind Sankar 201d9ff0323SArvind Sankar if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) 202d9ff0323SArvind Sankar continue; 2039a1663bcSArvind Sankar if (w == cmdline.res.width && h == cmdline.res.height && 2049a1663bcSArvind Sankar (cmdline.res.format < 0 || cmdline.res.format == pf) && 2059a1663bcSArvind Sankar (!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi))) 206d9ff0323SArvind Sankar return m; 207d9ff0323SArvind Sankar } 208d9ff0323SArvind Sankar 209d9ff0323SArvind Sankar efi_printk("Couldn't find requested mode\n"); 210d9ff0323SArvind Sankar 211d9ff0323SArvind Sankar return cur_mode; 212d9ff0323SArvind Sankar } 213d9ff0323SArvind Sankar 214fffb6804SArvind Sankar static void set_mode(efi_graphics_output_protocol_t *gop) 215fffb6804SArvind Sankar { 216fffb6804SArvind Sankar efi_graphics_output_protocol_mode_t *mode; 217fffb6804SArvind Sankar u32 cur_mode, new_mode; 218fffb6804SArvind Sankar 219fffb6804SArvind Sankar switch (cmdline.option) { 220fffb6804SArvind Sankar case EFI_CMDLINE_MODE_NUM: 221fffb6804SArvind Sankar new_mode = choose_mode_modenum(gop); 222fffb6804SArvind Sankar break; 223d9ff0323SArvind Sankar case EFI_CMDLINE_RES: 224d9ff0323SArvind Sankar new_mode = choose_mode_res(gop); 225d9ff0323SArvind Sankar break; 226fffb6804SArvind Sankar default: 227fffb6804SArvind Sankar return; 228fffb6804SArvind Sankar } 229fffb6804SArvind Sankar 230fffb6804SArvind Sankar mode = efi_table_attr(gop, mode); 231fffb6804SArvind Sankar cur_mode = efi_table_attr(mode, mode); 232fffb6804SArvind Sankar 233fffb6804SArvind Sankar if (new_mode == cur_mode) 234fffb6804SArvind Sankar return; 235fffb6804SArvind Sankar 236fffb6804SArvind Sankar if (efi_call_proto(gop, set_mode, new_mode) != EFI_SUCCESS) 237fffb6804SArvind Sankar efi_printk("Failed to set requested mode\n"); 238fffb6804SArvind Sankar } 239fffb6804SArvind Sankar 2409867fc9dSArvind Sankar static void find_bits(u32 mask, u8 *pos, u8 *size) 241fc372064SArd Biesheuvel { 2429867fc9dSArvind Sankar if (!mask) { 2439867fc9dSArvind Sankar *pos = *size = 0; 2449867fc9dSArvind Sankar return; 245fc372064SArd Biesheuvel } 246fc372064SArd Biesheuvel 2479867fc9dSArvind Sankar /* UEFI spec guarantees that the set bits are contiguous */ 2489867fc9dSArvind Sankar *pos = __ffs(mask); 2499867fc9dSArvind Sankar *size = __fls(mask) - *pos + 1; 250fc372064SArd Biesheuvel } 251fc372064SArd Biesheuvel 252fc372064SArd Biesheuvel static void 253fc372064SArd Biesheuvel setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, 25444c84b4aSArvind Sankar efi_pixel_bitmask_t pixel_info, int pixel_format) 255fc372064SArd Biesheuvel { 256d49fd4bbSArvind Sankar if (pixel_format == PIXEL_BIT_MASK) { 257d49fd4bbSArvind Sankar find_bits(pixel_info.red_mask, 258d49fd4bbSArvind Sankar &si->red_pos, &si->red_size); 259d49fd4bbSArvind Sankar find_bits(pixel_info.green_mask, 260d49fd4bbSArvind Sankar &si->green_pos, &si->green_size); 261d49fd4bbSArvind Sankar find_bits(pixel_info.blue_mask, 262d49fd4bbSArvind Sankar &si->blue_pos, &si->blue_size); 263d49fd4bbSArvind Sankar find_bits(pixel_info.reserved_mask, 264d49fd4bbSArvind Sankar &si->rsvd_pos, &si->rsvd_size); 265fc372064SArd Biesheuvel si->lfb_depth = si->red_size + si->green_size + 266fc372064SArd Biesheuvel si->blue_size + si->rsvd_size; 267fc372064SArd Biesheuvel si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; 268fc372064SArd Biesheuvel } else { 269d49fd4bbSArvind Sankar if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { 270fc372064SArd Biesheuvel si->red_pos = 0; 271d49fd4bbSArvind Sankar si->blue_pos = 16; 272d49fd4bbSArvind Sankar } else /* PIXEL_BGR_RESERVED_8BIT_PER_COLOR */ { 273fc372064SArd Biesheuvel si->blue_pos = 0; 274d49fd4bbSArvind Sankar si->red_pos = 16; 275d49fd4bbSArvind Sankar } 276d49fd4bbSArvind Sankar 277d49fd4bbSArvind Sankar si->green_pos = 8; 278d49fd4bbSArvind Sankar si->rsvd_pos = 24; 279d49fd4bbSArvind Sankar si->red_size = si->green_size = 280d49fd4bbSArvind Sankar si->blue_size = si->rsvd_size = 8; 281d49fd4bbSArvind Sankar 282d49fd4bbSArvind Sankar si->lfb_depth = 32; 283d49fd4bbSArvind Sankar si->lfb_linelength = pixels_per_scan_line * 4; 284fc372064SArd Biesheuvel } 285fc372064SArd Biesheuvel } 286fc372064SArd Biesheuvel 287ecf53091SArvind Sankar static efi_graphics_output_protocol_t * 288ecf53091SArvind Sankar find_gop(efi_guid_t *proto, unsigned long size, void **handles) 289fc372064SArd Biesheuvel { 290e484c594SArvind Sankar efi_graphics_output_protocol_t *first_gop; 2912732ea0dSArd Biesheuvel efi_handle_t h; 292fc372064SArd Biesheuvel int i; 293fc372064SArd Biesheuvel 294fc372064SArd Biesheuvel first_gop = NULL; 295fc372064SArd Biesheuvel 2962732ea0dSArd Biesheuvel for_each_efi_handle(h, handles, size, i) { 297e484c594SArvind Sankar efi_status_t status; 298e484c594SArvind Sankar 299e484c594SArvind Sankar efi_graphics_output_protocol_t *gop; 300e484c594SArvind Sankar efi_graphics_output_protocol_mode_t *mode; 301e484c594SArvind Sankar efi_graphics_output_mode_info_t *info; 302e484c594SArvind Sankar 303fc372064SArd Biesheuvel efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; 304fc372064SArd Biesheuvel void *dummy = NULL; 305fc372064SArd Biesheuvel 306966291f6SArd Biesheuvel status = efi_bs_call(handle_protocol, h, proto, (void **)&gop); 307fc372064SArd Biesheuvel if (status != EFI_SUCCESS) 308fc372064SArd Biesheuvel continue; 309fc372064SArd Biesheuvel 3108cd20797SArvind Sankar mode = efi_table_attr(gop, mode); 3118cd20797SArvind Sankar info = efi_table_attr(mode, info); 312d49fd4bbSArvind Sankar if (info->pixel_format == PIXEL_BLT_ONLY || 313d49fd4bbSArvind Sankar info->pixel_format >= PIXEL_FORMAT_MAX) 3148cd20797SArvind Sankar continue; 3158cd20797SArvind Sankar 316fc372064SArd Biesheuvel /* 317fc372064SArd Biesheuvel * Systems that use the UEFI Console Splitter may 318fc372064SArd Biesheuvel * provide multiple GOP devices, not all of which are 319fc372064SArd Biesheuvel * backed by real hardware. The workaround is to search 320fc372064SArd Biesheuvel * for a GOP implementing the ConOut protocol, and if 321fc372064SArd Biesheuvel * one isn't found, to just fall back to the first GOP. 3226327e6d0SArvind Sankar * 323fc372064SArd Biesheuvel * Once we've found a GOP supporting ConOut, 324fc372064SArd Biesheuvel * don't bother looking any further. 325fc372064SArd Biesheuvel */ 3268e0a22e2SArvind Sankar status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy); 3278e0a22e2SArvind Sankar if (status == EFI_SUCCESS) 3288e0a22e2SArvind Sankar return gop; 3298e0a22e2SArvind Sankar 3308e0a22e2SArvind Sankar if (!first_gop) 3318de8788dSArvind Sankar first_gop = gop; 332fc372064SArd Biesheuvel } 333fc372064SArd Biesheuvel 334ecf53091SArvind Sankar return first_gop; 335ecf53091SArvind Sankar } 336ecf53091SArvind Sankar 337ecf53091SArvind Sankar static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, 338ecf53091SArvind Sankar unsigned long size, void **handles) 339ecf53091SArvind Sankar { 340ecf53091SArvind Sankar efi_graphics_output_protocol_t *gop; 341ecf53091SArvind Sankar efi_graphics_output_protocol_mode_t *mode; 342e484c594SArvind Sankar efi_graphics_output_mode_info_t *info; 343ecf53091SArvind Sankar efi_physical_addr_t fb_base; 344ecf53091SArvind Sankar 345ecf53091SArvind Sankar gop = find_gop(proto, size, handles); 346ecf53091SArvind Sankar 347fc372064SArd Biesheuvel /* Did we find any GOPs? */ 348ecf53091SArvind Sankar if (!gop) 3496fc3cec3SArvind Sankar return EFI_NOT_FOUND; 350fc372064SArd Biesheuvel 351fffb6804SArvind Sankar /* Change mode if requested */ 352fffb6804SArvind Sankar set_mode(gop); 353fffb6804SArvind Sankar 354fc372064SArd Biesheuvel /* EFI framebuffer */ 355ecf53091SArvind Sankar mode = efi_table_attr(gop, mode); 3566327e6d0SArvind Sankar info = efi_table_attr(mode, info); 3576327e6d0SArvind Sankar 358fc372064SArd Biesheuvel si->orig_video_isVGA = VIDEO_TYPE_EFI; 359fc372064SArd Biesheuvel 3606327e6d0SArvind Sankar si->lfb_width = info->horizontal_resolution; 3616327e6d0SArvind Sankar si->lfb_height = info->vertical_resolution; 362fc372064SArd Biesheuvel 3636327e6d0SArvind Sankar fb_base = efi_table_attr(mode, frame_buffer_base); 364f1d1853bSArvind Sankar si->lfb_base = lower_32_bits(fb_base); 365f1d1853bSArvind Sankar si->ext_lfb_base = upper_32_bits(fb_base); 3666327e6d0SArvind Sankar if (si->ext_lfb_base) 367fc372064SArd Biesheuvel si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; 368fc372064SArd Biesheuvel 369fc372064SArd Biesheuvel si->pages = 1; 370fc372064SArd Biesheuvel 3716327e6d0SArvind Sankar setup_pixel_info(si, info->pixels_per_scan_line, 3726327e6d0SArvind Sankar info->pixel_information, info->pixel_format); 373fc372064SArd Biesheuvel 374fc372064SArd Biesheuvel si->lfb_size = si->lfb_linelength * si->lfb_height; 375fc372064SArd Biesheuvel 376fc372064SArd Biesheuvel si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; 3776fc3cec3SArvind Sankar 378dbd89c30SArvind Sankar return EFI_SUCCESS; 379fc372064SArd Biesheuvel } 380fc372064SArd Biesheuvel 381fc372064SArd Biesheuvel /* 382fc372064SArd Biesheuvel * See if we have Graphics Output Protocol 383fc372064SArd Biesheuvel */ 384cd33a5c1SArd Biesheuvel efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, 385fc372064SArd Biesheuvel unsigned long size) 386fc372064SArd Biesheuvel { 387fc372064SArd Biesheuvel efi_status_t status; 388fc372064SArd Biesheuvel void **gop_handle = NULL; 389fc372064SArd Biesheuvel 390966291f6SArd Biesheuvel status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, 391966291f6SArd Biesheuvel (void **)&gop_handle); 392fc372064SArd Biesheuvel if (status != EFI_SUCCESS) 393fc372064SArd Biesheuvel return status; 394fc372064SArd Biesheuvel 395966291f6SArd Biesheuvel status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, proto, NULL, 396966291f6SArd Biesheuvel &size, gop_handle); 397fc372064SArd Biesheuvel if (status != EFI_SUCCESS) 398fc372064SArd Biesheuvel goto free_handle; 399fc372064SArd Biesheuvel 400cd33a5c1SArd Biesheuvel status = setup_gop(si, proto, size, gop_handle); 401fc372064SArd Biesheuvel 402fc372064SArd Biesheuvel free_handle: 403966291f6SArd Biesheuvel efi_bs_call(free_pool, gop_handle); 404fc372064SArd Biesheuvel return status; 405fc372064SArd Biesheuvel } 406