All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>,
	Steffen Jaeckel <jaeckel-floss@eyet-services.de>,
	Michal Simek <michal.simek@xilinx.com>,
	Tom Rini <trini@konsulko.com>, Dennis Gilmore <dennis@ausil.us>,
	Daniel Schwierzeck <daniel.schwierzeck@gmail.com>,
	Lukas Auer <lukas.auer@aisec.fraunhofer.de>,
	Simon Glass <sjg@chromium.org>
Subject: [PATCH 20/28] bootmethod: Add an implementation of distro boot
Date: Wed, 18 Aug 2021 21:45:53 -0600	[thread overview]
Message-ID: <20210818214547.20.Iafd004865970e7357960cacc4981e212e4cf3d16@changeid> (raw)
In-Reply-To: <20210819034601.1618773-1-sjg@chromium.org>

Add a bootmethod type which handles distro boot, so we can boot a bootflow
using this commonly used mechanism.

In effect, this provides the same functionality as the 'pxe' and 'sysboot'
commands and shares the same code. But the interface into it is via a
bootmethod.

For now this requires the 'pxe' command be enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 MAINTAINERS          |   2 +
 boot/Kconfig         |  11 +++
 boot/Makefile        |   1 +
 boot/bootmethod.c    |  14 ++++
 boot/distro.c        | 194 +++++++++++++++++++++++++++++++++++++++++++
 include/bootmethod.h |   2 +
 include/distro.h     |  62 ++++++++++++++
 7 files changed, 286 insertions(+)
 create mode 100644 boot/distro.c
 create mode 100644 include/distro.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d977cee562b..f78141c138b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -634,7 +634,9 @@ BOOTMETHOD
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	boot/bootmethod.c
+F:	boot/distro.c
 F:	include/bootmethod.h
+F:	include/distro.h
 
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
diff --git a/boot/Kconfig b/boot/Kconfig
index 90f716c3ef1..8565fbeab84 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -299,6 +299,17 @@ config BOOTMETHOD
 	  iterating through available bootmethods to find a bootflow suitable
 	  for booting.
 
+config BOOTMETHOD_DISTRO
+	bool "Bootmethod support for distro boot"
+	depends on BOOTMETHOD && CMD_PXE
+	default y
+	help
+	  Enables support for distro boot using bootmethods. This makes the
+	  bootmethods look for a 'extlinux/extlinux.conf' on each filesystem
+	  they scan.
+
+	  This provides a way to try out bootmethod on an existing boot flow.
+
 config LEGACY_IMAGE_FORMAT
 	bool "Enable support for the legacy image format"
 	default y if !FIT_SIGNATURE
diff --git a/boot/Makefile b/boot/Makefile
index 10d427e115c..4ce721242b0 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -23,6 +23,7 @@ obj-y += image.o
 obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD) += bootmethod.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD_DISTRO) += distro.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
 obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
diff --git a/boot/bootmethod.c b/boot/bootmethod.c
index 8e4157c6a47..be9d4aa02cc 100644
--- a/boot/bootmethod.c
+++ b/boot/bootmethod.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <blk.h>
 #include <bootmethod.h>
+#include <distro.h>
 #include <dm.h>
 #include <fs.h>
 #include <log.h>
@@ -34,6 +35,7 @@ static const char *const bootmethod_state[BOOTFLOWST_COUNT] = {
 };
 
 static const char *const bootmethod_type[BOOTFLOWT_COUNT] = {
+	"distro-boot",
 };
 
 int bootmethod_get_state(struct bootflow_state **statep)
@@ -360,6 +362,12 @@ int bootmethod_find_in_blk(struct udevice *dev, struct udevice *blk, int seq,
 
 	bflow->state = BOOTFLOWST_FS;
 
+	if (CONFIG_IS_ENABLED(BOOTMETHOD_DISTRO)) {
+		ret = distro_boot_setup(desc, partnum, bflow);
+		if (ret)
+			return log_msg_ret("distro", ret);
+	}
+
 	return 0;
 }
 
@@ -372,6 +380,12 @@ int bootflow_boot(struct bootflow *bflow)
 		return log_msg_ret("load", -EPROTO);
 
 	switch (bflow->type) {
+	case BOOTFLOWT_DISTRO:
+		if (CONFIG_IS_ENABLED(BOOTMETHOD_DISTRO)) {
+			done = true;
+			ret = distro_boot(bflow);
+		}
+		break;
 	case BOOTFLOWT_COUNT:
 		break;
 	}
