From patchwork Thu Apr 28 08:09:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 567134 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:6886:0:0:0:0 with SMTP id m6csp5233237map; Thu, 28 Apr 2022 01:12:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzeypVj7VYpQwKtCSuWKLVtK8B37GjzhOD7v9rwPsl0PZ+iUmWuY4SxlwSCsXi34J3+XQuY X-Received: by 2002:a17:907:2d2a:b0:6f3:85a0:3987 with SMTP id gs42-20020a1709072d2a00b006f385a03987mr22187719ejc.383.1651133564544; Thu, 28 Apr 2022 01:12:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651133564; cv=none; d=google.com; s=arc-20160816; b=DjUkKnvtQ8+q2paNWt/uLunebNUv6ykeEKF2DPbx1c4MCEmXnEnzQoVVVaeRyw/RBI QFQvaHT0KLmih9PDX5jCFCJRGl5z0LBgzufskRzOHnxRRwWaP2aCkGuu6duJrxelGxTQ qZa7HX8C88lnyoPCDpjfGq63toiF6ahi3dtagH0RI5ah5uLdBruLZNt0cGLB40PIn5vh ufiVp9c2PKHYsr9+CvRk+fzzDHNBRQMVX2X2QF+3icav0qSwihkrGtolVRGKjQwttmLE 9cIAcikgVIwGMAHlSXhuKQpKbhC++W+o8ELPke3RvLsGYsZFaaHbpJZ8h/7RppNH8/kc ktTQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=0EQ3MOONx8H9Vnow2CgVj7ug336Cl++Am4tz+bMuhPg=; b=aAieVutWa5zk7LAszXtmd8e/N3sOgpdl+Ir6qhyNeDhPj1TDspGXwigY/43M5vmTip FIDCzO0e1a9DR5cvIJIe2e5WZ6bZZxSNOHKvy5uGZd2fSPV1IHsZOy39BBPN9in6rVFO ELWe1uW12jHel0+IfatuH9DEY3YdEk98KMmLyMaY3qJrhzyVOqNMktk8AIDe4hPKC6C8 AB6eqXcqT/unJfbbtBK2R3/aH/zdAISVhx7W/m+I+UqciInv/H6c93i8B5s/khR+6YBt eCcAK6jwJq6879A4b2qyA1XLoMuSYfNaVOTLnLF8ZlJic1ijaW9n2NohNU3ta97EsdlL GSfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GcP2topi; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id j25-20020aa7de99000000b00425c2dd8b9asi3322772edv.296.2022.04.28.01.12.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Apr 2022 01:12:44 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GcP2topi; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0822883EE6; Thu, 28 Apr 2022 10:11:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="GcP2topi"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CBE2E834AD; Thu, 28 Apr 2022 10:11:11 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9F2DC834AD for ; Thu, 28 Apr 2022 10:11:05 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=masahisa.kojima@linaro.org Received: by mail-pg1-x532.google.com with SMTP id 15so3387222pgf.4 for ; Thu, 28 Apr 2022 01:11:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0EQ3MOONx8H9Vnow2CgVj7ug336Cl++Am4tz+bMuhPg=; b=GcP2topiwuxIQFkegS+heerL1pg3B3C3iSn7ZCgF5CIGj4i0S3yAVQ6LnQtAQ2wRQO 5JAsgCYfddyEJWsFbUX06LUdJfw0On4Hpz+4vDwDuxLQLQo0Pc954ZEja3RDiUENhnvH gNWE6uUS5VTVPFxJBDaneAolLY7gGp4yPK1wZeOn8OAcjmDB2Im+IXfHerN6a+Fh5Ap/ 8Dlnl/PG2kMH0h8RYxQwnbNNsoK9vjgdZpmrU51rpngO7eKIZ4+t8AOKCdl7sqxA2t0+ xj+osF7z1vsVehGOhMgzUX2KiTrdSL5HZmFcTu81L1LUpt9LysKGDAGNq89JRRqZMV3P aYFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=0EQ3MOONx8H9Vnow2CgVj7ug336Cl++Am4tz+bMuhPg=; b=XRoi9fhVCSJULkq+HKSobC8P8zd1gI7Nitr2YwdGf69SsPJgDH5jbp1KAqIFUzYGmG zmHtjfVUPC8B/ZhgHgFGUucCgz0JpcSS3x/BgCPhWtSvyQLKN3ipFytBFcI5xtpg6Ogj Qfwace9RzZ4PIx7MP/csZ8BO8ZivGaQJzGdZmnBST8Afxyh53w339vHQ4uTYZeoNytil vx/c04QQLCnhHvmi2PZT26U4T2bVcrL0ELT6kGMaVCFhgTJ6X9kiOvwTDYMK6FJco+6b EHGn7vVichi+N0GduSK3/2NCDyMfkrOriFBChVRp50np9a2KsclNYcjRgaxy3pRUiCx4 tbKg== X-Gm-Message-State: AOAM532Qset0LDJx6yXjiNgwP5+4Hzlox6rRLBz1URofTtkv9244DA7D PhlS9CkEfhgazH3CJjzY1turdPFgFIJBFQ== X-Received: by 2002:a65:4848:0:b0:39c:c393:688c with SMTP id i8-20020a654848000000b0039cc393688cmr26839228pgs.376.1651133463820; Thu, 28 Apr 2022 01:11:03 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id b15-20020a17090a7acf00b001cd4989ff5fsm5684259pjl.38.2022.04.28.01.11.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Apr 2022 01:11:03 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Simon Glass , Takahiro Akashi , Francois Ozog , Mark Kettenis , Masahisa Kojima Subject: [PATCH v5 10/17] bootmenu: add distro boot entry Date: Thu, 28 Apr 2022 17:09:43 +0900 Message-Id: <20220428080950.23509-11-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220428080950.23509-1-masahisa.kojima@linaro.org> References: <20220428080950.23509-1-masahisa.kojima@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean This commit adds the distro_boot entries into the bootmenu. The bootmenu read the "boot_targets" U-Boot environment variable and enumerate it. User can select the distro boot entry, then bootmenu executes "run bootcmd_xxx" command. The bootmenu also checks the existing block devices and network option("dhcp" and "pxe") availability, then filter out the "boot_targets" appeared in bootmenu. The bootmenu example is as follows, distro boot entry has the "distro_boot" prefix. *** U-Boot Boot Menu *** distro_boot : usb0 distro_boot : scsi0 distro_boot : virtio0 distro_boot : dhcp Signed-off-by: Masahisa Kojima --- Changes in v5: - split into the separate patch - add function description comment - handle the case boot_targets variable is empty - filter out the non-exist device entry cmd/bootmenu.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index da688e6213..afe42b8041 100644 --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include @@ -31,6 +33,7 @@ enum boot_type { BOOTMENU_TYPE_NONE = 0, BOOTMENU_TYPE_BOOTMENU, BOOTMENU_TYPE_UEFI_BOOT_OPTION, + BOOTMENU_TYPE_DISTRO_BOOT, }; struct bootmenu_entry { @@ -90,6 +93,8 @@ static void bootmenu_print_entry(void *data) printf("bootmenu_%02d : %ls", entry->bootorder, entry->title); else if (entry->type == BOOTMENU_TYPE_UEFI_BOOT_OPTION) printf("UEFI BOOT%04X : %ls", entry->bootorder, entry->title); + else if (entry->type == BOOTMENU_TYPE_DISTRO_BOOT) + printf("distro_boot : %ls", entry->title); else printf("%ls", entry->title); @@ -465,6 +470,172 @@ static int prepare_uefi_bootorder_entry(struct bootmenu_data *menu, return 1; } +static int is_blk_device_available(char *token) +{ + struct driver *d = ll_entry_start(struct driver, driver); + const int n_ents = ll_entry_count(struct driver, driver); + struct driver *entry; + struct udevice *udev; + struct uclass *uc; + struct blk_desc *desc; + int ret, i; + const char *if_type_name; + + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return -ENODEV; + + for (entry = d; entry < d + n_ents; entry++) { + if (entry->id != UCLASS_BLK) + continue; + i = 0; + uclass_foreach_dev(udev, uc) { + if (udev->driver != entry) + continue; + desc = dev_get_uclass_plat(udev); + if_type_name = blk_get_if_type_name(desc->if_type); + if (strncmp(token, if_type_name, strlen(if_type_name)) == 0) { + char *p; + int j, len; + int devnum = 0; + + p = token + strlen(if_type_name); + len = strlen(p); + if (!len) + continue; /* no device number */ + + for (j = 0; j < len; j++) { + if (!isdigit(*p)) { + /* invalid device number */ + devnum = INT_MAX; + break; + } + devnum = (devnum * 10) + (*p++ - '0'); + } + + if (devnum == INT_MAX) + continue; + + if (devnum == desc->devnum) + return 1; + } + } + } + + if (strncmp(token, "dhcp", strlen("dhcp")) == 0) { + if (IS_ENABLED(CONFIG_CMD_DHCP)) + return 1; + } + + if (strncmp(token, "pxe", strlen("pxe")) == 0) { + if (IS_ENABLED(CONFIG_CMD_PXE)) + return 1; + } + + return -ENODEV; +} + +/** + * prepare_distro_boot_entry() - generate the distro boot entries + * + * This function read the "boot_targets" U-Boot environment variable + * and generate the bootmenu entries. + * + * @menu: pointer to the bootmenu structure + * @current: pointer to the last bootmenu entry list + * @index: pointer to the index of the last bootmenu entry, + * the number of uefi entry is added by this function + * Return: 1 on success, negative value on error + */ +static int prepare_distro_boot_entry(struct bootmenu_data *menu, + struct bootmenu_entry **current, + unsigned short int *index) +{ + char *p; + int len; + char *token; + char *boot_targets; + unsigned short int i = *index; + struct bootmenu_entry *entry = NULL; + struct bootmenu_entry *iter = *current; + + /* list the distro boot "boot_targets" */ + boot_targets = env_get("boot_targets"); + if (!boot_targets) + return -ENOENT; + + len = strlen(boot_targets); + if (!len) + return -ENOENT; + + p = calloc(1, len + 1); + strlcpy(p, boot_targets, len); + + token = strtok(p, " "); + + do { + u16 *buf; + char *command; + int command_size; + + if (is_blk_device_available(token) != 1) { + token = strtok(NULL, " "); + continue; + } + + entry = malloc(sizeof(struct bootmenu_entry)); + if (!entry) { + free(p); + return -ENOMEM; + } + + len = strlen(token); + buf = calloc(1, (len + 1) * sizeof(u16)); + entry->title = buf; + if (!entry->title) { + free(entry); + free(p); + return -ENOMEM; + } + utf8_utf16_strncpy(&buf, token, len); + sprintf(entry->key, "%d", i); + entry->num = i; + entry->menu = menu; + + command_size = sizeof("run bootcmd_") + len; + command = calloc(1, command_size); + if (!command) { + free(entry->title); + free(entry); + free(p); + return -ENOMEM; + } + snprintf(command, command_size, "run bootcmd_%s", token); + entry->command = command; + entry->type = BOOTMENU_TYPE_DISTRO_BOOT; + entry->next = NULL; + + if (!iter) + menu->first = entry; + else + iter->next = entry; + + iter = entry; + i++; + + if (i == MAX_COUNT - 1) + break; + + token = strtok(NULL, " "); + } while (token); + + free(p); + *index = i; + *current = iter; + + return 1; +} + static struct bootmenu_data *bootmenu_create(int delay) { int ret; @@ -498,6 +669,12 @@ static struct bootmenu_data *bootmenu_create(int delay) } } + if (i < MAX_COUNT - 1) { + ret = prepare_distro_boot_entry(menu, &iter, &i); + if (ret < 0 && ret != -ENOENT) + goto cleanup; + } + /* Add U-Boot console entry at the end */ if (i <= MAX_COUNT - 1) { entry = malloc(sizeof(struct bootmenu_entry));