From patchwork Sat May 26 03:53:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ge Song X-Patchwork-Id: 920868 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40t8Wn5wGPz9s0x for ; Sat, 26 May 2018 13:59:33 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="feFPFusQ"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40t8Wn45G7zDr10 for ; Sat, 26 May 2018 13:59:33 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="feFPFusQ"; dkim-atps=neutral X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:400e:c01::242; helo=mail-pl0-x242.google.com; envelope-from=songgebird@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="feFPFusQ"; dkim-atps=neutral Received: from mail-pl0-x242.google.com (mail-pl0-x242.google.com [IPv6:2607:f8b0:400e:c01::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40t8WZ745pzDqH3 for ; Sat, 26 May 2018 13:59:22 +1000 (AEST) Received: by mail-pl0-x242.google.com with SMTP id t12-v6so4198634plo.7 for ; Fri, 25 May 2018 20:59:22 -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=LHn9aJQ0qSoIk91NIZLlLStfrMy19bVT7yywYsjR4L8=; b=feFPFusQ+WSFicxRQ9W/7aaqB7VRi0GcI8lt1CILJTUG4gYoz4EuqcpaGlhN0P0AJk Lf1D1Awz1nkBoH64mh98+EuA1/kC6uTyYxc/+GLAbzGFK41Z1HK3x6k0F6fKYqCr0s6I AMnHuYjWdzU22wqfsR7Dewcl7mJcYiVK3q4KsTfk98VbQmqHTGwWXrvxvpnH8astw+zU fJ0pxLuVQq9TXuxZVCmZEtNtQDP8NhfrwWghrKa0cAdpyYIAy5ZvElhD/ZfZU6B5Qut/ 4HUISCnDga0dePVsqEjSdyVMVF/swgRKwIBSxc9ijyc0/VXdgNGjQRZ8x37gptOmfcRN xC4Q== 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=LHn9aJQ0qSoIk91NIZLlLStfrMy19bVT7yywYsjR4L8=; b=DOFt9RZhg7hoLxBOixtomS8NHx61WspnXmrjB6Aozd0m016gUMUWhpQnLCqjiiP0GW p8KsmMqtRiuO4v3O3/Jzotj4v5TrsQ0ApLOrFNmeUFA0miymN32aVy4xCdfS4NLof+sI 7atovb/CJ/YqpKcuKEbuE1WCnyGrjjrRIugvw6t8g5A4lHK7vKjcMTZyEMKTbqA6yKCz n639dJG60keuAOiViX9FDGRBcLs/Fr81HL2fFiTr/ftcZ3aM0DuroRlDHV5fzBiVJqkj TyV9nHc6re8dBuRW+l3W/HKBeWuKK6TRnUorblWm4Mu12l4QimBdZCQQZmPgk59OwFFb 2fnw== X-Gm-Message-State: ALKqPwdITqTnUo0h/QWZn7Gn0ynmaPpSc2xWIiCVgvlej4iRVr/yKAxO BeMTsABEmkYeRDR/MRao/0Rj9ouu X-Google-Smtp-Source: AB8JxZrVgEOL/Zim37ACOGomW/WhCVn1aFadPxPJwDxoL8fR6j5kP+x/idM9RuwDawdMY8mFwXjTHQ== X-Received: by 2002:a17:902:26a:: with SMTP id 97-v6mr5131252plc.367.1527307160190; Fri, 25 May 2018 20:59:20 -0700 (PDT) Received: from localhost.localdomain ([2002:9922:19f0:0:2c2:c6ff:fe3b:c671]) by smtp.gmail.com with ESMTPSA id v15-v6sm47761679pfa.107.2018.05.25.20.59.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 25 May 2018 20:59:19 -0700 (PDT) From: Ge Song X-Google-Original-From: Ge Song To: petitboot@lists.ozlabs.org, sam@mendozajonas.com Subject: [PATCH v4 1/2] Platform: Add a platform file which is suitable for arm64 Platform. Date: Sat, 26 May 2018 11:53:58 +0800 Message-Id: <20180526035359.24024-2-ge.song@hxt-semitech.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180526035359.24024-1-ge.song@hxt-semitech.com> References: <20180526035359.24024-1-ge.song@hxt-semitech.com> X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ge Song MIME-Version: 1.0 Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" 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 Signed-off-by: Ge Song <ge.song@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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, +}; + +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;