diff --git a/boot/distro.c b/boot/distro.c
new file mode 100644
index 00000000000..062a8535ef1
--- /dev/null
+++ b/boot/distro.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * distro boot implementation for bootflow
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <bootmethod.h>
+#include <command.h>
+#include <distro.h>
+#include <dm.h>
+#include <fs.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <net.h>
+#include <pxe_utils.h>
+#include <vsprintf.h>
+
+#define DISTRO_FNAME	"extlinux/extlinux.conf"
+
+/**
+ * struct distro_info - useful information for distro_getfile()
+ *
+ * @bflow: bootflow being booted
+ */
+struct distro_info {
+	struct bootflow *bflow;
+};
+
+static int distro_net_getfile(struct pxe_context *ctx, const char *file_path,
+			      char *file_addr, ulong *sizep)
+{
+	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
+	int ret;
+
+	printf("get %s %s\n", file_addr, file_path);
+	tftp_argv[1] = file_addr;
+	tftp_argv[2] = (void *)file_path;
+
+	if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
+		return -ENOENT;
+	ret = pxe_get_file_size(sizep);
+	if (ret)
+		return log_msg_ret("tftp", ret);
+
+	return 0;
+}
+
+int distro_net_setup(struct bootflow *bflow)
+{
+	const char *addr_str;
+	char fname[200];
+	char *bootdir;
+	ulong addr;
+	ulong size;
+	char *buf;
+	int ret;
+
+	addr_str = env_get("pxefile_addr_r");
+	if (!addr_str)
+		return log_msg_ret("pxeb", -EPERM);
+	addr = simple_strtoul(addr_str, NULL, 16);
+
+	bflow->type = BOOTFLOWT_DISTRO;
+	ret = pxe_get(addr, &bootdir, &size);
+	if (ret)
+		return log_msg_ret("pxeb", ret);
+	bflow->size = size;
+
+	/* Use the directory of the dhcp bootdir as our subdir, if provided */
+	if (bootdir) {
+		const char *last_slash;
+		int path_len;
+
+		last_slash = strrchr(bootdir, '/');
+		if (last_slash) {
+			path_len = (last_slash - bootdir) + 1;
+			bflow->subdir = malloc(path_len + 1);
+			memcpy(bflow->subdir, bootdir, path_len);
+			bflow->subdir[path_len] = '\0';
+		}
+	}
+	snprintf(fname, sizeof(fname), "%s%s",
+		 bflow->subdir ? bflow->subdir : "", DISTRO_FNAME);
+
+	bflow->fname = strdup(fname);
+	if (!bflow->fname)
+		return log_msg_ret("name", -ENOMEM);
+
+	bflow->state = BOOTFLOWST_LOADED;
+
+	/* Allocate the buffer, including the \0 byte added by get_pxe_file() */
+	buf = malloc(size + 1);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+	memcpy(buf, map_sysmem(addr, 0), size + 1);
+	bflow->buf = buf;
+
+	return 0;
+}
+
+int distro_boot_setup(struct blk_desc *desc, int partnum,
+		      struct bootflow *bflow)
+{
+	loff_t size, bytes_read;
+	ulong addr;
+	char *buf;
+	int ret;
+
+	bflow->type = BOOTFLOWT_DISTRO;
+	bflow->fname = strdup(DISTRO_FNAME);
+	if (!bflow->fname)
+		return log_msg_ret("name", -ENOMEM);
+	ret = fs_size(bflow->fname, &size);
+	if (ret)
+		return log_msg_ret("size", ret);
+	bflow->state = BOOTFLOWST_FILE;
+	bflow->size = size;
+	log_debug("   - distro file size %x\n", (uint)size);
+	if (size > 0x10000)
+		return log_msg_ret("chk", -E2BIG);
+
+	/* Sadly FS closes the file after fs_size() so we must redo this */
+	ret = fs_set_blk_dev_with_part(desc, partnum);
+	if (ret)
+		return log_msg_ret("set", ret);
+
+	buf = malloc(size + 1);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+	addr = map_to_sysmem(buf);
+
+	ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
+	if (ret) {
+		free(buf);
+		return log_msg_ret("read", ret);
+	}
+	if (size != bytes_read)
+		return log_msg_ret("bread", -EINVAL);
+	buf[size] = '\0';
+	bflow->state = BOOTFLOWST_LOADED;
+	bflow->buf = buf;
+
+	return 0;
+}
+
+static int disto_getfile(struct pxe_context *ctx, const char *file_path,
+			 char *file_addr, ulong *sizep)
+{
+	struct distro_info *info = ctx->userdata;
+	struct bootflow *bflow = info->bflow;
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	loff_t len_read;
+	ulong addr;
+	int ret;
+
+	addr = simple_strtoul(file_addr, NULL, 16);
+	ret = fs_set_blk_dev_with_part(desc, bflow->part);
+	if (ret)
+		return ret;
+	ret = fs_read(file_path, addr, 0, 0, &len_read);
+	if (ret)
+		return ret;
+	*sizep = len_read;
+
+	return 0;
+}
+
+int distro_boot(struct bootflow *bflow)
+{
+	struct cmd_tbl cmdtp = {};	/* dummy */
+	struct pxe_context ctx;
+	struct distro_info info;
+	bool is_net = !bflow->blk;
+	ulong addr;
+	int ret;
+
+	addr = map_to_sysmem(bflow->buf);
+	info.bflow = bflow;
+	ret = pxe_setup_ctx(&ctx, &cmdtp,
+			    is_net ? distro_net_getfile : disto_getfile,
+			    &info, !is_net, bflow->subdir);
+	if (ret)
+		return log_msg_ret("ctx", -EINVAL);
+
+	ret = pxe_process(&ctx, addr, false);
+	if (ret)
+		return log_msg_ret("bread", -EINVAL);
+
+	return 0;
+}
diff --git a/include/bootmethod.h b/include/bootmethod.h
index a45897b0c0c..d80be556b8a 100644
--- a/include/bootmethod.h
+++ b/include/bootmethod.h
@@ -24,6 +24,8 @@ enum bootflow_state_t {
 };
 
 enum bootflow_type_t {
+	BOOTFLOWT_DISTRO,	/**< Distro boot */
+
 	BOOTFLOWT_COUNT,
 };
 
