[PATCH] discover: add platform-uboot

Samuel Mendoza-Jonas sam at mendozajonas.com
Tue May 14 16:05:47 AEST 2019


On Wed, 2019-05-01 at 21:12 -0500, Marty E. Plummer wrote:
> Currently exists as a fairly cut-down version of platform-powerpc.c
> 
> Signed-off-by: Marty E. Plummer <hanetzer at startmail.com>
> ---
> Greets all. As mentioned in the commit message, this is pretty much a
> clone of platform-powerpc.c, it more or less works, but I've found an
> issue I'm not sure how to get around based on the existing code.
> 
> At some point, the equivalent of `fw_setenv autoboot? true` gets called,
> but this ? corrupts the env. I'd have to do (manually from userspace)
> the following to get it saved right: `fw_setenv autoboot\? true`, but
> I'm not sure how, if at all, I can escape this in talloc_asprintf.
> 
> Does anyone have any suggestions as to how to do this?

Hi Marty,

I think I saw on IRC that you found a solution to this, was there any
news?

Cheers,
Sam

> 
> Marty E. Plummer
> ---
> Note: I currently have platform-uboot.c above platform-arm64.c because
> the probe function of arm64 does match what I have and will be
> prioritized over platform-uboot.c, this relates to my previous mailing
> about code sharing among arch's and firmware platforms (eg, mixing
> platform-efi.c [currently no-existant] and platfom-x86_64.c [same])
> 
>  configure.ac              |  18 ++-
>  discover/Makefile.am      |   4 +
>  discover/platform-uboot.c | 274 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 294 insertions(+), 2 deletions(-)
>  create mode 100644 discover/platform-uboot.c
> 
> diff --git a/configure.ac b/configure.ac
> index 5d541fb..c66aabc 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -334,7 +334,12 @@ AC_ARG_ENABLE(
>  )
>  AS_IF(
>  	[test "x$enable_platform_all" = "xyes"],
> -	[enable_platform_arm64="yes"; enable_platform_powerpc="yes"; enable_platform_ps3="yes"]
> +	[
> +	 enable_platform_arm64="yes";
> +	 enable_platform_powerpc="yes";
> +	 enable_platform_ps3="yes";
> +	 enable_platform_uboot="yes"
> +	 ]
>  )
>  
>  AC_ARG_ENABLE(
> @@ -349,7 +354,7 @@ AC_ARG_ENABLE(
>  AS_IF(
>  	[test "x$enable_platform_auto" = "xyes"],
>  	[AS_CASE([$host],
> -		[aarch64-*-*],   [enable_platform_arm64="yes"],
> +		[aarch64-*-*],   [enable_platform_arm64="yes";enable_platform_uboot="yes"],
>  		[powerpc*-*-*],  [enable_platform_powerpc="yes"],
>  	)]
>  )
> @@ -380,6 +385,15 @@ AC_ARG_ENABLE(
>  	)])
>  AM_CONDITIONAL([PLATFORM_PS3], [test "x$enable_platform_ps3" = "xyes"])
>  
> +AC_ARG_ENABLE(
> +	[platform-uboot],
> +	[AS_HELP_STRING(
> +		[--enable-platform-uboot],
> +		[build support for uboot platforms [default=no]]
> +	)]
> +)
> +AM_CONDITIONAL([PLATFORM_UBOOT], [test "x$enable_platform_uboot" = "xyes"])
> +
>  AC_ARG_ENABLE(
>  	[debug],
>  	[AS_HELP_STRING([--enable-debug],
> diff --git a/discover/Makefile.am b/discover/Makefile.am
> index bfe33fa..b95a7e3 100644
> --- a/discover/Makefile.am
> +++ b/discover/Makefile.am
> @@ -81,6 +81,10 @@ discover_platform_ro_SOURCES = \
>  	discover/dt.h \
>  	discover/hostboot.h
>  
> +if PLATFORM_UBOOT
> +discover_platform_ro_SOURCES += discover/platform-uboot.c
> +endif
> +
>  if PLATFORM_ARM64
>  discover_platform_ro_SOURCES += discover/platform-arm64.c
>  endif
> diff --git a/discover/platform-uboot.c b/discover/platform-uboot.c
> new file mode 100644
> index 0000000..1705a46
> --- /dev/null
> +++ b/discover/platform-uboot.c
> @@ -0,0 +1,274 @@
> +#include <string.h>
> +#include <sys/stat.h>
> +
> +#include <file/file.h>
> +#include <log/log.h>
> +#include <process/process.h>
> +#include <talloc/talloc.h>
> +#include <crypt/crypt.h>
> +
> +#include "platform.h"
> +
> +static const char *devtree_dir = "/proc/device-tree";
> +
> +struct platform_uboot {
> +	struct param_list *params;
> +};
> +
> +#define to_platform_uboot(p) \
> +	(struct platform_uboot*)(p->platform_data)
> +
> +static int parse_nvram_params(struct platform_uboot *platform,
> +			      char *buf, int len)
> +{
> +	char *pos, *name, *value;
> +	unsigned int paramlen;
> +
> +	for (pos = buf; pos < buf + len; pos += paramlen + 1) {
> +		unsigned int namelen;
> +		char *newline;
> +
> +		newline = strchr(pos, '\n');
> +		if (!newline)
> +			break;
> +
> +		*newline = '\0';
> +
> +		paramlen = strlen(pos);
> +
> +		name = pos;
> +		value = strchr(pos, '=');
> +		if (!value)
> +			continue;
> +
> +		namelen = value - name;
> +		if (namelen == 0)
> +			continue;
> +
> +		if (!param_list_is_known_n(platform->params, name, namelen))
> +			continue;
> +
> +		*value = '\0';
> +		value++;
> +
> +		param_list_set(platform->params, name, value, false);
> +	}
> +
> +	return 0;
> +}
> +
> +static int parse_nvram(struct platform_uboot *platform)
> +{
> +	struct process_stdout *stdout;
> +	const char *argv[2];
> +	int rc;
> +
> +	argv[0] = "fw_printenv";
> +	argv[1] = NULL;
> +
> +	rc = process_get_stdout_argv(NULL, &stdout, argv);
> +
> +	if (rc) {
> +		fprintf(stderr, "fw_printenv process returned "
> +			"non-zero exit status\n");
> +		rc = -1;
> +	} else {
> +		rc = parse_nvram_params(platform, stdout->buf, stdout->len);
> +	}
> +
> +	talloc_free(stdout);
> +	return rc;
> +}
> +
> +static int write_nvram(struct platform_uboot *platform)
> +{
> +	struct process *process;
> +	struct param *param;
> +	const char *argv[4];
> +	int rc = 0;
> +
> +	argv[0] = "fw_setenv";
> +	argv[1] = NULL;
> +	argv[2] = NULL;
> +	argv[3] = NULL;
> +
> +	process = process_create(platform);
> +	process->path = "fw_setenv";
> +	process->argv = argv;
> +
> +	param_list_for_each(platform->params, param) {
> +		char *paramname, *paramval;
> +
> +		if (!param->modified)
> +			continue;
> +
> +		paramname = talloc_asprintf(platform, "%s", param->name);
> +		argv[1] = paramname;
> +
> +		paramval = talloc_asprintf(platform, "%s", param->value);
> +		argv[2] = paramval;
> +
> +		rc = process_run_sync(process);
> +
> +		talloc_free(paramname);
> +		talloc_free(paramval);
> +
> +		if (rc || !process_exit_ok(process)) {
> +			rc = -1;
> +			pb_log("fw_setenv process returned non-zero exit status\n");
> +			break;
> +		}
> +	}
> +
> +	process_release(process);
> +	return rc;
> +}
> +
> +static void params_update_all(struct param_list *pl, const struct config *config,
> +			      const struct config *defaults)
> +{
> +	char *tmp = NULL;
> +	const char *val;
> +
> +	if (config->autoboot_enabled == defaults->autoboot_enabled)
> +		val = "";
> +	else
> +		val = config->autoboot_enabled ? "true" : "false";
> +
> +	param_list_set_non_empty(pl, "auto-boot?", val, true);
> +
> +	if (config->autoboot_timeout_sec == defaults->autoboot_timeout_sec)
> +		val = "";
> +	else
> +		val = tmp = talloc_asprintf(pl, "%d", config->autoboot_timeout_sec);
> +
> +	param_list_set_non_empty(pl, "petitboot,timeout", val, true);
> +	if (tmp)
> +		talloc_free(tmp);
> +
> +	val = config->lang ?: "";
> +	param_list_set_non_empty(pl, "petitboot,language", val, true);
> +
> +	if (config->allow_writes == defaults->allow_writes)
> +		val = "";
> +	else
> +		val = config->allow_writes ? "true" : "false";
> +	param_list_set_non_empty(pl, "petitboot,write?", val, true);
> +
> +	if (!config->manual_console) {
> +		val = config->boot_console ?: "";
> +		param_list_set_non_empty(pl, "petitboot,console", val, true);
> +	}
> +
> +	val = config->http_proxy ?: "";
> +	param_list_set_non_empty(pl, "petitboot,http_proxy", val, true);
> +	val = config->https_proxy ?: "";
> +	param_list_set_non_empty(pl, "petitboot,https_proxy", val, true);
> +
> +	params_update_network_values(pl, "petitboot,network", config);
> +	params_update_bootdev_values(pl, "petitboot,bootdevs", config);
> +}
> +
> +static void config_get_active_consoles(struct config *config)
> +{
> +	config->n_consoles = 2;
> +	config->consoles = talloc_array(config, char *, config->n_consoles);
> +	if (!config->consoles)
> +		goto err;
> +
> +	config->consoles[0] = talloc_asprintf(config->consoles,
> +					      "/dev/ttyS2 [Serial]");
> +	config->consoles[1] = talloc_asprintf(config->consoles,
> +					      "/dev/tty1 [VGA]");
> +
> +	return;
> +err:
> +	config->n_consoles = 0;
> +	pb_log("Failed to allocate memory for consoles\n");
> +}
> +
> +static int load_config(struct platform *p, struct config *config)
> +{
> +	struct platform_uboot *platform = to_platform_uboot(p);
> +	const char *hash;
> +	int rc;
> +
> +	rc = parse_nvram(platform);
> +	if (rc)
> +		pb_log_fn("Failed to parse nvram\n");
> +
> +	config_populate_all(config, platform->params);
> +
> +	config_get_active_consoles(config);
> +
> +	hash = param_list_get_value(platform->params, "petitboot,password");
> +	if (hash) {
> +		rc = crypt_set_password_hash(platform, hash);
> +		if (rc)
> +			pb_log("Failed to set password hash\n");
> +	}
> +
> +	return 0;
> +}
> +
> +static int save_config(struct platform *p, struct config *config)
> +{
> +	struct platform_uboot *platform = to_platform_uboot(p);
> +	struct config *defaults;
> +
> +	defaults = talloc_zero(platform, struct config);
> +	config_set_defaults(defaults);
> +
> +	params_update_all(platform->params, config, defaults);
> +
> +	talloc_free(defaults);
> +	return write_nvram(platform);
> +}
> +
> +static int get_sysinfo(struct platform *p, struct system_info *sysinfo)
> +{
> +	struct platform_uboot *platform = p->platform_data;
> +	char *buf, *filename;
> +	int len, rc;
> +
> +	filename = talloc_asprintf(platform, "%smodel", devtree_dir);
> +	rc = read_file(platform, filename, &buf, &len);
> +	if (rc == 0)
> +		sysinfo->type = talloc_steal(sysinfo, buf);
> +	talloc_free(filename);
> +
> +	return 0;
> +}
> +
> +static bool probe(struct platform *p, void *ctx)
> +{
> +	struct platform_uboot *platform;
> +	struct stat statbuf;
> +	int rc;
> +
> +	rc = stat("/proc/device-tree", &statbuf);
> +	if (rc)
> +		return false;
> +
> +	if (!S_ISDIR(statbuf.st_mode))
> +		return false;
> +
> +	platform = talloc_zero(ctx, struct platform_uboot);
> +	platform->params = talloc_zero(platform, struct param_list);
> +	param_list_init(platform->params, common_known_params());
> +
> +	p->platform_data = platform;
> +
> +	return true;
> +}
> +
> +static struct platform platform_uboot = {
> +	.name		= "uboot",
> +	.dhcp_arch_id	= 0x000d,
> +	.probe		= probe,
> +	.load_config	= load_config,
> +	.save_config	= save_config,
> +	.get_sysinfo	= get_sysinfo,
> +};
> +
> +register_platform(platform_uboot);




More information about the Petitboot mailing list