[PATCH v4 1/2] Platform: Add a platform file which is suitable for arm64 Platform.
Samuel Mendoza-Jonas
sam at mendozajonas.com
Wed May 30 10:33:44 AEST 2018
On Sat, 2018-05-26 at 11:53 +0800, Ge Song wrote:
> On arm64 servers, plenty of devices(especially for those bootable devices)
> cannot be supported from efi firmware. In this situation, linux&petitboot
> is the wonderful way to address the issue.
>
> Since efi is the primary firmware on arm64 servers, most of the management
> related works can be completed under that enviroment. Therefore some similar
> functions implemented in petitboot have been removed.
>
> Signed-off-by: Ge Song <ge.song at hxt-semitech.com>
> ---
> Since V4:
> * Platform-arm64.c: Revise code to remove the warning complained by compiler.
> Adjust to v4 lib efi to set efivarfs path in probe();
> * Platform.c: Remove one redundant line in config_set_defaults()(exist in
> master branch)
>
> discover/Makefile.am | 3 +-
> discover/platform-arm64.c | 746 ++++++++++++++++++++
> discover/platform.c | 1 -
> 3 files changed, 748 insertions(+), 2 deletions(-)
>
> diff --git a/discover/Makefile.am b/discover/Makefile.am
> index ef4c6027d128..3681caac586b 100644
> --- a/discover/Makefile.am
> +++ b/discover/Makefile.am
> @@ -82,7 +82,8 @@ discover_platform_ro_SOURCES = \
> discover/dt.c \
> discover/dt.h \
> discover/hostboot.h \
> - discover/platform-powerpc.c
> + discover/platform-powerpc.c \
> + discover/platform-arm64.c
>
> discover_platform_ro_CPPFLAGS = \
> $(AM_CPPFLAGS)
> diff --git a/discover/platform-arm64.c b/discover/platform-arm64.c
> new file mode 100644
> index 000000000000..24bf505fe2e3
> --- /dev/null
> +++ b/discover/platform-arm64.c
> @@ -0,0 +1,746 @@
> +/*
> + * Defines an arm64 platform, based on the powerpc platform.
> + *
> + * Actually, this is apply to platforms that adopt efi as its underlying
> + * firmware(x86/x64/arm64).
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + * Copyright (C) 2018 Huaxintong Semiconductor Technology Co.,Ltd. All rights
> + * reserved.
> + * Author: Ge Song <ge.song at hxt-semitech.com>
> + */
> +#include <errno.h>
> +#include <file/file.h>
> +#include <limits.h>
> +#include <list/list.h>
> +#include <log/log.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/fcntl.h>
> +#include <sys/statfs.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include <types/types.h>
> +
> +#include "efi/efivar.h"
> +#include "ipmi.h"
> +#include "platform.h"
> +#include "talloc/talloc.h"
> +
> +#define DEF_ATTR (EFI_VARIABLE_NON_VOLATILE | \
> + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)
> +static const char *pb_vars_guid = "fb78ab4b-bd43-41a0-99a2-4e74bef9169b";
> +static const int ipmi_timeout = 10000; /* milliseconds. */
> +
> +struct param {
> + char *name;
> + char *value;
> + bool modified;
> + struct list_item list;
> +};
> +
> +struct platform_arm64 {
> + struct list params;
> + struct ipmi *ipmi;
> +};
> +
> +static const char *known_params[] = {
> + "auto-boot?",
> + "network",
> + "timeout",
> + "bootdevs",
> + "language",
> + "debug?",
> + "write?",
> + "snapshots?",
> + "console",
> + "http_proxy",
> + "https_proxy",
> + NULL,
> +};
Along with what Geoff said, we may as well keep these parameter names the
same as found in platform-powerpc.c. Eg, "petitboot,snapshots?" rather
than just "snapshots?".
> +
> +static inline struct platform_arm64 *to_platform_arm64(struct platform *p)
> +{
> + return (struct platform_arm64 *)(p->platform_data);
> +}
> +
> +static void parse_nvram(struct platform_arm64 *platform)
> +{
> + int i, rc;
> + size_t size;
> + uint32_t attr;
> + uint8_t *data;
> + const char *pb_guid = pb_vars_guid;
> + const char *known_param;
> + struct param *param;
> +
> + for (i = 0; known_params[i]; i++) {
> + known_param = known_params[i];
> + rc = efi_get_variable(platform, pb_guid, known_param,
> + &data, &size, &attr);
> + if (!rc) {
> + param = talloc(platform, struct param);
> + param->modified = false;
> + param->name = talloc_strdup(platform, known_param);
> + param->value = talloc_strdup(platform, (char *)data);
> + list_add(&platform->params, ¶m->list);
> + }
> + }
> +}
> +
> +static void write_nvram(struct platform_arm64 *platform)
> +{
> + struct param *param;
> + const char *pb_guid = pb_vars_guid;
> + uint32_t attr = DEF_ATTR;
> + size_t data_size;
> +
> + list_for_each_entry(&platform->params, param, list) {
> + if (param->modified) {
> + data_size = strlen(param->value) + 1;
> + efi_set_variable(platform, pb_guid, param->name,
> + (uint8_t *)param->value, data_size, attr);
> + }
> + }
> +}
> +
> +static const char *get_param(struct platform_arm64 *platform,
> + const char *name)
> +{
> + struct param *param;
> +
> + list_for_each_entry(&platform->params, param, list)
> + if (!strcmp(param->name, name))
> + return param->value;
> + return NULL;
> +}
> +
> +static void set_param(struct platform_arm64 *platform, const char *name,
> + const char *value)
> +{
> + struct param *param;
> +
> + list_for_each_entry(&platform->params, param, list) {
> + if (strcmp(param->name, name))
> + continue;
> +
> + if (!strcmp(param->value, value))
> + return;
> +
> + talloc_free(param->value);
> + param->value = talloc_strdup(param, value);
> + param->modified = true;
> + return;
> + }
> +
> + param = talloc(platform, struct param);
> + param->modified = true;
> + param->name = talloc_strdup(platform, name);
> + param->value = talloc_strdup(platform, value);
> + list_add(&platform->params, ¶m->list);
> +}
> +
> +static int parse_hwaddr(struct interface_config *ifconf, char *str)
> +{
> + int i;
> +
> + if (strlen(str) != strlen("00:00:00:00:00:00"))
> + return -1;
> +
> + for (i = 0; i < HWADDR_SIZE; i++) {
> + char byte[3], *endp;
> + unsigned long x;
> +
> + byte[0] = str[i * 3 + 0];
> + byte[1] = str[i * 3 + 1];
> + byte[2] = '\0';
> +
> + x = strtoul(byte, &endp, 16);
> + if (endp != byte + 2)
> + return -1;
> +
> + ifconf->hwaddr[i] = x & 0xff;
> + }
> +
> + return 0;
> +}
> +
> +static int parse_one_interface_config(struct config *config,
> + char *confstr)
> +{
> + struct interface_config *ifconf;
> + char *tok, *saveptr;
> +
> + ifconf = talloc_zero(config, struct interface_config);
> +
> + if (!confstr || !strlen(confstr))
> + goto out_err;
> +
> + /* first token should be the mac address */
> + tok = strtok_r(confstr, ",", &saveptr);
> + if (!tok)
> + goto out_err;
> +
> + if (parse_hwaddr(ifconf, tok))
> + goto out_err;
> +
> + /* second token is the method */
> + tok = strtok_r(NULL, ",", &saveptr);
> + if (!tok || !strlen(tok) || !strcmp(tok, "ignore")) {
> + ifconf->ignore = true;
> +
> + } else if (!strcmp(tok, "dhcp")) {
> + ifconf->method = CONFIG_METHOD_DHCP;
> +
> + } else if (!strcmp(tok, "static")) {
> + ifconf->method = CONFIG_METHOD_STATIC;
> +
> + /* ip/mask, [optional] gateway, [optional] url */
> + tok = strtok_r(NULL, ",", &saveptr);
> + if (!tok)
> + goto out_err;
> + ifconf->static_config.address =
> + talloc_strdup(ifconf, tok);
> +
> + tok = strtok_r(NULL, ",", &saveptr);
> + if (tok) {
> + ifconf->static_config.gateway =
> + talloc_strdup(ifconf, tok);
> + }
> +
> + tok = strtok_r(NULL, ",", &saveptr);
> + if (tok) {
> + ifconf->static_config.url =
> + talloc_strdup(ifconf, tok);
> + }
> +
> + } else {
> + pb_log("Unknown network configuration method %s\n", tok);
> + goto out_err;
> + }
> +
> + config->network.interfaces = talloc_realloc(config,
> + config->network.interfaces,
> + struct interface_config *,
> + ++config->network.n_interfaces);
> +
> + config->network.interfaces[config->network.n_interfaces - 1] = ifconf;
> +
> + return 0;
> +out_err:
> + talloc_free(ifconf);
> + return -1;
> +}
> +
> +static int parse_one_dns_config(struct config *config,
> + char *confstr)
> +{
> + char *tok, *saveptr = NULL;
> +
> + for (tok = strtok_r(confstr, ",", &saveptr); tok;
> + tok = strtok_r(NULL, ",", &saveptr)) {
> +
> + char *server = talloc_strdup(config, tok);
> +
> + config->network.dns_servers = talloc_realloc(config,
> + config->network.dns_servers, const char *,
> + ++config->network.n_dns_servers);
> +
> + config->network.dns_servers[config->network.n_dns_servers - 1]
> + = server;
> + }
> +
> + return 0;
> +}
> +
> +static void populate_network_config(struct platform_arm64 *platform,
> + struct config *config)
> +{
> + char *val, *saveptr = NULL;
> + const char *cval;
> + int i;
> +
> + cval = get_param(platform, "network");
> + if (!cval || !strlen(cval))
> + return;
> +
> + val = talloc_strdup(config, cval);
> +
> + for (i = 0; ; i++) {
> + char *tok;
> +
> + tok = strtok_r(i == 0 ? val : NULL, " ", &saveptr);
> + if (!tok)
> + break;
> +
> + if (!strncasecmp(tok, "dns,", strlen("dns,")))
> + parse_one_dns_config(config, tok + strlen("dns,"));
> + else
> + parse_one_interface_config(config, tok);
> +
> + }
> +
> + talloc_free(val);
> +}
> +
> +static int read_bootdev(void *ctx, char **pos, struct autoboot_option *opt)
> +{
> + char *delim = strchr(*pos, ' ');
> + int len, prefix = 0, rc = -1;
> + enum device_type type;
> +
> + if (!strncmp(*pos, "uuid:", strlen("uuid:"))) {
> + prefix = strlen("uuid:");
> + opt->boot_type = BOOT_DEVICE_UUID;
> + } else if (!strncmp(*pos, "mac:", strlen("mac:"))) {
> + prefix = strlen("mac:");
> + opt->boot_type = BOOT_DEVICE_UUID;
> + } else {
> + type = find_device_type(*pos);
> + if (type != DEVICE_TYPE_UNKNOWN) {
> + opt->type = type;
> + opt->boot_type = BOOT_DEVICE_TYPE;
> + rc = 0;
> + }
> + }
> +
> + if (opt->boot_type == BOOT_DEVICE_UUID) {
> + if (delim)
> + len = (int)(delim - *pos) - prefix;
> + else
> + len = strlen(*pos) - prefix;
> +
> + if (len) {
> + opt->uuid = talloc_strndup(ctx, *pos + prefix, len);
> + rc = 0;
> + }
> + }
> +
> + /* Always advance pointer to next option or end */
> + if (delim)
> + *pos = delim + 1;
> + else
> + *pos += strlen(*pos);
> +
> + return rc;
> +}
> +
> +static void populate_bootdev_config(struct platform_arm64 *platform,
> + struct config *config)
> +{
> + struct autoboot_option *opt, *new = NULL;
> + char *pos, *end;
> + unsigned int n_new = 0;
> + const char *val;
> +
> + /* Check for ordered bootdevs */
> + val = get_param(platform, "bootdevs");
> + if (!val || !strlen(val)) {
> + pos = end = NULL;
> + } else {
> + pos = talloc_strdup(config, val);
> + end = strchr(pos, '\0');
> + }
> +
> + while (pos && pos < end) {
> + opt = talloc(config, struct autoboot_option);
> +
> + if (read_bootdev(config, &pos, opt)) {
> + pb_log("bootdev config is in an unknown format "
> + "(expected uuid:... or mac:...)\n");
> + talloc_free(opt);
> + continue;
> + }
> +
> + new = talloc_realloc(config, new, struct autoboot_option,
> + n_new + 1);
> + new[n_new] = *opt;
> + n_new++;
> + talloc_free(opt);
> +
> + }
> +
> + if (!n_new) {
> + /* If autoboot has been disabled, clear the default options */
> + if (!config->autoboot_enabled) {
> + talloc_free(config->autoboot_opts);
> + config->n_autoboot_opts = 0;
> + }
> + return;
> + }
> +
> + talloc_free(config->autoboot_opts);
> + config->autoboot_opts = new;
> + config->n_autoboot_opts = n_new;
> +}
> +
> +static void populate_config(struct platform_arm64 *platform,
> + struct config *config)
> +{
> + const char *val;
> + char *end;
> + unsigned long timeout;
> +
> + /* if the "auto-boot?' property is present and "false", disable auto
> + * boot */
> + val = get_param(platform, "auto-boot?");
> + config->autoboot_enabled = !val || strcmp(val, "false");
> +
> + val = get_param(platform, "timeout");
> + if (val) {
> + timeout = strtoul(val, &end, 10);
> + if (end != val) {
> + if (timeout >= INT_MAX)
> + timeout = INT_MAX;
> + config->autoboot_timeout_sec = (int)timeout;
> + }
> + }
> +
> + val = get_param(platform, "language");
> + config->lang = val ? talloc_strdup(config, val) : NULL;
> +
> + populate_network_config(platform, config);
> +
> + populate_bootdev_config(platform, config);
> +
> + if (!config->debug) {
> + val = get_param(platform, "debug?");
> + config->debug = val && !strcmp(val, "true");
> + }
> +
> + val = get_param(platform, "write?");
> + if (val)
> + config->allow_writes = !strcmp(val, "true");
> +
> + val = get_param(platform, "snapshots?");
> + if (val)
> + config->disable_snapshots = !strcmp(val, "false");
> +
> + val = get_param(platform, "console");
> + if (val)
> + config->boot_console = talloc_strdup(config, val);
> + /* If a full path is already set we don't want to override it */
> + config->manual_console = config->boot_console &&
> + !strchr(config->boot_console, '[');
> +
> + val = get_param(platform, "http_proxy");
> + if (val)
> + config->http_proxy = talloc_strdup(config, val);
> + val = get_param(platform, "https_proxy");
> + if (val)
> + config->https_proxy = talloc_strdup(config, val);
> +}
> +
> +static char *iface_config_str(void *ctx, struct interface_config *config)
> +{
> + char *str;
> +
> + /* todo: HWADDR size is hardcoded as 6, but we may need to handle
> + * different hardware address formats */
> + str = talloc_asprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x,",
> + config->hwaddr[0], config->hwaddr[1],
> + config->hwaddr[2], config->hwaddr[3],
> + config->hwaddr[4], config->hwaddr[5]);
> +
> + if (config->ignore) {
> + str = talloc_asprintf_append(str, "ignore");
> +
> + } else if (config->method == CONFIG_METHOD_DHCP) {
> + str = talloc_asprintf_append(str, "dhcp");
> +
> + } else if (config->method == CONFIG_METHOD_STATIC) {
> + str = talloc_asprintf_append(str, "static,%s%s%s%s%s",
> + config->static_config.address,
> + config->static_config.gateway ? "," : "",
> + config->static_config.gateway ?: "",
> + config->static_config.url ? "," : "",
> + config->static_config.url ?: "");
> + }
> + return str;
> +}
> +
> +static char *dns_config_str(void *ctx, const char **dns_servers, int n)
> +{
> + char *str;
> + int i;
> +
> + str = talloc_strdup(ctx, "dns,");
> + for (i = 0; i < n; i++) {
> + str = talloc_asprintf_append(str, "%s%s",
> + i == 0 ? "" : ",",
> + dns_servers[i]);
> + }
> +
> + return str;
> +}
> +
> +static void update_string_config(struct platform_arm64 *platform,
> + const char *name, const char *value)
> +{
> + const char *cur;
> +
> + cur = get_param(platform, name);
> +
> + /* don't set an empty parameter if it doesn't already exist */
> + if (!cur && !strlen(value))
> + return;
> +
> + set_param(platform, name, value);
> +}
> +
> +static void update_network_config(struct platform_arm64 *platform,
> + struct config *config)
> +{
> + unsigned int i;
> + char *val;
> +
> + /*
> + * Don't store IPMI overrides to NVRAM. If this was a persistent
> + * override it was already stored in NVRAM by
> + * get_ipmi_network_override()
> + */
> + if (config->network.n_interfaces &&
> + config->network.interfaces[0]->override)
> + return;
> +
> + val = talloc_strdup(platform, "");
> +
> + for (i = 0; i < config->network.n_interfaces; i++) {
> + char *iface_str = iface_config_str(platform,
> + config->network.interfaces[i]);
> + val = talloc_asprintf_append(val, "%s%s",
> + *val == '\0' ? "" : " ", iface_str);
> + talloc_free(iface_str);
> + }
> +
> + if (config->network.n_dns_servers) {
> + char *dns_str = dns_config_str(platform,
> + config->network.dns_servers,
> + config->network.n_dns_servers);
> + val = talloc_asprintf_append(val, "%s%s",
> + *val == '\0' ? "" : " ", dns_str);
> + talloc_free(dns_str);
> + }
> +
> + update_string_config(platform, "network", val);
> +
> + talloc_free(val);
> +}
> +
> +static void update_bootdev_config(struct platform_arm64 *platform,
> + struct config *config)
> +{
> + char *val = NULL, *boot_str = NULL, *tmp = NULL;
> + struct autoboot_option *opt;
> + const char delim = ' ';
> + unsigned int i;
> +
> + if (!config->n_autoboot_opts)
> + val = "";
> +
> + for (i = 0; i < config->n_autoboot_opts; i++) {
> + opt = &config->autoboot_opts[i];
> + switch (opt->boot_type) {
> + case BOOT_DEVICE_TYPE:
> + boot_str = talloc_asprintf(config, "%s%c",
> + device_type_name(opt->type),
> + delim);
> + break;
> + case BOOT_DEVICE_UUID:
> + boot_str = talloc_asprintf(config, "uuid:%s%c",
> + opt->uuid, delim);
> + break;
> + }
> + tmp = val = talloc_asprintf_append(val, "%s", boot_str);
> + }
> +
> + update_string_config(platform, "bootdevs", val);
> + talloc_free(tmp);
> + if (boot_str)
> + talloc_free(boot_str);
> +}
> +
> +static void update_config(struct platform_arm64 *platform,
> + struct config *config, struct config *defaults)
> +{
> + char *tmp = NULL;
> + const char *val;
> +
> + if (config->autoboot_enabled == defaults->autoboot_enabled)
> + val = "";
> + else
> + val = config->autoboot_enabled ? "true" : "false";
> + update_string_config(platform, "auto-boot?", val);
> +
> + if (config->autoboot_timeout_sec == defaults->autoboot_timeout_sec)
> + val = "";
> + else
> + val = tmp = talloc_asprintf(platform, "%d",
> + config->autoboot_timeout_sec);
> +
> + update_string_config(platform, "timeout", val);
> + if (tmp)
> + talloc_free(tmp);
> +
> + val = config->lang ?: "";
> + update_string_config(platform, "language", val);
> +
> + if (config->allow_writes == defaults->allow_writes)
> + val = "";
> + else
> + val = config->allow_writes ? "true" : "false";
> + update_string_config(platform, "write?", val);
> +
> + if (!config->manual_console) {
> + val = config->boot_console ?: "";
> + update_string_config(platform, "console", val);
> + }
> +
> + val = config->http_proxy ?: "";
> + update_string_config(platform, "http_proxy", val);
> + val = config->https_proxy ?: "";
> + update_string_config(platform, "https_proxy", val);
> +
> + update_network_config(platform, config);
> +
> + update_bootdev_config(platform, config);
> +
> + write_nvram(platform);
> +}
> +
> +static void get_ipmi_bmc_mac(struct platform *p, uint8_t *buf)
> +{
> + struct platform_arm64 *platform = p->platform_data;
> + uint16_t resp_len = 8;
> + uint8_t resp[8];
> + uint8_t req[] = { 0x1, 0x5, 0x0, 0x0 };
> + int i, rc;
> +
> + rc = ipmi_transaction(platform->ipmi, IPMI_NETFN_TRANSPORT,
> + IPMI_CMD_TRANSPORT_GET_LAN_PARAMS,
> + req, sizeof(req),
> + resp, &resp_len,
> + ipmi_timeout);
> +
> + pb_debug("BMC MAC resp [%d][%d]:\n", rc, resp_len);
> +
> + if (rc == 0 && resp_len > 0) {
> + for (i = 2; i < resp_len; i++) {
> + pb_debug(" %x", resp[i]);
> + buf[i - 2] = resp[i];
> + }
> + pb_debug("\n");
> + }
> +
> +}
> +
> +static void get_active_consoles(struct config *config)
> +{
> + config->n_consoles = 3;
> + config->consoles = talloc_array(config, char *, config->n_consoles);
> + if (!config->consoles)
> + goto err;
> +
> + config->consoles[0] = talloc_asprintf(config->consoles,
> + "/dev/hvc0 [IPMI / Serial]");
> + config->consoles[1] = talloc_asprintf(config->consoles,
> + "/dev/ttyAMA0 [Serial]");
> + config->consoles[2] = 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_arm64 *platform = to_platform_arm64(p);
> +
> + parse_nvram(platform);
> +
> + populate_config(platform, config);
> +
> + get_active_consoles(config);
> +
> + return 0;
> +}
> +
> +static int save_config(struct platform *p, struct config *config)
> +{
> + struct platform_arm64 *platform = to_platform_arm64(p);
> + struct config *defaults;
> +
> + defaults = talloc_zero(platform, struct config);
> + config_set_defaults(defaults);
> +
> + update_config(platform, config, defaults);
> +
> + talloc_free(defaults);
> +
> + return 0;
> +}
> +
> +static int get_sysinfo(struct platform *p, struct system_info *sysinfo)
> +{
> + struct platform_arm64 *platform = p->platform_data;
> +
> + sysinfo->bmc_mac = talloc_zero_size(sysinfo, HWADDR_SIZE);
> +
> + if (platform->ipmi)
> + get_ipmi_bmc_mac(p, sysinfo->bmc_mac);
> +
> + return 0;
> +}
> +
> +static bool probe(struct platform *p, void *ctx)
> +{
> + struct platform_arm64 *platform;
> + const char *path = "/sys/firmware/efi/efivars/";
> + int rc = 0;
> + struct statfs buf;
> +
> + if (access(path, F_OK))
> + return false;
> +
> + memset(&buf, '\0', sizeof(buf));
> + rc = statfs(path, &buf);
> + if (rc)
> + return false;
> +
> + typeof(buf.f_type) magic = EFIVARFS_MAGIC;
> + if (!memcmp(&buf.f_type, &magic, sizeof (magic))) {
> + platform = talloc_zero(ctx, struct platform_arm64);
> + list_init(&platform->params);
> + p->platform_data = platform;
> +
> + set_efivarfs_path(path);
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static struct platform platform_arm64 = {
> + .name = "arm64",
> + .dhcp_arch_id = 0x000d,
> + .probe = probe,
> + .load_config = load_config,
> + .save_config = save_config,
> + .get_sysinfo = get_sysinfo,
> +};
> +
> +register_platform(platform_arm64);
> diff --git a/discover/platform.c b/discover/platform.c
> index cc6306f035b9..bcf6b1141c7a 100644
> --- a/discover/platform.c
> +++ b/discover/platform.c
> @@ -121,7 +121,6 @@ void config_set_defaults(struct config *config)
>
> config->autoboot_enabled = true;
> config->autoboot_timeout_sec = 10;
> - config->autoboot_enabled = true;
> config->network.interfaces = NULL;
> config->network.n_interfaces = 0;
> config->network.dns_servers = NULL;
More information about the Petitboot
mailing list