mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-12 16:07:30 +00:00
Merge branch '2021-05-06-misc-updates'
- Allow for boards to update bootargs before booting the OS (helpful in some forms of secure boot). - Enhance GPT write support. - gpio-sysinfo updates - Allow env to be appended from dtb
This commit is contained in:
commit
1b8ad819ce
30 changed files with 516 additions and 36 deletions
|
@ -53,6 +53,13 @@
|
|||
osd0 = "/osd";
|
||||
};
|
||||
|
||||
config {
|
||||
environment {
|
||||
from_fdt = "yes";
|
||||
fdt_env_path = "";
|
||||
};
|
||||
};
|
||||
|
||||
audio: audio-codec {
|
||||
compatible = "sandbox,audio-codec";
|
||||
#sound-dai-cells = <1>;
|
||||
|
@ -1526,6 +1533,13 @@
|
|||
compatible = "sandbox,sysinfo-sandbox";
|
||||
};
|
||||
|
||||
sysinfo-gpio {
|
||||
compatible = "gpio-sysinfo";
|
||||
gpios = <&gpio_a 15>, <&gpio_a 16>, <&gpio_a 17>;
|
||||
revisions = <19>, <5>;
|
||||
names = "rev_a", "foo";
|
||||
};
|
||||
|
||||
some_regmapped-bus {
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
|
|
46
cmd/gpt.c
46
cmd/gpt.c
|
@ -350,17 +350,46 @@ static int get_gpt_info(struct blk_desc *dev_desc)
|
|||
}
|
||||
|
||||
/* a wrapper to test get_gpt_info */
|
||||
static int do_get_gpt_info(struct blk_desc *dev_desc)
|
||||
static int do_get_gpt_info(struct blk_desc *dev_desc, char * const namestr)
|
||||
{
|
||||
int ret;
|
||||
int numparts;
|
||||
|
||||
ret = get_gpt_info(dev_desc);
|
||||
if (ret > 0) {
|
||||
print_gpt_info();
|
||||
numparts = get_gpt_info(dev_desc);
|
||||
|
||||
if (numparts > 0) {
|
||||
if (namestr) {
|
||||
char disk_guid[UUID_STR_LEN + 1];
|
||||
char *partitions_list;
|
||||
int partlistlen;
|
||||
int ret = -1;
|
||||
|
||||
ret = get_disk_guid(dev_desc, disk_guid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
partlistlen = calc_parts_list_len(numparts);
|
||||
partitions_list = malloc(partlistlen);
|
||||
if (!partitions_list) {
|
||||
del_gpt_info();
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(partitions_list, '\0', partlistlen);
|
||||
|
||||
ret = create_gpt_partitions_list(numparts, disk_guid,
|
||||
partitions_list);
|
||||
if (ret < 0)
|
||||
printf("Error: Could not create partition list string!\n");
|
||||
else
|
||||
env_set(namestr, partitions_list);
|
||||
|
||||
free(partitions_list);
|
||||
} else {
|
||||
print_gpt_info();
|
||||
}
|
||||
del_gpt_info();
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
return numparts;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -982,7 +1011,7 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
|||
ret = do_disk_guid(blk_dev_desc, argv[4]);
|
||||
#ifdef CONFIG_CMD_GPT_RENAME
|
||||
} else if (strcmp(argv[1], "read") == 0) {
|
||||
ret = do_get_gpt_info(blk_dev_desc);
|
||||
ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
|
||||
} else if ((strcmp(argv[1], "swap") == 0) ||
|
||||
(strcmp(argv[1], "rename") == 0)) {
|
||||
ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
|
||||
|
@ -1028,8 +1057,9 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
|
|||
" gpt guid mmc 0 varname\n"
|
||||
#ifdef CONFIG_CMD_GPT_RENAME
|
||||
"gpt partition renaming commands:\n"
|
||||
" gpt read <interface> <dev>\n"
|
||||
" gpt read <interface> <dev> [<varname>]\n"
|
||||
" - read GPT into a data structure for manipulation\n"
|
||||
" - read GPT partitions into environment variable\n"
|
||||
" gpt swap <interface> <dev> <name1> <name2>\n"
|
||||
" - change all partitions named name1 to name2\n"
|
||||
" and vice-versa\n"
|
||||
|
|
|
@ -459,6 +459,8 @@ static int initr_env(void)
|
|||
else
|
||||
env_set_default(NULL, 0);
|
||||
|
||||
env_import_fdt();
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF_CONTROL))
|
||||
env_set_hex("fdtcontroladdr",
|
||||
(unsigned long)map_to_sysmem(gd->fdt_blob));
|
||||
|
|
|
@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* board_fdt_chosen_bootargs - boards may override this function to use
|
||||
* alternative kernel command line arguments
|
||||
*/
|
||||
__weak char *board_fdt_chosen_bootargs(void)
|
||||
{
|
||||
return env_get("bootargs");
|
||||
}
|
||||
|
||||
int fdt_chosen(void *fdt)
|
||||
{
|
||||
int nodeoffset;
|
||||
|
@ -286,7 +295,8 @@ int fdt_chosen(void *fdt)
|
|||
if (nodeoffset < 0)
|
||||
return nodeoffset;
|
||||
|
||||
str = env_get("bootargs");
|
||||
str = board_fdt_chosen_bootargs();
|
||||
|
||||
if (str) {
|
||||
err = fdt_setprop(fdt, nodeoffset, "bootargs", str,
|
||||
strlen(str) + 1);
|
||||
|
|
|
@ -110,6 +110,10 @@ static int spl_fit_get_image_name(const struct spl_fit_info *ctx,
|
|||
* no string in the property for this index. Check if the
|
||||
* sysinfo-level code can supply one.
|
||||
*/
|
||||
rc = sysinfo_detect(sysinfo);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = sysinfo_get_fit_loadable(sysinfo, index - i - 1, type,
|
||||
&str);
|
||||
if (rc && rc != -ENOENT)
|
||||
|
|
|
@ -91,6 +91,7 @@ CONFIG_ENV_IS_NOWHERE=y
|
|||
CONFIG_ENV_IS_IN_EXT4=y
|
||||
CONFIG_ENV_EXT4_INTERFACE="host"
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
|
||||
CONFIG_ENV_IMPORT_FDT=y
|
||||
CONFIG_BOOTP_SEND_HOSTNAME=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_IP_DEFRAG=y
|
||||
|
@ -204,6 +205,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_EARLY=y
|
||||
|
|
|
@ -106,6 +106,7 @@ CONFIG_ENV_IS_NOWHERE=y
|
|||
CONFIG_ENV_IS_IN_EXT4=y
|
||||
CONFIG_ENV_EXT4_INTERFACE="host"
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
|
||||
CONFIG_ENV_IMPORT_FDT=y
|
||||
CONFIG_BOOTP_SEND_HOSTNAME=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_IP_DEFRAG=y
|
||||
|
@ -245,6 +246,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_EARLY=y
|
||||
|
|
|
@ -178,6 +178,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_EARLY=y
|
||||
|
|
|
@ -197,6 +197,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_SPL_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
|
|
|
@ -199,6 +199,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_SPL_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
|
|
|
@ -237,6 +237,23 @@ doc/arch/index.rst:
|
|||
=> gpt swap host 0 name othername
|
||||
[ . . . ]
|
||||
|
||||
Modifying GPT partition layout from U-Boot:
|
||||
===========================================
|
||||
|
||||
The entire GPT partition layout can be exported to an environment
|
||||
variable and then modified enmasse. Users can change the partition
|
||||
numbers, offsets, names and sizes. The resulting variable can used to
|
||||
reformat the device. Here is an example of reading the GPT partitions
|
||||
into a variable and then modifying them:
|
||||
|
||||
U-BOOT> gpt read mmc 0 current_partitions
|
||||
U-BOOT> env edit current_partitions
|
||||
edit: uuid_disk=[...];name=part1,start=0x4000,size=0x4000,uuid=[...];
|
||||
name=part2,start=0xc000,size=0xc000,uuid=[...];[ . . . ]
|
||||
|
||||
U-BOOT> gpt write mmc 0 $current_partitions
|
||||
U-BOOT> gpt verify mmc 0 $current_partitions
|
||||
|
||||
Partition type GUID:
|
||||
====================
|
||||
|
||||
|
|
37
doc/device-tree-bindings/sysinfo/gpio-sysinfo.txt
Normal file
37
doc/device-tree-bindings/sysinfo/gpio-sysinfo.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
GPIO-based Sysinfo device
|
||||
|
||||
This binding describes several GPIOs which specify a board revision. Each GPIO
|
||||
forms a digit in a ternary revision number. This revision is then mapped to a
|
||||
name using the revisions and names properties.
|
||||
|
||||
Each GPIO may be floating, pulled-up, or pulled-down, mapping to digits 2, 1,
|
||||
and 0, respectively. The first GPIO forms the least-significant digit of the
|
||||
revision. For example, consider the property
|
||||
|
||||
gpios = <&gpio 0>, <&gpio 1>, <&gpio 2>;
|
||||
|
||||
If GPIO 0 is pulled-up, GPIO 1 is pulled-down, and GPIO 2 is floating, then the
|
||||
revision would be
|
||||
|
||||
0t201 = 2*9 + 0*3 + 1*3 = 19
|
||||
|
||||
If instead GPIO 0 is floating, GPIO 1 is pulled-up, and GPIO 2 is pulled-down,
|
||||
then the revision would be
|
||||
|
||||
0t012 = 0*9 + 1*3 + 2*1 = 5
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "gpio-sysinfo".
|
||||
- gpios: should be a list of gpios forming the revision number,
|
||||
least-significant-digit first
|
||||
- revisions: a list of known revisions; any revisions not present will have the
|
||||
name "unknown"
|
||||
- names: the name of each revision in revisions
|
||||
|
||||
Example:
|
||||
sysinfo {
|
||||
compatible = "gpio-sysinfo";
|
||||
gpios = <&gpio_a 15>, <&gpio_a 16>, <&gpio_a 17>;
|
||||
revisions = <19>, <5>;
|
||||
names = "rev_a", "foo";
|
||||
};
|
|
@ -1215,9 +1215,9 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, -1,
|
||||
NULL);
|
||||
if (ret) {
|
||||
ret = dev_count_phandle_with_args(dev, list_name, "#gpio-cells",
|
||||
-ENOENT);
|
||||
if (ret < 0) {
|
||||
debug("%s: Node '%s', property '%s', GPIO count failed: %d\n",
|
||||
__func__, dev->name, list_name, ret);
|
||||
}
|
||||
|
|
|
@ -30,4 +30,12 @@ config SYSINFO_SMBIOS
|
|||
one which provides a way to specify this SMBIOS information in the
|
||||
devicetree, without needing any board-specific functionality.
|
||||
|
||||
config SYSINFO_GPIO
|
||||
bool "Enable gpio sysinfo driver"
|
||||
help
|
||||
Support querying gpios to determine board revision. This uses gpios to
|
||||
form a ternary number (when they are pulled-up, -down, or floating).
|
||||
This ternary number is then mapped to a board revision name using
|
||||
device tree properties.
|
||||
|
||||
endif
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
obj-y += sysinfo-uclass.o
|
||||
obj-$(CONFIG_SYSINFO_GAZERBEAM) += gazerbeam.o
|
||||
obj-$(CONFIG_SYSINFO_GPIO) += gpio.o
|
||||
obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o
|
||||
obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sysinfo.h>
|
||||
|
||||
enum {
|
||||
BOARD_MULTICHANNEL,
|
||||
BOARD_VARIANT,
|
||||
BOARD_HWVERSION,
|
||||
BOARD_HWVERSION = SYSINFO_ID_BOARD_MODEL,
|
||||
BOARD_MULTICHANNEL = SYSINFO_ID_USER,
|
||||
BOARD_VARIANT
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
141
drivers/sysinfo/gpio.c
Normal file
141
drivers/sysinfo/gpio.c
Normal file
|
@ -0,0 +1,141 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Sean Anderson <sean.anderson@seco.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <sysinfo.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
/**
|
||||
* struct sysinfo_gpio_priv - GPIO sysinfo private data
|
||||
* @gpios: List of GPIOs used to detect the revision
|
||||
* @gpio_num: The number of GPIOs in @gpios
|
||||
* @revision: The revision as detected from the GPIOs.
|
||||
*/
|
||||
struct sysinfo_gpio_priv {
|
||||
struct gpio_desc *gpios;
|
||||
int gpio_num, revision;
|
||||
};
|
||||
|
||||
static int sysinfo_gpio_detect(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
ret = dm_gpio_get_values_as_int_base3(priv->gpios, priv->gpio_num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->revision = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sysinfo_gpio_get_int(struct udevice *dev, int id, int *val)
|
||||
{
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
switch (id) {
|
||||
case SYSINFO_ID_BOARD_MODEL:
|
||||
*val = priv->revision;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
static int sysinfo_gpio_get_str(struct udevice *dev, int id, size_t size, char *val)
|
||||
{
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
switch (id) {
|
||||
case SYSINFO_ID_BOARD_MODEL: {
|
||||
const char *name = NULL;
|
||||
int i, ret;
|
||||
u32 revision;
|
||||
|
||||
for (i = 0; i < priv->gpio_num; i++) {
|
||||
ret = dev_read_u32_index(dev, "revisions", i,
|
||||
&revision);
|
||||
if (ret) {
|
||||
if (ret != -EOVERFLOW)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
if (revision == priv->revision) {
|
||||
ret = dev_read_string_index(dev, "names", i,
|
||||
&name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!name)
|
||||
name = "unknown";
|
||||
|
||||
strncpy(val, name, size);
|
||||
val[size - 1] = '\0';
|
||||
return 0;
|
||||
} default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
static const struct sysinfo_ops sysinfo_gpio_ops = {
|
||||
.detect = sysinfo_gpio_detect,
|
||||
.get_int = sysinfo_gpio_get_int,
|
||||
.get_str = sysinfo_gpio_get_str,
|
||||
};
|
||||
|
||||
static int sysinfo_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->gpio_num = gpio_get_list_count(dev, "gpios");
|
||||
if (priv->gpio_num < 0) {
|
||||
dev_err(dev, "could not get gpios length (err = %d)\n",
|
||||
priv->gpio_num);
|
||||
return priv->gpio_num;
|
||||
}
|
||||
|
||||
priv->gpios = calloc(priv->gpio_num, sizeof(*priv->gpios));
|
||||
if (!priv->gpios) {
|
||||
dev_err(dev, "could not allocate memory for %d gpios\n",
|
||||
priv->gpio_num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = gpio_request_list_by_name(dev, "gpios", priv->gpios,
|
||||
priv->gpio_num, GPIOD_IS_IN);
|
||||
if (ret != priv->gpio_num) {
|
||||
dev_err(dev, "could not get gpios (err = %d)\n",
|
||||
priv->gpio_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!dev_read_bool(dev, "revisions") || !dev_read_bool(dev, "names")) {
|
||||
dev_err(dev, "revisions or names properties missing\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id sysinfo_gpio_ids[] = {
|
||||
{ .compatible = "gpio-sysinfo" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sysinfo_gpio) = {
|
||||
.name = "sysinfo_gpio",
|
||||
.id = UCLASS_SYSINFO,
|
||||
.of_match = sysinfo_gpio_ids,
|
||||
.ops = &sysinfo_gpio_ops,
|
||||
.priv_auto = sizeof(struct sysinfo_gpio_priv),
|
||||
.probe = sysinfo_gpio_probe,
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
enum {
|
||||
BOOL_CALLED_DETECT,
|
||||
BOOL_CALLED_DETECT = SYSINFO_ID_USER,
|
||||
INT_TEST1,
|
||||
INT_TEST2,
|
||||
STR_VACATIONSPOT,
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#include <dm.h>
|
||||
#include <sysinfo.h>
|
||||
|
||||
struct sysinfo_priv {
|
||||
bool detected;
|
||||
};
|
||||
|
||||
int sysinfo_get(struct udevice **devp)
|
||||
{
|
||||
return uclass_first_device_err(UCLASS_SYSINFO, devp);
|
||||
|
@ -15,19 +19,29 @@ int sysinfo_get(struct udevice **devp)
|
|||
|
||||
int sysinfo_detect(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!ops->detect)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->detect(dev);
|
||||
ret = ops->detect(dev);
|
||||
if (!ret)
|
||||
priv->detected = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sysinfo_get_fit_loadable(struct udevice *dev, int index, const char *type,
|
||||
const char **strp)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_fit_loadable)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -36,8 +50,12 @@ int sysinfo_get_fit_loadable(struct udevice *dev, int index, const char *type,
|
|||
|
||||
int sysinfo_get_bool(struct udevice *dev, int id, bool *val)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_bool)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -46,8 +64,12 @@ int sysinfo_get_bool(struct udevice *dev, int id, bool *val)
|
|||
|
||||
int sysinfo_get_int(struct udevice *dev, int id, int *val)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_int)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -56,8 +78,12 @@ int sysinfo_get_int(struct udevice *dev, int id, int *val)
|
|||
|
||||
int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_str)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -68,4 +94,5 @@ UCLASS_DRIVER(sysinfo) = {
|
|||
.id = UCLASS_SYSINFO,
|
||||
.name = "sysinfo",
|
||||
.post_bind = dm_scan_fdt_dev,
|
||||
.per_device_auto = sizeof(bool),
|
||||
};
|
||||
|
|
18
env/Kconfig
vendored
18
env/Kconfig
vendored
|
@ -670,6 +670,24 @@ config DELAY_ENVIRONMENT
|
|||
later by U-Boot code. With CONFIG_OF_CONTROL this is instead
|
||||
controlled by the value of /config/load-environment.
|
||||
|
||||
config ENV_IMPORT_FDT
|
||||
bool "Amend environment by FDT properties"
|
||||
depends on OF_CONTROL
|
||||
help
|
||||
If selected, after the environment has been loaded from its
|
||||
persistent location, the "env_fdt_path" variable is looked
|
||||
up and used as a path to a node in the control DTB. The
|
||||
property/value pairs in that node is then used to update the
|
||||
run-time environment. This can be useful to use the same
|
||||
U-Boot binary with different board variants.
|
||||
|
||||
config ENV_FDT_PATH
|
||||
string "Default value for env_fdt_path variable"
|
||||
depends on ENV_IMPORT_FDT
|
||||
default "/config/environment"
|
||||
help
|
||||
The initial value of the env_fdt_path variable.
|
||||
|
||||
config ENV_APPEND
|
||||
bool "Always append the environment with new data"
|
||||
default n
|
||||
|
|
30
env/common.c
vendored
30
env/common.c
vendored
|
@ -20,6 +20,7 @@
|
|||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <u-boot/crc.h>
|
||||
#include <dm/ofnode.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -334,3 +335,32 @@ int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf,
|
|||
return found;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENV_IMPORT_FDT
|
||||
void env_import_fdt(void)
|
||||
{
|
||||
const char *path;
|
||||
struct ofprop prop;
|
||||
ofnode node;
|
||||
int res;
|
||||
|
||||
path = env_get("env_fdt_path");
|
||||
if (!path || !path[0])
|
||||
return;
|
||||
|
||||
node = ofnode_path(path);
|
||||
if (!ofnode_valid(node)) {
|
||||
printf("Warning: device tree node '%s' not found\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
for (res = ofnode_get_first_property(node, &prop);
|
||||
!res;
|
||||
res = ofnode_get_next_property(&prop)) {
|
||||
const char *name, *val;
|
||||
|
||||
val = ofnode_get_property_by_prop(&prop, &name, NULL);
|
||||
env_set(name, val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -375,4 +375,19 @@ int env_get_char(int index);
|
|||
* This is used for those unfortunate archs with crappy toolchains
|
||||
*/
|
||||
void env_reloc(void);
|
||||
|
||||
|
||||
/**
|
||||
* env_import_fdt() - Import environment values from device tree blob
|
||||
*
|
||||
* This uses the value of the environment variable "env_fdt_path" as a
|
||||
* path to an fdt node, whose property/value pairs are added to the
|
||||
* environment.
|
||||
*/
|
||||
#ifdef CONFIG_ENV_IMPORT_FDT
|
||||
void env_import_fdt(void);
|
||||
#else
|
||||
static inline void env_import_fdt(void) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -103,6 +103,9 @@ const uchar default_environment[] = {
|
|||
#ifdef CONFIG_SYS_SOC
|
||||
"soc=" CONFIG_SYS_SOC "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ENV_IMPORT_FDT
|
||||
"env_fdt_path=" CONFIG_ENV_FDT_PATH "\0"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_BOOTCOUNT_BOOTLIMIT) && (CONFIG_BOOTCOUNT_BOOTLIMIT > 0)
|
||||
"bootlimit=" __stringify(CONFIG_BOOTCOUNT_BOOTLIMIT)"\0"
|
||||
|
|
|
@ -185,6 +185,16 @@ int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name);
|
|||
*/
|
||||
int ft_board_setup(void *blob, struct bd_info *bd);
|
||||
|
||||
/**
|
||||
* board_fdt_chosen_bootargs() - Arbitrarily amend fdt kernel command line
|
||||
*
|
||||
* This is used for late modification of kernel command line arguments just
|
||||
* before they are added into the /chosen node in flat device tree.
|
||||
*
|
||||
* @return: pointer to kernel command line arguments in memory
|
||||
*/
|
||||
char *board_fdt_chosen_bootargs(void);
|
||||
|
||||
/*
|
||||
* The keystone2 SOC requires all 32 bit aliased addresses to be converted
|
||||
* to their 36 physical format. This has to happen after all fdt nodes
|
||||
|
|
|
@ -60,7 +60,8 @@ struct sysinfo_ops {
|
|||
* This operation might take a long time (e.g. read from EEPROM,
|
||||
* check the presence of a device on a bus etc.), hence this is not
|
||||
* done in the probe() method, but later during operation in this
|
||||
* dedicated method.
|
||||
* dedicated method. This method will be called before any other
|
||||
* methods.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
*/
|
||||
|
@ -104,7 +105,7 @@ struct sysinfo_ops {
|
|||
* get_fit_loadable - Get the name of an image to load from FIT
|
||||
* This function can be used to provide the image names based on runtime
|
||||
* detection. A classic use-case would when DTBOs are used to describe
|
||||
* additionnal daughter cards.
|
||||
* additional daughter cards.
|
||||
*
|
||||
* @dev: The sysinfo instance to gather the data.
|
||||
* @index: Index of the image. Starts at 0 and gets incremented
|
||||
|
@ -127,6 +128,9 @@ struct sysinfo_ops {
|
|||
*
|
||||
* @dev: The device containing the information
|
||||
*
|
||||
* This function must be called before any other accessor function for this
|
||||
* device.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
*/
|
||||
int sysinfo_detect(struct udevice *dev);
|
||||
|
@ -138,7 +142,8 @@ int sysinfo_detect(struct udevice *dev);
|
|||
* @id: A unique identifier for the bool value to be read.
|
||||
* @val: Pointer to a buffer that receives the value read.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get_bool(struct udevice *dev, int id, bool *val);
|
||||
|
||||
|
@ -149,7 +154,8 @@ int sysinfo_get_bool(struct udevice *dev, int id, bool *val);
|
|||
* @id: A unique identifier for the int value to be read.
|
||||
* @val: Pointer to a buffer that receives the value read.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get_int(struct udevice *dev, int id, int *val);
|
||||
|
||||
|
@ -161,7 +167,8 @@ int sysinfo_get_int(struct udevice *dev, int id, int *val);
|
|||
* @size: The size of the buffer to receive the string data.
|
||||
* @val: Pointer to a buffer that receives the value read.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val);
|
||||
|
||||
|
@ -173,7 +180,8 @@ int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val);
|
|||
* function that returns the unique device. This is especially useful for use
|
||||
* in sysinfo files.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get(struct udevice **devp);
|
||||
|
||||
|
@ -181,7 +189,7 @@ int sysinfo_get(struct udevice **devp);
|
|||
* sysinfo_get_fit_loadable - Get the name of an image to load from FIT
|
||||
* This function can be used to provide the image names based on runtime
|
||||
* detection. A classic use-case would when DTBOs are used to describe
|
||||
* additionnal daughter cards.
|
||||
* additional daughter cards.
|
||||
*
|
||||
* @dev: The sysinfo instance to gather the data.
|
||||
* @index: Index of the image. Starts at 0 and gets incremented
|
||||
|
@ -190,8 +198,8 @@ int sysinfo_get(struct udevice **devp);
|
|||
* @strp: A pointer to string. Untouched if the function fails
|
||||
*
|
||||
*
|
||||
* Return: 0 if OK, -ENOENT if no loadable is available else -ve on
|
||||
* error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), -ENOENT if no
|
||||
* loadable is available else -ve on error.
|
||||
*/
|
||||
int sysinfo_get_fit_loadable(struct udevice *dev, int index, const char *type,
|
||||
const char **strp);
|
||||
|
|
|
@ -96,6 +96,7 @@ obj-$(CONFIG_SPMI) += spmi.o
|
|||
obj-y += syscon.o
|
||||
obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
|
||||
obj-$(CONFIG_SYSINFO) += sysinfo.o
|
||||
obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
|
||||
obj-$(CONFIG_TEE) += tee.o
|
||||
obj-$(CONFIG_TIMER) += timer.o
|
||||
obj-$(CONFIG_DM_USB) += usb.o
|
||||
|
|
69
test/dm/sysinfo-gpio.c
Normal file
69
test/dm/sysinfo-gpio.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Sean Anderson <sean.anderson@seco.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <sysinfo.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/test.h>
|
||||
#include <test/test.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
static int dm_test_sysinfo_gpio(struct unit_test_state *uts)
|
||||
{
|
||||
char buf[64];
|
||||
int val;
|
||||
struct udevice *sysinfo, *gpio;
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_SYSINFO, "sysinfo-gpio",
|
||||
&sysinfo));
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_GPIO, "base-gpios", &gpio));
|
||||
|
||||
/*
|
||||
* Set up pins: pull-up (1), pull-down (0) and floating (2). This should
|
||||
* result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19
|
||||
*/
|
||||
sandbox_gpio_set_flags(gpio, 15, GPIOD_EXT_PULL_UP);
|
||||
sandbox_gpio_set_flags(gpio, 16, GPIOD_EXT_PULL_DOWN);
|
||||
sandbox_gpio_set_flags(gpio, 17, 0);
|
||||
ut_assertok(sysinfo_detect(sysinfo));
|
||||
ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val));
|
||||
ut_asserteq(19, val);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf),
|
||||
buf));
|
||||
ut_asserteq_str("rev_a", buf);
|
||||
|
||||
/*
|
||||
* Set up pins: floating (2), pull-up (1) and pull-down (0). This should
|
||||
* result in digits 0 1 2, i.e. 1 * 3 + 2 = 5
|
||||
*/
|
||||
sandbox_gpio_set_flags(gpio, 15, 0);
|
||||
sandbox_gpio_set_flags(gpio, 16, GPIOD_EXT_PULL_UP);
|
||||
sandbox_gpio_set_flags(gpio, 17, GPIOD_EXT_PULL_DOWN);
|
||||
ut_assertok(sysinfo_detect(sysinfo));
|
||||
ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val));
|
||||
ut_asserteq(5, val);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf),
|
||||
buf));
|
||||
ut_asserteq_str("foo", buf);
|
||||
|
||||
/*
|
||||
* Set up pins: floating (2), pull-up (1) and pull-down (0). This should
|
||||
* result in digits 1 2 0, i.e. 1 * 9 + 2 * 3 = 15
|
||||
*/
|
||||
sandbox_gpio_set_flags(gpio, 15, GPIOD_EXT_PULL_DOWN);
|
||||
sandbox_gpio_set_flags(gpio, 16, 0);
|
||||
sandbox_gpio_set_flags(gpio, 17, GPIOD_EXT_PULL_UP);
|
||||
ut_assertok(sysinfo_detect(sysinfo));
|
||||
ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val));
|
||||
ut_asserteq(15, val);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf),
|
||||
buf));
|
||||
ut_asserteq_str("unknown", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_sysinfo_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
|
|
@ -17,40 +17,45 @@
|
|||
static int dm_test_sysinfo(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *sysinfo;
|
||||
bool called_detect;
|
||||
bool called_detect = false;
|
||||
char str[64];
|
||||
int i;
|
||||
|
||||
ut_assertok(sysinfo_get(&sysinfo));
|
||||
ut_assert(sysinfo);
|
||||
|
||||
sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT, &called_detect);
|
||||
ut_asserteq(-EPERM, sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT,
|
||||
&called_detect));
|
||||
ut_assert(!called_detect);
|
||||
|
||||
sysinfo_detect(sysinfo);
|
||||
|
||||
sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT, &called_detect);
|
||||
ut_assertok(sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT,
|
||||
&called_detect));
|
||||
ut_assert(called_detect);
|
||||
|
||||
sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), str);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str),
|
||||
str));
|
||||
ut_assertok(strcmp(str, "R'lyeh"));
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST1, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST1, &i));
|
||||
ut_asserteq(0, i);
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST2, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST2, &i));
|
||||
ut_asserteq(100, i);
|
||||
|
||||
sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), str);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str),
|
||||
str));
|
||||
ut_assertok(strcmp(str, "Carcosa"));
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST1, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST1, &i));
|
||||
ut_asserteq(1, i);
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST2, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST2, &i));
|
||||
ut_asserteq(99, i);
|
||||
|
||||
sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), str);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str),
|
||||
str));
|
||||
ut_assertok(strcmp(str, "Yuggoth"));
|
||||
|
||||
return 0;
|
||||
|
|
1
test/env/Makefile
vendored
1
test/env/Makefile
vendored
|
@ -5,3 +5,4 @@
|
|||
obj-y += cmd_ut_env.o
|
||||
obj-y += attr.o
|
||||
obj-y += hashtable.o
|
||||
obj-$(CONFIG_ENV_IMPORT_FDT) += fdt.o
|
||||
|
|
20
test/env/fdt.c
vendored
Normal file
20
test/env/fdt.c
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env_attr.h>
|
||||
#include <test/env.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
static int env_test_fdt_import(struct unit_test_state *uts)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = env_get("from_fdt");
|
||||
ut_assertnonnull(val);
|
||||
ut_asserteq_str("yes", val);
|
||||
|
||||
val = env_get("fdt_env_path");
|
||||
ut_assertnull(val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
ENV_TEST(env_test_fdt_import, 0);
|
Loading…
Reference in a new issue