From patchwork Thu Jul 27 21:38:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 794579 X-Patchwork-Delegate: agraf@suse.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="J9UjnQYP"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xJQSV35YRz9s3T for ; Fri, 28 Jul 2017 07:42:50 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 12480C21F88; Thu, 27 Jul 2017 21:40:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 00DECC21F09; Thu, 27 Jul 2017 21:39:31 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 68F8DC21DE5; Thu, 27 Jul 2017 21:38:31 +0000 (UTC) Received: from mail-qt0-f195.google.com (mail-qt0-f195.google.com [209.85.216.195]) by lists.denx.de (Postfix) with ESMTPS id C11ECC21EE5 for ; Thu, 27 Jul 2017 21:38:28 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id i19so11110829qte.1 for ; Thu, 27 Jul 2017 14:38:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7WWZWQsMMg+kEAYusbmvM5LG89eLAo+ZM4rCPvoau5o=; b=J9UjnQYPXvAMA1noEq/cOqDwaUATOqAI9GH09SSXqT/cVH4I+Fh/zJ7cvRyHV4CpAu BFCDsowYY6Wovt+Q5SH0qS6GMBR205jpUVF1SldazXdXXol4/QvER2xFTsCq1O5W03SW OwF10doAl7xabFLckfxGszOS54ms9IITfOB2nQHb9WN7iva9iWvhe0ZX9Nwn0E0iS/Uk 6r6/1/wx2wDRuqNE+LjxXzNYGIgzZ9uWDkmQlnoEuXCCMqnoAA6M7sXVEcHEFQaIacVm u6A5oGg8VSDKaFnuh6ROaCKxyVjt50g9I0KjWYNageDxyoSpnV2j9jTW+P8K9+kfx/2a +HZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7WWZWQsMMg+kEAYusbmvM5LG89eLAo+ZM4rCPvoau5o=; b=CAlJJu+qdj3RyMfcZqADqCOt/5lbIxXrrCW+m47P+W5+HU6HoZRRXbneaoWyVDKyAg wcbgSMaRpsqebk5ubdtTOJpuxeASjV6piUhJeJqad6rMHwrFj1AhQMOmVY+PFHWNGN0g ByYo6mqzG8yTlArHmaf1zUeUpZkx0rkHXJRgKgP51PXACnC4oHy00P3IP6JI5PAinfDH DT7fxmCbpJanD9MTgftnxFFjG+biBBBEjhAooZMF9M7bv7x6NzNaNm9AxUmU2e42hjhg CI+dyTbEm7mPeLnL+PN6pyR8nrlhEkKwBkiBOqpNhqtDVBhciTWk36kRFR50cr0Jyn3O Y3jQ== X-Gm-Message-State: AIVw112zhwX9U5Sg4iE8tojTGjsgcyuYCLtc+b4uN4Oj8gXTNaKI03cN 5i73bUT69swuxbqxwI8= X-Received: by 10.237.63.131 with SMTP id s3mr5682185qth.90.1501191507450; Thu, 27 Jul 2017 14:38:27 -0700 (PDT) Received: from localhost ([144.121.20.162]) by smtp.gmail.com with ESMTPSA id 37sm2885055qto.87.2017.07.27.14.38.26 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 27 Jul 2017 14:38:26 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Thu, 27 Jul 2017 17:38:05 -0400 Message-Id: <20170727213807.7523-9-robdclark@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170727213807.7523-1-robdclark@gmail.com> References: <20170727213807.7523-1-robdclark@gmail.com> Cc: xypron.glpk@gmx.de Subject: [U-Boot] [RFC 08/10] efi_loader: refactor boot device and loaded_image handling X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Get rid of the hacky fake boot-device and duplicate device-path constructing (which needs to match what efi_disk and efi_net do). Instead convert over to use efi_device_path helpers to construct device-paths, and use that to look up the actual boot device. Also, extract out a helper to plug things in properly to the loaded_image. In a following patch we'll want to re-use this in efi_load_image() to handle the case of loading an image from a file_path. Signed-off-by: Rob Clark --- cmd/bootefi.c | 163 +++++++++++++----------------------------- include/efi_loader.h | 3 + lib/efi_loader/efi_boottime.c | 35 +++++++++ 3 files changed, 87 insertions(+), 114 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d20775eccd..5b97958e4d 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -43,76 +43,16 @@ static struct efi_device_path_file_path bootefi_image_path[] = { } }; -static struct efi_device_path_file_path bootefi_device_path[] = { - { - .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH, - .dp.length = sizeof(bootefi_image_path[0]), - .str = { 'b','o','o','t','e','f','i' }, - }, { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(bootefi_image_path[0]), - } -}; - -/* The EFI loaded_image interface for the image executed via "bootefi" */ -static struct efi_loaded_image loaded_image_info = { - .device_handle = bootefi_device_path, - .file_path = bootefi_image_path, -}; - -/* The EFI object struct for the image executed via "bootefi" */ -static struct efi_object loaded_image_info_obj = { - .handle = &loaded_image_info, - .protocols = { - { - /* - * When asking for the loaded_image interface, just - * return handle which points to loaded_image_info - */ - .guid = &efi_guid_loaded_image, - .protocol_interface = &loaded_image_info, - }, - { - /* - * When asking for the device path interface, return - * bootefi_device_path - */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path, - }, - { - .guid = &efi_guid_console_control, - .protocol_interface = (void *) &efi_console_control - }, - { - .guid = &efi_guid_device_path_to_text_protocol, - .protocol_interface = (void *) &efi_device_path_to_text - }, - }, -}; - -/* The EFI object struct for the device the "bootefi" image was loaded from */ -static struct efi_object bootefi_device_obj = { - .handle = bootefi_device_path, - .protocols = { - { - /* When asking for the device path interface, return - * bootefi_device_path */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path - } - }, -}; +/* if we have CONFIG_DM we construct a proper device-path from the + * boot device, otherwise fallback to using bootefi_device_path. + */ +static struct efi_device_path *bootefi_device_path; /* Initialize and populate EFI object list */ static void efi_init_obj_list(void) { efi_obj_list_initalized = 1; - list_add_tail(&loaded_image_info_obj.link, &efi_obj_list); - list_add_tail(&bootefi_device_obj.link, &efi_obj_list); efi_console_register(); #ifdef CONFIG_PARTITIONS efi_disk_register(); @@ -121,13 +61,7 @@ static void efi_init_obj_list(void) efi_gop_register(); #endif #ifdef CONFIG_NET - void *nethandle = loaded_image_info.device_handle; - efi_net_register(&nethandle); - - if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6)) - loaded_image_info.device_handle = nethandle; - else - loaded_image_info.device_handle = bootefi_device_path; + efi_net_register(); #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE efi_smbios_register(); @@ -212,12 +146,24 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( */ static unsigned long do_bootefi_exec(void *efi, void *fdt) { + static struct efi_loaded_image loaded_image_info = {0}; + static struct efi_object loaded_image_info_obj = {0}; + ulong ret; + ulong (*entry)(void *image_handle, struct efi_system_table *st) asmlinkage; ulong fdt_pages, fdt_size, fdt_start, fdt_end; const efi_guid_t fdt_guid = EFI_FDT_GUID; bootm_headers_t img = { 0 }; + /* Initialize and populate EFI object list */ + if (!efi_obj_list_initalized) + efi_init_obj_list(); + + efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, + bootefi_device_path, + (struct efi_device_path *)bootefi_image_path); + /* * gd lives in a fixed register which may get clobbered while we execute * the payload. So save it here and restore it on every callback entry @@ -255,10 +201,6 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) if (!entry) return -ENOENT; - /* Initialize and populate EFI object list */ - if (!efi_obj_list_initalized) - efi_init_obj_list(); - /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); @@ -282,7 +224,12 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) } #endif - return efi_do_enter(&loaded_image_info, &systab, entry); + ret = efi_do_enter(&loaded_image_info, &systab, entry); + + /* image has returned, loaded-image obj goes *poof*: */ + list_del(&loaded_image_info_obj.link); + + return ret; } @@ -344,58 +291,46 @@ U_BOOT_CMD( bootefi_help_text ); -void efi_set_bootdev(const char *dev, const char *devnr, const char *path) +static int parse_partnum(const char *devnr) { - __maybe_unused struct blk_desc *desc; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - char *colon, *s; - -#if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION) - desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); -#endif - -#ifdef CONFIG_BLK - if (desc) { - snprintf(devname, sizeof(devname), "%s", desc->bdev->name); - } else -#endif - - { - /* Assemble the condensed device name we use in efi_disk.c */ - snprintf(devname, sizeof(devname), "%s%s", dev, devnr); + const char *str = strchr(devnr, ':'); + if (str) { + str++; + return simple_strtoul(str, NULL, 16); } + return 0; +} - colon = strchr(devname, ':'); - -#if CONFIG_IS_ENABLED(ISO_PARTITION) - /* For ISOs we create partition block devices */ - if (desc && (desc->type != DEV_TYPE_UNKNOWN) && - (desc->part_type == PART_TYPE_ISO)) { - if (!colon) - snprintf(devname, sizeof(devname), "%s:1", devname); +void efi_set_bootdev(const char *dev, const char *devnr, const char *path) +{ + char filename[32] = { 0 }; /* dp->str is u16[32] long */ + char *s; - colon = NULL; - } -#endif + if (strcmp(dev, "Net")) { + static struct blk_desc *desc; + static int part; - if (colon) - *colon = '\0'; + desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); + part = parse_partnum(devnr); - /* Patch bootefi_device_path to the target device */ - memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str)); - ascii2unicode(bootefi_device_path[0].str, devname); + bootefi_device_path = efi_dp_from_part(desc, part); + } else { +#ifdef CONFIG_NET + bootefi_device_path = efi_dp_from_eth(); +#endif + } /* Patch bootefi_image_path to the target file path */ memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str)); if (strcmp(dev, "Net")) { /* Add leading / to fs paths, because they're absolute */ - snprintf(devname, sizeof(devname), "/%s", path); + snprintf(filename, sizeof(filename), "/%s", path); } else { - snprintf(devname, sizeof(devname), "%s", path); + snprintf(filename, sizeof(filename), "%s", path); } /* DOS style file path: */ - s = devname; + s = filename; while ((s = strchr(s, '/'))) *s++ = '\\'; - ascii2unicode(bootefi_image_path[0].str, devname); + ascii2unicode(bootefi_image_path[0].str, filename); } diff --git a/include/efi_loader.h b/include/efi_loader.h index c5cc15fc4c..208beffa78 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -201,6 +201,9 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table efi_status_t efi_get_protocol(struct efi_object *efiobj, struct efi_handler *handler, void **protocol_interface); +void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj, + struct efi_device_path *device_path, + struct efi_device_path *file_path); #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER extern void *efi_bounce_buffer; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 9ce550f5d2..aa342670c2 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -714,6 +714,41 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, return EFI_EXIT(efi_install_configuration_table(guid, table)); } +/* Initialize a loaded_image_info + loaded_image_info object with correct + * protocols, boot-device, etc. + */ +void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj, + struct efi_device_path *device_path, + struct efi_device_path *file_path) +{ + obj->handle = info; + + /* + * When asking for the device path interface, return + * bootefi_device_path + */ + obj->protocols[0].guid = &efi_guid_device_path; + obj->protocols[0].protocol_interface = device_path; + + /* + * When asking for the loaded_image interface, just + * return handle which points to loaded_image_info + */ + obj->protocols[1].guid = &efi_guid_loaded_image; + obj->protocols[1].protocol_interface = info; + + obj->protocols[2].guid = &efi_guid_console_control; + obj->protocols[2].protocol_interface = (void *)&efi_console_control; + + obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol; + obj->protocols[3].protocol_interface = (void *)&efi_guid_device_path_to_text_protocol; + + info->file_path = file_path; + info->device_handle = efi_dp_find_obj(device_path); + + list_add_tail(&obj->link, &efi_obj_list); +} + static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_handle_t parent_image, struct efi_device_path *file_path,