On 8 September 2016 at 01:02, Lukas Wunner <lukas@xxxxxxxxx> wrote: > Use LocateHandleBuffer instead of the LocateHandle + AllocatePool + > LocateHandle combo to save a bit on code. > > Usage of LocateHandle for UGA and GOP has been present in the efistub > since its introduction with commit 291f36325f9f ("x86, efi: EFI boot > stub support"). It was subsequently inherited by the PCI ROM retrieval > with commit dd5fc854de5f ("EFI: Stash ROMs if they're not in the PCI > BAR"). > > One valid reason to not use LocateHandleBuffer would be if a specific > memory type is required for the buffer, and particularly if the buffer > needs to persist across ExitBootServices. The spec does not mandate > which type is used, edk2 seems to default to EfiBootServicesData. > In the three use cases modified by this commit (UGA, GOP, PCI), the > buffer is freed before ExitBootServices is called. Hence the memory > type is irrelevant. > > No functional change intended. > > Cc: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> > Signed-off-by: Lukas Wunner <lukas@xxxxxxxxx> > --- > What is the oldest UEFI version we claim to support? For ARM, this is not an issue, but it appears that LocateHandleBuffer () was introduced in v1.10 > The patch can be reviewed somewhat more comfortably with green/red > highlighting on GitHub: > https://github.com/l1k/linux/commit/2ff1fc10c84f > > It depends on two patches which are already queued in Matt's tree for 4.9: > > "x86/efi: Optimize away setup_gop32/64 if unused" > https://patchwork.kernel.org/patch/9315763/ > > "x86/efi: Allow invocation of arbitrary boot services" > https://patchwork.kernel.org/patch/9293371/ > > arch/x86/boot/compressed/eboot.c | 90 ++++++++++----------------------- > drivers/firmware/efi/libstub/arm-stub.c | 17 ++++--- > drivers/firmware/efi/libstub/gop.c | 29 +++-------- > include/linux/efi.h | 5 +- > 4 files changed, 47 insertions(+), 94 deletions(-) > > diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c > index 447a6a2..87c8d31 100644 > --- a/arch/x86/boot/compressed/eboot.c > +++ b/arch/x86/boot/compressed/eboot.c > @@ -340,13 +340,12 @@ free_struct: > > static void > setup_efi_pci32(struct boot_params *params, void **pci_handle, > - unsigned long size) > + unsigned long nr_pci) > { > efi_pci_io_protocol_32 *pci = NULL; > efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; > u32 *handles = (u32 *)(unsigned long)pci_handle; > efi_status_t status; > - unsigned long nr_pci; > struct setup_data *data; > int i; > > @@ -355,7 +354,6 @@ setup_efi_pci32(struct boot_params *params, void **pci_handle, > while (data && data->next) > data = (struct setup_data *)(unsigned long)data->next; > > - nr_pci = size / sizeof(u32); > for (i = 0; i < nr_pci; i++) { > struct pci_setup_rom *rom = NULL; > u32 h = handles[i]; > @@ -447,13 +445,12 @@ free_struct: > > static void > setup_efi_pci64(struct boot_params *params, void **pci_handle, > - unsigned long size) > + unsigned long nr_pci) > { > efi_pci_io_protocol_64 *pci = NULL; > efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; > u64 *handles = (u64 *)(unsigned long)pci_handle; > efi_status_t status; > - unsigned long nr_pci; > struct setup_data *data; > int i; > > @@ -462,7 +459,6 @@ setup_efi_pci64(struct boot_params *params, void **pci_handle, > while (data && data->next) > data = (struct setup_data *)(unsigned long)data->next; > > - nr_pci = size / sizeof(u64); > for (i = 0; i < nr_pci; i++) { > struct pci_setup_rom *rom = NULL; > u64 h = handles[i]; > @@ -502,53 +498,38 @@ setup_efi_pci64(struct boot_params *params, void **pci_handle, > static void setup_efi_pci(struct boot_params *params) > { > efi_status_t status; > - void **pci_handle = NULL; > + void **pci_handle; > efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; > - unsigned long size = 0; > + unsigned long nr_pci; > > - status = efi_call_early(locate_handle, > + status = efi_call_early(locate_handle_buffer, > EFI_LOCATE_BY_PROTOCOL, > - &pci_proto, NULL, &size, pci_handle); > + &pci_proto, NULL, &nr_pci, &pci_handle); > > - if (status == EFI_BUFFER_TOO_SMALL) { > - status = efi_call_early(allocate_pool, > - EFI_LOADER_DATA, > - size, (void **)&pci_handle); > - > - if (status != EFI_SUCCESS) { > - efi_printk(sys_table, "Failed to alloc mem for pci_handle\n"); > - return; > - } > - > - status = efi_call_early(locate_handle, > - EFI_LOCATE_BY_PROTOCOL, &pci_proto, > - NULL, &size, pci_handle); > - } > + if (status == EFI_OUT_OF_RESOURCES) > + efi_printk(sys_table, "Failed to alloc mem for pci_handle\n"); > > if (status != EFI_SUCCESS) > - goto free_handle; > + return; > > if (efi_early->is64) > - setup_efi_pci64(params, pci_handle, size); > + setup_efi_pci64(params, pci_handle, nr_pci); > else > - setup_efi_pci32(params, pci_handle, size); > + setup_efi_pci32(params, pci_handle, nr_pci); > > -free_handle: > efi_call_early(free_pool, pci_handle); > } > > static efi_status_t > -setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) > +setup_uga32(void **uga_handle, unsigned long nr_ugas, u32 *width, u32 *height) > { > struct efi_uga_draw_protocol *uga = NULL, *first_uga; > efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; > - unsigned long nr_ugas; > u32 *handles = (u32 *)uga_handle;; > efi_status_t status = EFI_INVALID_PARAMETER; > int i; > > first_uga = NULL; > - nr_ugas = size / sizeof(u32); > for (i = 0; i < nr_ugas; i++) { > efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; > u32 w, h, depth, refresh; > @@ -583,17 +564,15 @@ setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) > } > > static efi_status_t > -setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height) > +setup_uga64(void **uga_handle, unsigned long nr_ugas, u32 *width, u32 *height) > { > struct efi_uga_draw_protocol *uga = NULL, *first_uga; > efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; > - unsigned long nr_ugas; > u64 *handles = (u64 *)uga_handle;; > efi_status_t status = EFI_INVALID_PARAMETER; > int i; > > first_uga = NULL; > - nr_ugas = size / sizeof(u64); > for (i = 0; i < nr_ugas; i++) { > efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; > u32 w, h, depth, refresh; > @@ -631,30 +610,18 @@ setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height) > * See if we have Universal Graphics Adapter (UGA) protocol > */ > static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, > - unsigned long size) > + unsigned long nr_ugas, void **uga_handle) > { > efi_status_t status; > u32 width, height; > - void **uga_handle = NULL; > - > - status = efi_call_early(allocate_pool, EFI_LOADER_DATA, > - size, (void **)&uga_handle); > - if (status != EFI_SUCCESS) > - return status; > - > - status = efi_call_early(locate_handle, > - EFI_LOCATE_BY_PROTOCOL, > - uga_proto, NULL, &size, uga_handle); > - if (status != EFI_SUCCESS) > - goto free_handle; > > height = 0; > width = 0; > > if (efi_early->is64) > - status = setup_uga64(uga_handle, size, &width, &height); > + status = setup_uga64(uga_handle, nr_ugas, &width, &height); > else > - status = setup_uga32(uga_handle, size, &width, &height); > + status = setup_uga32(uga_handle, nr_ugas, &width, &height); > > if (!width && !height) > goto free_handle; > @@ -686,27 +653,26 @@ void setup_graphics(struct boot_params *boot_params) > struct screen_info *si; > efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; > efi_status_t status; > - unsigned long size; > - void **gop_handle = NULL; > - void **uga_handle = NULL; > + unsigned long nr; > + void **gop_handle; > + void **uga_handle; > > si = &boot_params->screen_info; > memset(si, 0, sizeof(*si)); > > - size = 0; > - status = efi_call_early(locate_handle, > + status = efi_call_early(locate_handle_buffer, > EFI_LOCATE_BY_PROTOCOL, > - &graphics_proto, NULL, &size, gop_handle); > - if (status == EFI_BUFFER_TOO_SMALL) > - status = efi_setup_gop(NULL, si, &graphics_proto, size); > + &graphics_proto, NULL, &nr, &gop_handle); > + if (status == EFI_SUCCESS) > + status = efi_setup_gop(NULL, si, &graphics_proto, nr, > + gop_handle); > > if (status != EFI_SUCCESS) { > - size = 0; > - status = efi_call_early(locate_handle, > + status = efi_call_early(locate_handle_buffer, > EFI_LOCATE_BY_PROTOCOL, > - &uga_proto, NULL, &size, uga_handle); > - if (status == EFI_BUFFER_TOO_SMALL) > - setup_uga(si, &uga_proto, size); > + &uga_proto, NULL, &nr, &uga_handle); > + if (status == EFI_SUCCESS) > + setup_uga(si, &uga_proto, nr, uga_handle); > } > } > > diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c > index 993aa56..27fd62d 100644 > --- a/drivers/firmware/efi/libstub/arm-stub.c > +++ b/drivers/firmware/efi/libstub/arm-stub.c > @@ -173,18 +173,19 @@ static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg) > { > efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; > efi_status_t status; > - unsigned long size; > - void **gop_handle = NULL; > + unsigned long nr; > + void **gop_handle; > struct screen_info *si = NULL; > > - size = 0; > - status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, > - &gop_proto, NULL, &size, gop_handle); > - if (status == EFI_BUFFER_TOO_SMALL) { > + status = efi_call_early(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL, > + &gop_proto, NULL, &nr, &gop_handle); > + if (status == EFI_SUCCESS) { > si = alloc_screen_info(sys_table_arg); > - if (!si) > + if (!si) { > + efi_call_early(free_pool, gop_handle); > return NULL; > - efi_setup_gop(sys_table_arg, si, &gop_proto, size); > + } > + efi_setup_gop(sys_table_arg, si, &gop_proto, nr, gop_handle); > } > return si; > } > diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c > index 932742e..a2dca32 100644 > --- a/drivers/firmware/efi/libstub/gop.c > +++ b/drivers/firmware/efi/libstub/gop.c > @@ -111,10 +111,9 @@ __gop_query32(efi_system_table_t *sys_table_arg, > > static efi_status_t > setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, > - efi_guid_t *proto, unsigned long size, void **gop_handle) > + efi_guid_t *proto, unsigned long nr_gops, void **gop_handle) > { > struct efi_graphics_output_protocol_32 *gop32, *first_gop; > - unsigned long nr_gops; > u16 width, height; > u32 pixels_per_scan_line; > u32 ext_lfb_base; > @@ -128,7 +127,6 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, > first_gop = NULL; > gop32 = NULL; > > - nr_gops = size / sizeof(u32); > for (i = 0; i < nr_gops; i++) { > struct efi_graphics_output_mode_info *info = NULL; > efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; > @@ -136,6 +134,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, > void *dummy = NULL; > efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; > u64 current_fb_base; > + unsigned long size; > > status = efi_call_early(handle_protocol, h, > proto, (void **)&gop32); > @@ -228,10 +227,9 @@ __gop_query64(efi_system_table_t *sys_table_arg, > > static efi_status_t > setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, > - efi_guid_t *proto, unsigned long size, void **gop_handle) > + efi_guid_t *proto, unsigned long nr_gops, void **gop_handle) > { > struct efi_graphics_output_protocol_64 *gop64, *first_gop; > - unsigned long nr_gops; > u16 width, height; > u32 pixels_per_scan_line; > u32 ext_lfb_base; > @@ -245,7 +243,6 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, > first_gop = NULL; > gop64 = NULL; > > - nr_gops = size / sizeof(u64); > for (i = 0; i < nr_gops; i++) { > struct efi_graphics_output_mode_info *info = NULL; > efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; > @@ -253,6 +250,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, > void *dummy = NULL; > efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; > u64 current_fb_base; > + unsigned long size; > > status = efi_call_early(handle_protocol, h, > proto, (void **)&gop64); > @@ -324,31 +322,18 @@ out: > */ > efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, > struct screen_info *si, efi_guid_t *proto, > - unsigned long size) > + unsigned long nr_gops, void **gop_handle) > { > efi_status_t status; > - void **gop_handle = NULL; > - > - status = efi_call_early(allocate_pool, EFI_LOADER_DATA, > - size, (void **)&gop_handle); > - if (status != EFI_SUCCESS) > - return status; > - > - status = efi_call_early(locate_handle, > - EFI_LOCATE_BY_PROTOCOL, > - proto, NULL, &size, gop_handle); > - if (status != EFI_SUCCESS) > - goto free_handle; > > if (efi_is_64bit()) { > - status = setup_gop64(sys_table_arg, si, proto, size, > + status = setup_gop64(sys_table_arg, si, proto, nr_gops, > gop_handle); > } else { > - status = setup_gop32(sys_table_arg, si, proto, size, > + status = setup_gop32(sys_table_arg, si, proto, nr_gops, > gop_handle); > } > > -free_handle: > efi_call_early(free_pool, gop_handle); > return status; > } > diff --git a/include/linux/efi.h b/include/linux/efi.h > index 4ae1a1a..52fe49d 100644 > --- a/include/linux/efi.h > +++ b/include/linux/efi.h > @@ -304,7 +304,8 @@ typedef struct { > void *close_protocol; > void *open_protocol_information; > void *protocols_per_handle; > - void *locate_handle_buffer; > + efi_status_t (*locate_handle_buffer)(int, efi_guid_t *, void *, > + unsigned long *, efi_handle_t **); > efi_status_t (*locate_protocol)(efi_guid_t *, void *, void **); > void *install_multiple_protocol_interfaces; > void *uninstall_multiple_protocol_interfaces; > @@ -1424,7 +1425,7 @@ efi_status_t efi_parse_options(char *cmdline); > > efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, > struct screen_info *si, efi_guid_t *proto, > - unsigned long size); > + unsigned long nr_gops, void **gop_handle); > > bool efi_runtime_disabled(void); > extern void efi_call_virt_check_flags(unsigned long flags, const char *call); > -- > 2.9.3 > -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html