diff --git a/include/distro.h b/include/distro.h
new file mode 100644
index 00000000000..80b8da4bed3
--- /dev/null
+++ b/include/distro.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __distro_h
+#define __distro_h
+
+struct blk_desc;
+
+/**
+ * distro_boot_setup() - Set up a bootflow for distro boot from a block device
+ *
+ * This fills out a bootflow for a particular boot device and partition. It
+ * scans for a filesystem and suitable file, updating the bootflow accordingly.
+ *
+ * This sets the following fields in @bflow:
+ *
+ *	type, size, fname, state, subdir, buf
+ *
+ * The caller mast have already set the other fields.
+ *
+ * @desc: Block-device descriptor
+ * @partnum: Partition number (1..)
+ * @bflow: Partial bootflow to be completed by this function
+ * @return 0 on success (bootflow got to 'loaded' state), -ve on error
+ */
+int distro_boot_setup(struct blk_desc *desc, int partnum,
+		      struct bootflow *bflow);
+
+/**
+ * distro_boot_setup() - Set up a bootflow for distro boot from a network device
+ *
+ * This fills out a bootflow for a network device. It scans the tftp server for
+ * a suitable file, updating the bootflow accordingly.
+ *
+ * At present no control is provided as to which network device is used.
+ *
+ * This sets the following fields in @bflow:
+ *
+ *	type, size, fname, state,, buf
+ *
+ * The caller mast have already set the other fields.
+ *
+ * @bflow: Partial bootflow to be completed by this function
+ * @return 0 on success (bootflow got to 'loaded' state), -ve on error
+ */
+int distro_net_setup(struct bootflow *bflow);
+
+/**
+ * distro_boot() - Boot a distro
+ *
+ * Boots a bootflow of type BOOTFLOWT_DISTRO. This typically needs to load more
+ * files as it processes and this is done via the same media as the bootflow
+ * was loaded
+ *
+ * @bflow: Bootflow to boot
+*/
+int distro_boot(struct bootflow *bflow);
+
+#endif
-- 
2.33.0.rc1.237.g0d66db33f3-goog


  parent reply	other threads:[~2021-08-19  3:50 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
2021-08-19  3:45 ` [PATCH 01/28] Create a new boot/ directory Simon Glass
2021-08-19  3:45 ` [PATCH 02/28] pxe: Move API comments to the header files Simon Glass
2021-08-19  3:45 ` [PATCH 03/28] pxe: Use a context pointer Simon Glass
2021-08-19  3:45 ` [PATCH 04/28] pxe: Move do_getfile() into the context Simon Glass
2021-08-19  3:45 ` [PATCH 05/28] pxe: Add a userdata field to " Simon Glass
2021-08-19  3:45 ` [PATCH 06/28] pxe: Tidy up the is_pxe global Simon Glass
2021-08-19  3:45 ` [PATCH 07/28] pxe: Move pxe_utils files Simon Glass
2021-08-19  3:45 ` [PATCH 08/28] pxe: Tidy up some comments in pxe_utils Simon Glass
2021-08-19  3:45 ` [PATCH 09/28] pxe: Tidy up code style a little " Simon Glass
2021-08-19  3:45 ` [PATCH 10/28] pxe: Move common parsing coding into pxe_util Simon Glass
2021-08-19  3:45 ` [PATCH 11/28] pxe: Clean up the use of bootfile Simon Glass
2021-08-19  3:45 ` [PATCH 12/28] pxe: Drop get_bootfile_path() Simon Glass
2021-08-19  3:45 ` [PATCH 13/28] lib: Add tests for simple_itoa() Simon Glass
2021-08-19  3:45 ` [PATCH 14/28] lib: Add a function to convert a string to a hex value Simon Glass
2021-08-19  3:45 ` [PATCH 15/28] pxe: Return the file size from the getfile() function Simon Glass
2021-08-19  3:45 ` [PATCH 16/28] pxe: Refactor sysboot to have one helper Simon Glass
2021-08-19  3:45 ` [PATCH 17/28] doc: Move distro boot doc to rST Simon Glass
2021-08-19  3:45 ` [PATCH 18/28] pxe: Allow calling the pxe_get logic directly Simon Glass
2021-08-19  3:45 ` [PATCH 19/28] bootmethod: Add the uclass and core implementation Simon Glass
2021-08-19  3:45 ` Simon Glass [this message]
2021-08-19  3:45 ` [PATCH 21/28] bootmethod: Add a command Simon Glass
2021-08-19  3:45 ` [PATCH 22/28] bootflow: " Simon Glass
2021-08-19  3:45 ` [PATCH 23/28] bootmethod: Add tests for bootmethod and bootflow Simon Glass
2021-08-19  3:45 ` [PATCH 24/28] bootmethod: doc: Add documentation Simon Glass
2021-08-19  3:45 ` [PATCH 25/28] mmc: Allow for children other than the block device Simon Glass
2021-08-19  3:45 ` [PATCH 26/28] mmc: Add a bootmethod Simon Glass
2021-08-19  3:46 ` [PATCH 27/28] ethernet: " Simon Glass
2021-08-19  3:46 ` [PATCH 28/28] RFC: rpi: Switch over to use bootflow Simon Glass
2021-08-19 13:59 ` [PATCH 00/28] Initial implementation of bootmethod/bootflow Tom Rini
2021-08-19 14:25   ` Simon Glass
2021-08-19 17:27     ` Tom Rini
2021-08-23 12:35       ` Ilias Apalodimas
2021-08-23 17:25         ` Simon Glass
2021-08-23 20:08           ` Tom Rini
2021-08-24  9:29             ` Ilias Apalodimas
2021-08-25 13:11               ` Simon Glass
2021-08-25 13:29                 ` Peter Robinson
2021-08-25 21:34                   ` Mark Kettenis
2021-08-25 21:58                     ` Tom Rini
2021-08-20  3:15     ` AKASHI Takahiro
2021-08-20 18:22       ` Simon Glass
2021-08-23  0:46         ` AKASHI Takahiro
2021-08-23 11:54 ` Mark Kettenis
2021-08-23 17:25   ` Simon Glass
2021-08-23 20:01     ` Tom Rini
2021-08-24 10:22       ` Mark Kettenis
2021-08-25 10:45         ` Emmanuel Vadot
2021-08-25 13:11           ` Simon Glass
2021-08-25 14:42             ` AKASHI Takahiro
2021-08-25 14:56               ` Tom Rini
2021-08-25 21:54                 ` Mark Kettenis
2021-08-25 22:06                   ` Tom Rini
2021-08-26  6:33                     ` AKASHI Takahiro
2021-08-26 13:03                       ` Tom Rini
2021-08-26 12:01                     ` Mark Kettenis
2021-08-26 13:00                       ` Tom Rini
2021-08-26 13:32                         ` Mark Kettenis
2021-08-26 13:50                           ` Ilias Apalodimas
2021-08-26 11:55                 ` Peter Robinson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210818214547.20.Iafd004865970e7357960cacc4981e212e4cf3d16@changeid \
    --to=sjg@chromium.org \
    --cc=daniel.schwierzeck@gmail.com \
    --cc=dennis@ausil.us \
    --cc=ilias.apalodimas@linaro.org \
    --cc=jaeckel-floss@eyet-services.de \
    --cc=lukas.auer@aisec.fraunhofer.de \
    --cc=michal.simek@xilinx.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.