improvements with dev_read_addr_..._ptr()
scan all entries in multi-device boot_targets
EFI empty-capsule support
This commit is contained in:
Tom Rini
2023-10-14 10:50:20 -04:00
42 changed files with 837 additions and 164 deletions
+8 -8
View File
@@ -321,7 +321,7 @@ exit:
static void *k3_sysfw_get_spi_addr(void)
{
struct udevice *dev;
fdt_addr_t addr;
void *addr;
int ret;
unsigned int sf_bus = spl_spi_boot_bus();
@@ -329,11 +329,11 @@ static void *k3_sysfw_get_spi_addr(void)
if (ret)
return NULL;
addr = dev_read_addr_index(dev, 1);
if (addr == FDT_ADDR_T_NONE)
addr = dev_read_addr_index_ptr(dev, 1);
if (!addr)
return NULL;
return (void *)(addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS);
return addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS;
}
static void k3_sysfw_spi_copy(u32 *dst, u32 *src, size_t len)
@@ -349,18 +349,18 @@ static void k3_sysfw_spi_copy(u32 *dst, u32 *src, size_t len)
static void *get_sysfw_hf_addr(void)
{
struct udevice *dev;
fdt_addr_t addr;
void *addr;
int ret;
ret = uclass_find_first_device(UCLASS_MTD, &dev);
if (ret)
return NULL;
addr = dev_read_addr_index(dev, 1);
if (addr == FDT_ADDR_T_NONE)
addr = dev_read_addr_index_ptr(dev, 1);
if (!addr)
return NULL;
return (void *)(addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS);
return addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS;
}
#endif
+3
View File
@@ -126,6 +126,9 @@ void spl_board_init(void)
{
struct sandbox_state *state = state_get_current();
if (!CONFIG_IS_ENABLED(UNIT_TEST))
return;
if (state->run_unittests) {
struct unit_test *tests = UNIT_TEST_ALL_START();
const int count = UNIT_TEST_ALL_COUNT();
+2 -1
View File
@@ -469,10 +469,11 @@ int bootdev_find_by_label(const char *label, struct udevice **devp,
* if no sequence number was provided, we must scan all
* bootdevs for this media uclass
*/
if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && seq == -1)
if (seq == -1)
method_flags |= BOOTFLOW_METHF_SINGLE_UCLASS;
if (method_flagsp)
*method_flagsp = method_flags;
log_debug("method flags %x\n", method_flags);
return 0;
}
log_debug("- no device in %s\n", media->name);
+19 -2
View File
@@ -260,8 +260,25 @@ static int iter_incr(struct bootflow_iter *iter)
} else {
log_debug("labels %p\n", iter->labels);
if (iter->labels) {
ret = bootdev_next_label(iter, &dev,
&method_flags);
/*
* when the label is "mmc" we want to scan all
* mmc bootdevs, not just the first. See
* bootdev_find_by_label() where this flag is
* set up
*/
if (iter->method_flags & BOOTFLOW_METHF_SINGLE_UCLASS) {
uclass_next_device(&dev);
log_debug("looking for next device %s: %s\n",
iter->dev->name,
dev ? dev->name : "<none>");
} else {
dev = NULL;
}
if (!dev) {
log_debug("looking at next label\n");
ret = bootdev_next_label(iter, &dev,
&method_flags);
}
} else {
ret = bootdev_next_prio(iter, &dev);
method_flags = 0;
+17
View File
@@ -385,6 +385,23 @@ capsules. Refer :ref:`etype_efi_capsule` for documentation about the
efi-capsule binman entry type, which describes all the properties that
can be specified.
Dumping capsule headers
***********************
The mkeficapsule tool also provides a command-line option to dump the
contents of the capsule header. This is a useful functionality when
trying to understand the structure of a capsule and is also used in
capsule verification. This feature is used in testing the capsule
contents in binman's test framework.
To check the contents of the capsule headers, the mkeficapsule command
can be used.
.. code-block:: console
$ mkeficapsule --dump-capsule \
<capsule_file_name>
Performing the update
*********************
+23 -2
View File
@@ -145,7 +145,7 @@ fdt_addr_t devfdt_get_addr_name(const struct udevice *dev, const char *name)
index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
"reg-names", name);
if (index < 0)
return index;
return FDT_ADDR_T_NONE;
return devfdt_get_addr_index(dev, index);
#else
@@ -153,6 +153,16 @@ fdt_addr_t devfdt_get_addr_name(const struct udevice *dev, const char *name)
#endif
}
void *devfdt_get_addr_name_ptr(const struct udevice *dev, const char *name)
{
fdt_addr_t addr = devfdt_get_addr_name(dev, name);
if (addr == FDT_ADDR_T_NONE)
return NULL;
return map_sysmem(addr, 0);
}
fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev,
const char *name, fdt_size_t *size)
{
@@ -162,7 +172,7 @@ fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev,
index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
"reg-names", name);
if (index < 0)
return index;
return FDT_ADDR_T_NONE;
return devfdt_get_addr_size_index(dev, index, size);
#else
@@ -170,6 +180,17 @@ fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev,
#endif
}
void *devfdt_get_addr_size_name_ptr(const struct udevice *dev,
const char *name, fdt_size_t *size)
{
fdt_addr_t addr = devfdt_get_addr_size_name(dev, name, size);
if (addr == FDT_ADDR_T_NONE)
return NULL;
return map_sysmem(addr, 0);
}
fdt_addr_t devfdt_get_addr(const struct udevice *dev)
{
return devfdt_get_addr_index(dev, 0);
+21
View File
@@ -181,6 +181,16 @@ fdt_addr_t dev_read_addr_name(const struct udevice *dev, const char *name)
return dev_read_addr_index(dev, index);
}
void *dev_read_addr_name_ptr(const struct udevice *dev, const char *name)
{
fdt_addr_t addr = dev_read_addr_name(dev, name);
if (addr == FDT_ADDR_T_NONE)
return NULL;
return map_sysmem(addr, 0);
}
fdt_addr_t dev_read_addr_size_name(const struct udevice *dev, const char *name,
fdt_size_t *size)
{
@@ -192,6 +202,17 @@ fdt_addr_t dev_read_addr_size_name(const struct udevice *dev, const char *name,
return dev_read_addr_size_index(dev, index, size);
}
void *dev_read_addr_size_name_ptr(const struct udevice *dev, const char *name,
fdt_size_t *size)
{
fdt_addr_t addr = dev_read_addr_size_name(dev, name, size);
if (addr == FDT_ADDR_T_NONE)
return NULL;
return map_sysmem(addr, 0);
}
void *dev_remap_addr_name(const struct udevice *dev, const char *name)
{
fdt_addr_t addr = dev_read_addr_name(dev, name);
+2 -3
View File
@@ -1287,7 +1287,7 @@ static int udma_get_mmrs(struct udevice *dev)
u32 cap2, cap3, cap4;
int i;
ud->mmrs[MMR_GCFG] = (uint32_t *)devfdt_get_addr_name(dev, mmr_names[MMR_GCFG]);
ud->mmrs[MMR_GCFG] = dev_read_addr_name_ptr(dev, mmr_names[MMR_GCFG]);
if (!ud->mmrs[MMR_GCFG])
return -EINVAL;
@@ -1325,8 +1325,7 @@ static int udma_get_mmrs(struct udevice *dev)
if (i == MMR_RCHANRT && ud->rchan_cnt == 0)
continue;
ud->mmrs[i] = (uint32_t *)devfdt_get_addr_name(dev,
mmr_names[i]);
ud->mmrs[i] = dev_read_addr_name_ptr(dev, mmr_names[i]);
if (!ud->mmrs[i])
return -EINVAL;
}
+2 -2
View File
@@ -176,8 +176,8 @@ static int tegra186_gpio_bind(struct udevice *parent)
if (parent_plat)
return 0;
regs = (uint32_t *)devfdt_get_addr_name(parent, "gpio");
if (regs == (uint32_t *)FDT_ADDR_T_NONE)
regs = dev_read_addr_name_ptr(parent, "gpio");
if (!regs)
return -EINVAL;
for (port = 0; port < ctlr_data->port_count; port++) {
+9 -9
View File
@@ -84,9 +84,9 @@ struct k3_sec_proxy_mbox {
struct mbox_chan chan;
struct k3_sec_proxy_desc *desc;
struct k3_sec_proxy_thread *chans;
phys_addr_t target_data;
phys_addr_t scfg;
phys_addr_t rt;
void *target_data;
void *scfg;
void *rt;
};
static inline u32 sp_readl(void __iomem *addr, unsigned int offset)
@@ -319,20 +319,20 @@ static int k3_sec_proxy_of_to_priv(struct udevice *dev,
return -ENODEV;
}
spm->target_data = devfdt_get_addr_name(dev, "target_data");
if (spm->target_data == FDT_ADDR_T_NONE) {
spm->target_data = dev_read_addr_name_ptr(dev, "target_data");
if (!spm->target_data) {
dev_err(dev, "No reg property for target data base\n");
return -EINVAL;
}
spm->scfg = devfdt_get_addr_name(dev, "scfg");
if (spm->scfg == FDT_ADDR_T_NONE) {
spm->scfg = dev_read_addr_name_ptr(dev, "scfg");
if (!spm->scfg) {
dev_err(dev, "No reg property for Secure Cfg base\n");
return -EINVAL;
}
spm->rt = devfdt_get_addr_name(dev, "rt");
if (spm->rt == FDT_ADDR_T_NONE) {
spm->rt = dev_read_addr_name_ptr(dev, "rt");
if (!spm->rt) {
dev_err(dev, "No reg property for Real Time Cfg base\n");
return -EINVAL;
}
+6 -6
View File
@@ -472,9 +472,9 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
if (!data->cfg)
return -EINVAL;
data->base = (void __iomem *)devfdt_get_addr_name(dev, "phy_ctrl");
if (IS_ERR(data->base))
return PTR_ERR(data->base);
data->base = (void __iomem *)dev_read_addr_name_ptr(dev, "phy_ctrl");
if (!data->base)
return -EINVAL;
device_get_supply_regulator(dev, "usb0_vbus_power-supply",
&data->vbus_power_supply);
@@ -555,9 +555,9 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
if (i || data->cfg->phy0_dual_route) {
snprintf(name, sizeof(name), "pmu%d", i);
phy->pmu = (void __iomem *)devfdt_get_addr_name(dev, name);
if (IS_ERR(phy->pmu))
return PTR_ERR(phy->pmu);
phy->pmu = (void __iomem *)dev_read_addr_name_ptr(dev, name);
if (!phy->pmu)
return -EINVAL;
}
phy->id = i;
+2 -2
View File
@@ -143,8 +143,8 @@ static int sr_pcie_phy_probe(struct udevice *dev)
core->dev = dev;
core->base = (void __iomem *)devfdt_get_addr_name(dev, "reg_base");
core->cdru = (void __iomem *)devfdt_get_addr_name(dev, "cdru_base");
core->base = (void __iomem *)dev_read_addr_name_ptr(dev, "reg_base");
core->cdru = (void __iomem *)dev_read_addr_name_ptr(dev, "cdru_base");
debug("ip base %p\n", core->base);
debug("cdru base %p\n", core->cdru);
+19 -15
View File
@@ -5,6 +5,7 @@
*/
#include <common.h>
#include <mapmem.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
@@ -24,7 +25,7 @@
* @bits_per_mux: true if one register controls more than one pin
*/
struct single_pdata {
fdt_addr_t base;
void *base;
int offset;
u32 mask;
u32 width;
@@ -97,7 +98,7 @@ struct single_fdt_bits_cfg {
#if (!IS_ENABLED(CONFIG_SANDBOX))
static unsigned int single_read(struct udevice *dev, fdt_addr_t reg)
static unsigned int single_read(struct udevice *dev, void *reg)
{
struct single_pdata *pdata = dev_get_plat(dev);
@@ -113,7 +114,7 @@ static unsigned int single_read(struct udevice *dev, fdt_addr_t reg)
return readb(reg);
}
static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg)
static void single_write(struct udevice *dev, unsigned int val, void *reg)
{
struct single_pdata *pdata = dev_get_plat(dev);
@@ -131,18 +132,18 @@ static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg)
#else /* CONFIG_SANDBOX */
static unsigned int single_read(struct udevice *dev, fdt_addr_t reg)
static unsigned int single_read(struct udevice *dev, void *reg)
{
struct single_priv *priv = dev_get_priv(dev);
return priv->sandbox_regs[reg];
return priv->sandbox_regs[map_to_sysmem(reg)];
}
static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg)
static void single_write(struct udevice *dev, unsigned int val, void *reg)
{
struct single_priv *priv = dev_get_priv(dev);
priv->sandbox_regs[reg] = val;
priv->sandbox_regs[map_to_sysmem(reg)] = val;
}
#endif /* CONFIG_SANDBOX */
@@ -214,7 +215,8 @@ static int single_get_pin_muxing(struct udevice *dev, unsigned int pin,
{
struct single_pdata *pdata = dev_get_plat(dev);
struct single_priv *priv = dev_get_priv(dev);
fdt_addr_t reg;
phys_addr_t phys_reg;
void *reg;
const char *fname;
unsigned int val;
int offset, pin_shift = 0;
@@ -226,13 +228,15 @@ static int single_get_pin_muxing(struct udevice *dev, unsigned int pin,
reg = pdata->base + offset;
val = single_read(dev, reg);
phys_reg = map_to_sysmem(reg);
if (pdata->bits_per_mux)
pin_shift = pin % (pdata->width / priv->bits_per_pin) *
priv->bits_per_pin;
val &= (pdata->mask << pin_shift);
fname = single_get_pin_function(dev, pin);
snprintf(buf, size, "%pa 0x%08x %s", &reg, val,
snprintf(buf, size, "%pa 0x%08x %s", &phys_reg, val,
fname ? fname : "UNCLAIMED");
return 0;
}
@@ -243,7 +247,7 @@ static int single_request(struct udevice *dev, int pin, int flags)
struct single_pdata *pdata = dev_get_plat(dev);
struct single_gpiofunc_range *frange = NULL;
struct list_head *pos, *tmp;
phys_addr_t reg;
void *reg;
int mux_bytes = 0;
u32 data;
@@ -321,7 +325,7 @@ static int single_configure_pins(struct udevice *dev,
int stride = pdata->args_count + 1;
int n, pin, count = size / sizeof(u32);
struct single_func *func;
phys_addr_t reg;
void *reg;
u32 offset, val, mux;
/* If function mask is null, needn't enable it. */
@@ -379,7 +383,7 @@ static int single_configure_bits(struct udevice *dev,
int n, pin, count = size / sizeof(struct single_fdt_bits_cfg);
int npins_in_reg, pin_num_from_lsb;
struct single_func *func;
phys_addr_t reg;
void *reg;
u32 offset, val, mask, bit_pos, val_pos, mask_pos, submask;
/* If function mask is null, needn't enable it. */
@@ -570,7 +574,7 @@ static int single_probe(struct udevice *dev)
static int single_of_to_plat(struct udevice *dev)
{
fdt_addr_t addr;
void *addr;
fdt_size_t size;
struct single_pdata *pdata = dev_get_plat(dev);
int ret;
@@ -591,8 +595,8 @@ static int single_of_to_plat(struct udevice *dev)
return -EINVAL;
}
addr = dev_read_addr_size_index(dev, 0, &size);
if (addr == FDT_ADDR_T_NONE) {
addr = dev_read_addr_size_index_ptr(dev, 0, &size);
if (!addr) {
dev_err(dev, "failed to get base register address\n");
return -EINVAL;
}
+10 -10
View File
@@ -903,7 +903,7 @@ static int am654_ddrss_power_on(struct am654_ddrss_desc *ddrss)
static int am654_ddrss_ofdata_to_priv(struct udevice *dev)
{
struct am654_ddrss_desc *ddrss = dev_get_priv(dev);
phys_addr_t reg;
void *reg;
int ret;
debug("%s(dev=%p)\n", __func__, dev);
@@ -926,26 +926,26 @@ static int am654_ddrss_ofdata_to_priv(struct udevice *dev)
return ret;
}
reg = devfdt_get_addr_name(dev, "ss");
if (reg == FDT_ADDR_T_NONE) {
reg = dev_read_addr_name_ptr(dev, "ss");
if (!reg) {
dev_err(dev, "No reg property for DDRSS wrapper logic\n");
return -EINVAL;
}
ddrss->ddrss_ss_cfg = (void *)reg;
ddrss->ddrss_ss_cfg = reg;
reg = devfdt_get_addr_name(dev, "ctl");
if (reg == FDT_ADDR_T_NONE) {
reg = dev_read_addr_name_ptr(dev, "ctl");
if (!reg) {
dev_err(dev, "No reg property for Controller region\n");
return -EINVAL;
}
ddrss->ddrss_ctl_cfg = (void *)reg;
ddrss->ddrss_ctl_cfg = reg;
reg = devfdt_get_addr_name(dev, "phy");
if (reg == FDT_ADDR_T_NONE) {
reg = dev_read_addr_name_ptr(dev, "phy");
if (!reg) {
dev_err(dev, "No reg property for PHY region\n");
return -EINVAL;
}
ddrss->ddrss_phy_cfg = (void *)reg;
ddrss->ddrss_phy_cfg = reg;
ret = dev_read_u32_array(dev, "ti,ss-reg",
(u32 *)&ddrss->params.ss_reg,
+10 -13
View File
@@ -331,32 +331,29 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev)
{
struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
struct k3_ddrss_data *ddrss_data = (struct k3_ddrss_data *)dev_get_driver_data(dev);
phys_addr_t reg;
void *reg;
int ret;
debug("%s(dev=%p)\n", __func__, dev);
reg = dev_read_addr_name(dev, "cfg");
if (reg == FDT_ADDR_T_NONE) {
reg = dev_read_addr_name_ptr(dev, "cfg");
if (!reg) {
dev_err(dev, "No reg property for DDRSS wrapper logic\n");
return -EINVAL;
}
ddrss->ddrss_ctl_cfg = (void *)reg;
ddrss->ddrss_ctl_cfg = reg;
reg = dev_read_addr_name(dev, "ctrl_mmr_lp4");
if (reg == FDT_ADDR_T_NONE) {
reg = dev_read_addr_name_ptr(dev, "ctrl_mmr_lp4");
if (!reg) {
dev_err(dev, "No reg property for CTRL MMR\n");
return -EINVAL;
}
ddrss->ddrss_ctrl_mmr = (void *)reg;
ddrss->ddrss_ctrl_mmr = reg;
reg = dev_read_addr_name(dev, "ss_cfg");
if (reg == FDT_ADDR_T_NONE) {
reg = dev_read_addr_name_ptr(dev, "ss_cfg");
if (!reg)
dev_dbg(dev, "No reg property for SS Config region, but this is optional so continuing.\n");
ddrss->ddrss_ss_cfg = NULL;
} else {
ddrss->ddrss_ss_cfg = (void *)reg;
}
ddrss->ddrss_ss_cfg = reg;
ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0);
if (ret) {
+6 -6
View File
@@ -987,10 +987,10 @@ static int k3_nav_ringacc_init(struct udevice *dev, struct k3_nav_ringacc *ringa
if (!base_cfg)
return -EINVAL;
base_rt = (uint32_t *)devfdt_get_addr_name(dev, "rt");
base_rt = dev_read_addr_name_ptr(dev, "rt");
pr_debug("rt %p\n", base_rt);
if (IS_ERR(base_rt))
return PTR_ERR(base_rt);
if (!base_rt)
return -EINVAL;
ringacc->rings = devm_kzalloc(dev,
sizeof(*ringacc->rings) *
@@ -1045,9 +1045,9 @@ struct k3_nav_ringacc *k3_ringacc_dmarings_init(struct udevice *dev,
ringacc->tisci = data->tisci;
ringacc->tisci_dev_id = data->tisci_dev_id;
base_rt = (uint32_t *)devfdt_get_addr_name(dev, "ringrt");
if (IS_ERR(base_rt))
return base_rt;
base_rt = dev_read_addr_name_ptr(dev, "ringrt");
if (!base_rt)
return ERR_PTR(-EINVAL);
ringacc->rings = devm_kzalloc(dev,
sizeof(*ringacc->rings) *
+39 -8
View File
@@ -19,7 +19,7 @@ struct udevice;
*
* @dev: Pointer to a device
*
* Return: addr
* Return: Address, or FDT_ADDR_T_NONE if there is no such property
*/
fdt_addr_t devfdt_get_addr(const struct udevice *dev);
@@ -59,7 +59,7 @@ void *devfdt_remap_addr_index(const struct udevice *dev, int index);
* devfdt_remap_addr_name() - Get the reg property of a device, indexed by
* name, as a memory-mapped I/O pointer
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @index
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
*
* @dev: Pointer to a device
@@ -87,7 +87,7 @@ void *devfdt_map_physmem(const struct udevice *dev, unsigned long size);
* @index: the 'reg' property can hold a list of <addr, size> pairs
* and @index is used to select which one is required
*
* Return: addr
* Return: Address, or FDT_ADDR_T_NONE if there is no such property
*/
fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index);
@@ -114,7 +114,7 @@ void *devfdt_get_addr_index_ptr(const struct udevice *dev, int index);
* @size: Pointer to size variable - this function returns the size
* specified in the 'reg' property here
*
* Return: addr
* Return: Address, or FDT_ADDR_T_NONE if there is no such property
*/
fdt_addr_t devfdt_get_addr_size_index(const struct udevice *dev, int index,
fdt_size_t *size);
@@ -139,13 +139,26 @@ void *devfdt_get_addr_size_index_ptr(const struct udevice *dev, int index,
*
* @dev: Pointer to a device
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @index
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
*
* Return: addr
* Return: Address, or FDT_ADDR_T_NONE if there is no such property
*/
fdt_addr_t devfdt_get_addr_name(const struct udevice *dev, const char *name);
/**
* devfdt_get_addr_name_ptr() - Get the reg property of a device as a pointer,
* indexed by name
*
* @dev: Pointer to a device
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
*
* Return: Pointer to addr, or NULL if there is no such property
*/
void *devfdt_get_addr_name_ptr(const struct udevice *dev, const char *name);
/**
* devfdt_get_addr_size_name() - Get the reg property and its size for a device,
* indexed by name
@@ -154,16 +167,34 @@ fdt_addr_t devfdt_get_addr_name(const struct udevice *dev, const char *name);
*
* @dev: Pointer to a device
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @index
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
* @size: Pointer to size variable - this function returns the size
* specified in the 'reg' property here
*
* Return: addr
* Return: Address, or FDT_ADDR_T_NONE if there is no such property
*/
fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev,
const char *name, fdt_size_t *size);
/**
* devfdt_get_addr_size_name_ptr() - Get the reg property for a device as a
* pointer, indexed by name
*
* Returns the address and size specified in the 'reg' property of a device.
*
* @dev: Pointer to a device
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
* @size: Pointer to size variable - this function returns the size
* specified in the 'reg' property here
*
* Return: Pointer to addr, or NULL if there is no such property
*/
void *devfdt_get_addr_size_name_ptr(const struct udevice *dev,
const char *name, fdt_size_t *size);
/**
* devfdt_get_addr_pci() - Read an address and handle PCI address translation
*
+44 -3
View File
@@ -277,19 +277,32 @@ void *dev_remap_addr_index(const struct udevice *dev, int index);
*
* @dev: Device to read from
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @index
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
*
* Return: address or FDT_ADDR_T_NONE if not found
*/
fdt_addr_t dev_read_addr_name(const struct udevice *dev, const char *name);
/**
* dev_read_addr_name_ptr() - Get the reg property of a device as a pointer,
* indexed by name
*
* @dev: Device to read from
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
*
* Return: pointer or NULL if not found
*/
void *dev_read_addr_name_ptr(const struct udevice *dev, const char *name);
/**
* dev_read_addr_size_name() - Get the reg property of a device, indexed by name
*
* @dev: Device to read from
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @index
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
* @size: place to put size value (on success)
*
@@ -298,13 +311,28 @@ fdt_addr_t dev_read_addr_name(const struct udevice *dev, const char *name);
fdt_addr_t dev_read_addr_size_name(const struct udevice *dev, const char *name,
fdt_size_t *size);
/**
* dev_read_addr_size_name_ptr() - Get the reg property of a device as a pointer,
* indexed by name
*
* @dev: Device to read from
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
* @size: place to put size value (on success)
*
* Return: pointer or NULL if not found
*/
void *dev_read_addr_size_name_ptr(const struct udevice *dev, const char *name,
fdt_size_t *size);
/**
* dev_remap_addr_name() - Get the reg property of a device, indexed by name,
* as a memory-mapped I/O pointer
*
* @dev: Device to read from
* @name: the 'reg' property can hold a list of <addr, size> pairs, with the
* 'reg-names' property providing named-based identification. @index
* 'reg-names' property providing named-based identification. @name
* indicates the value to search for in 'reg-names'.
*
* Return: pointer or NULL if not found
@@ -980,6 +1008,12 @@ static inline fdt_addr_t dev_read_addr_name(const struct udevice *dev,
return devfdt_get_addr_name(dev, name);
}
static inline void *dev_read_addr_name_ptr(const struct udevice *dev,
const char *name)
{
return devfdt_get_addr_name_ptr(dev, name);
}
static inline fdt_addr_t dev_read_addr_size_name(const struct udevice *dev,
const char *name,
fdt_size_t *size)
@@ -987,6 +1021,13 @@ static inline fdt_addr_t dev_read_addr_size_name(const struct udevice *dev,
return devfdt_get_addr_size_name(dev, name, size);
}
static inline void *dev_read_addr_size_name_ptr(const struct udevice *dev,
const char *name,
fdt_size_t *size)
{
return devfdt_get_addr_size_name_ptr(dev, name, size);
}
static inline fdt_addr_t dev_read_addr(const struct udevice *dev)
{
return devfdt_get_addr(dev);
+10
View File
@@ -221,6 +221,16 @@ static int bootdev_test_order(struct unit_test_state *uts)
ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
bootflow_iter_uninit(&iter);
/* Make sure it scans a bootdevs in each target */
ut_assertok(env_set("boot_targets", "mmc spi"));
ut_asserteq(0, bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(3, iter.num_devs);
ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
bootflow_iter_uninit(&iter);
return 0;
}
BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+1 -1
View File
@@ -132,6 +132,6 @@ class Bintoolbootgen(bintool.Bintool):
result = self.build_from_git(
'https://github.com/Xilinx/bootgen',
'all',
['all'],
'bootgen')
return result
+1 -1
View File
@@ -109,6 +109,6 @@ class Bintoolfiptool(bintool.Bintool):
return None
result = self.build_from_git(
'https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git',
'fiptool',
['fiptool'],
'tools/fiptool/fiptool')
return result
+1 -1
View File
@@ -170,7 +170,7 @@ class Bintoolfutility(bintool.Bintool):
# .gitcookies file. So use a mirror instead.
result = self.build_from_git(
'https://github.com/sjg20/vboot_reference.git',
'all',
['all'],
'build/futility/futility',
flags=['USE_FLASHROM=0'])
return result
+26
View File
@@ -80,6 +80,32 @@ class Bintoolmkeficapsule(bintool.Bintool):
return self.run_cmd(*args)
def generate_empty_capsule(self, image_guid, output_fname,
accept=True):
"""Generate empty capsules for FWU A/B updates
Args:
image_guid (str): GUID used for identifying the image
in case of an accept capsule
output_fname (str): Path to the output capsule file
accept (bool): Generate an accept capsule,
else a revert capsule
Returns:
str: Tool output
"""
if accept:
args = [
f'--guid={image_guid}',
'--fw-accept'
]
else:
args = [ '--fw-revert' ]
args += [ output_fname ]
return self.run_cmd(*args)
def fetch(self, method):
"""Fetch handler for mkeficapsule
+44
View File
@@ -532,6 +532,50 @@ payload using the blob-ext subnode.
.. _etype_efi_empty_capsule:
Entry: efi-empty-capsule: Entry for generating EFI Empty Capsule files
----------------------------------------------------------------------
The parameters needed for generation of the empty capsules can
be provided as properties in the entry.
Properties / Entry arguments:
- image-guid: Image GUID which will be used for identifying the
updatable image on the board. Mandatory for accept capsule.
- capsule-type - String to indicate type of capsule to generate. Valid
values are 'accept' and 'revert'.
For more details on the description of the capsule format, and the capsule
update functionality, refer Section 8.5 and Chapter 23 in the `UEFI
specification`_. For more information on the empty capsule, refer the
sections 2.3.2 and 2.3.3 in the `Dependable Boot specification`_.
A typical accept empty capsule entry node would then look something
like this::
empty-capsule {
type = "efi-empty-capsule";
/* GUID of the image being accepted */
image-type-id = SANDBOX_UBOOT_IMAGE_GUID;
capsule-type = "accept";
};
A typical revert empty capsule entry node would then look something
like this::
empty-capsule {
type = "efi-empty-capsule";
capsule-type = "revert";
};
The empty capsules do not have any input payload image.
.. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf
.. _`Dependable Boot specification`: https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
.. _etype_encrypted:
Entry: encrypted: Externally built encrypted binary blob
+18 -6
View File
@@ -11,6 +11,24 @@ from binman.etype.section import Entry_section
from dtoc import fdt_util
from u_boot_pylib import tools
def get_binman_test_guid(type_str):
"""Get the test image GUID for binman
Based on the string passed to the function, return
the corresponding GUID.
Args:
type_str: Key value of the type of GUID to look for
Returns:
The actual GUID value (str)
"""
TYPE_TO_GUID = {
'binman-test' : '09d7cf52-0720-4710-91d1-08469b7fe9c8'
}
return TYPE_TO_GUID[type_str]
class Entry_efi_capsule(Entry_section):
"""Generate EFI capsules
@@ -104,12 +122,6 @@ class Entry_efi_capsule(Entry_section):
self.auth = 1
def BuildSectionData(self, required):
def get_binman_test_guid(type_str):
TYPE_TO_GUID = {
'binman-test' : '09d7cf52-0720-4710-91d1-08469b7fe9c8'
}
return TYPE_TO_GUID[type_str]
private_key = ''
public_key_cert = ''
if self.auth:
+86
View File
@@ -0,0 +1,86 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2023 Linaro Limited
#
# Entry-type module for producing an empty EFI capsule
#
import os
from binman.entry import Entry
from binman.etype.efi_capsule import get_binman_test_guid
from binman.etype.section import Entry_section
from dtoc import fdt_util
from u_boot_pylib import tools
class Entry_efi_empty_capsule(Entry_section):
"""Generate EFI empty capsules
The parameters needed for generation of the empty capsules can
be provided as properties in the entry.
Properties / Entry arguments:
- image-guid: Image GUID which will be used for identifying the
updatable image on the board. Mandatory for accept capsule.
- capsule-type - String to indicate type of capsule to generate. Valid
values are 'accept' and 'revert'.
For more details on the description of the capsule format, and the capsule
update functionality, refer Section 8.5 and Chapter 23 in the `UEFI
specification`_. For more information on the empty capsule, refer the
sections 2.3.2 and 2.3.3 in the `Dependable Boot specification`_.
A typical accept empty capsule entry node would then look something like this
empty-capsule {
type = "efi-empty-capsule";
/* GUID of image being accepted */
image-type-id = SANDBOX_UBOOT_IMAGE_GUID;
capsule-type = "accept";
};
A typical revert empty capsule entry node would then look something like this
empty-capsule {
type = "efi-empty-capsule";
capsule-type = "revert";
};
The empty capsules do not have any input payload image.
.. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf
.. _`Dependable Boot specification`: https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
self.required_props = ['capsule-type']
self.accept = 0
self.revert = 0
def ReadNode(self):
super().ReadNode()
self.image_guid = fdt_util.GetString(self._node, 'image-guid')
self.capsule_type = fdt_util.GetString(self._node, 'capsule-type')
if self.capsule_type != 'accept' and self.capsule_type != 'revert':
self.Raise('capsule-type should be either \'accept\' or \'revert\'')
if self.capsule_type == 'accept' and not self.image_guid:
self.Raise('Image GUID needed for generating accept capsule')
def BuildSectionData(self, required):
uniq = self.GetUniqueName()
outfile = self._filename if self._filename else 'capsule.%s' % uniq
capsule_fname = tools.get_output_filename(outfile)
accept = True if self.capsule_type == 'accept' else False
guid = self.image_guid
if self.image_guid == "binman-test":
guid = get_binman_test_guid('binman-test')
ret = self.mkeficapsule.generate_empty_capsule(guid, capsule_fname,
accept)
if ret is not None:
return tools.read_file(capsule_fname)
def AddBintools(self, btools):
self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
+120 -40
View File
@@ -121,9 +121,14 @@ COMP_BINTOOLS = ['bzip2', 'gzip', 'lz4', 'lzma_alone', 'lzop', 'xz', 'zstd']
TEE_ADDR = 0x5678
# Firmware Management Protocol(FMP) GUID
FW_MGMT_GUID = 'edd5cb6d2de8444cbda17194199ad92a'
FW_MGMT_GUID = '6dcbd5ed-e82d-4c44-bda1-7194199ad92a'
# Image GUID specified in the DTS
CAPSULE_IMAGE_GUID = '52cfd7092007104791d108469b7fe9c8'
CAPSULE_IMAGE_GUID = '09d7cf52-0720-4710-91d1-08469b7fe9c8'
# Windows cert GUID
WIN_CERT_TYPE_EFI_GUID = '4aafd29d-68df-49ee-8aa9-347d375665a7'
# Empty capsule GUIDs
EMPTY_CAPSULE_ACCEPT_GUID = '0c996046-bcc0-4d04-85ec-e1fcedf1c6f8'
EMPTY_CAPSULE_REVERT_GUID = 'acd58b4b-c0e8-475f-99b5-6b3f7e07aaf0'
class TestFunctional(unittest.TestCase):
"""Functional tests for binman
@@ -7223,52 +7228,94 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
self.assertRegex(err,
"Image 'image'.*missing bintools.*: bootgen")
def _GetCapsuleHeaders(self, data):
"""Get the capsule header contents
Args:
data: Capsule file contents
Returns:
Dict:
key: Capsule Header name (str)
value: Header field value (str)
"""
capsule_file = os.path.join(self._indir, 'test.capsule')
tools.write_file(capsule_file, data)
out = tools.run('mkeficapsule', '--dump-capsule', capsule_file)
lines = out.splitlines()
re_line = re.compile(r'^([^:\-\t]*)(?:\t*\s*:\s*(.*))?$')
vals = {}
for line in lines:
mat = re_line.match(line)
if mat:
vals[mat.group(1)] = mat.group(2)
return vals
def _CheckCapsule(self, data, signed_capsule=False, version_check=False,
capoemflags=False):
fmp_signature = "4d535331" # 'M', 'S', 'S', '1'
fmp_size = "10"
fmp_fw_version = "02"
oemflag = "0080"
fmp_signature = "3153534D" # 'M', 'S', 'S', '1'
fmp_size = "00000010"
fmp_fw_version = "00000002"
capsule_image_index = "00000001"
oemflag = "00018000"
auth_hdr_revision = "00000200"
auth_hdr_cert_type = "00000EF1"
payload_data = EFI_CAPSULE_DATA
payload_data_len = len(EFI_CAPSULE_DATA)
# TODO - Currently, these offsets for capsule fields are hardcoded.
# There are plans to add support to the mkeficapsule tool to dump
# the capsule contents which can then be used for capsule
# verification.
hdr = self._GetCapsuleHeaders(data)
# Firmware Management Protocol(FMP) GUID - offset(0 - 32)
self.assertEqual(FW_MGMT_GUID, data.hex()[:32])
# Image GUID - offset(96 - 128)
self.assertEqual(CAPSULE_IMAGE_GUID, data.hex()[96:128])
self.assertEqual(FW_MGMT_GUID.upper(), hdr['EFI_CAPSULE_HDR.CAPSULE_GUID'])
self.assertEqual(CAPSULE_IMAGE_GUID.upper(),
hdr['FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID'])
self.assertEqual(capsule_image_index,
hdr['FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_INDEX'])
if capoemflags:
# OEM Flags - offset(40 - 44)
self.assertEqual(oemflag, data.hex()[40:44])
if signed_capsule and version_check:
# FMP header signature - offset(4770 - 4778)
self.assertEqual(fmp_signature, data.hex()[4770:4778])
# FMP header size - offset(4778 - 4780)
self.assertEqual(fmp_size, data.hex()[4778:4780])
# firmware version - offset(4786 - 4788)
self.assertEqual(fmp_fw_version, data.hex()[4786:4788])
# payload offset signed capsule(4802 - 4808)
self.assertEqual(payload_data.hex(), data.hex()[4802:4808])
elif signed_capsule:
# payload offset signed capsule(4770 - 4776)
self.assertEqual(payload_data.hex(), data.hex()[4770:4776])
elif version_check:
# FMP header signature - offset(184 - 192)
self.assertEqual(fmp_signature, data.hex()[184:192])
# FMP header size - offset(192 - 194)
self.assertEqual(fmp_size, data.hex()[192:194])
# firmware version - offset(200 - 202)
self.assertEqual(fmp_fw_version, data.hex()[200:202])
# payload offset for non-signed capsule with version header(216 - 222)
self.assertEqual(payload_data.hex(), data.hex()[216:222])
self.assertEqual(oemflag, hdr['EFI_CAPSULE_HDR.FLAGS'])
if signed_capsule:
self.assertEqual(auth_hdr_revision,
hdr['EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wREVISION'])
self.assertEqual(auth_hdr_cert_type,
hdr['EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wCERTTYPE'])
self.assertEqual(WIN_CERT_TYPE_EFI_GUID.upper(),
hdr['EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.CERT_TYPE'])
if version_check:
self.assertEqual(fmp_signature,
hdr['FMP_PAYLOAD_HDR.SIGNATURE'])
self.assertEqual(fmp_size,
hdr['FMP_PAYLOAD_HDR.HEADER_SIZE'])
self.assertEqual(fmp_fw_version,
hdr['FMP_PAYLOAD_HDR.FW_VERSION'])
self.assertEqual(payload_data_len, int(hdr['Payload Image Size']))
def _CheckEmptyCapsule(self, data, accept_capsule=False):
if accept_capsule:
capsule_hdr_guid = EMPTY_CAPSULE_ACCEPT_GUID
else:
# payload offset for non-signed capsule with no version header(184 - 190)
self.assertEqual(payload_data.hex(), data.hex()[184:190])
capsule_hdr_guid = EMPTY_CAPSULE_REVERT_GUID
hdr = self._GetCapsuleHeaders(data)
self.assertEqual(capsule_hdr_guid.upper(),
hdr['EFI_CAPSULE_HDR.CAPSULE_GUID'])
if accept_capsule:
capsule_size = "0000002C"
else:
capsule_size = "0000001C"
self.assertEqual(capsule_size,
hdr['EFI_CAPSULE_HDR.CAPSULE_IMAGE_SIZE'])
if accept_capsule:
self.assertEqual(CAPSULE_IMAGE_GUID.upper(), hdr['ACCEPT_IMAGE_GUID'])
def testCapsuleGen(self):
"""Test generation of EFI capsule"""
@@ -7334,5 +7381,38 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
self.assertIn("entry is missing properties: image-guid",
str(e.exception))
def testCapsuleGenAcceptCapsule(self):
"""Test generationg of accept EFI capsule"""
data = self._DoReadFile('319_capsule_accept.dts')
self._CheckEmptyCapsule(data, accept_capsule=True)
def testCapsuleGenRevertCapsule(self):
"""Test generationg of revert EFI capsule"""
data = self._DoReadFile('320_capsule_revert.dts')
self._CheckEmptyCapsule(data)
def testCapsuleGenAcceptGuidMissing(self):
"""Test that binman errors out on missing image GUID for accept capsule"""
with self.assertRaises(ValueError) as e:
self._DoReadFile('321_capsule_accept_missing_guid.dts')
self.assertIn("Image GUID needed for generating accept capsule",
str(e.exception))
def testCapsuleGenEmptyCapsuleTypeMissing(self):
"""Test that capsule-type is specified"""
with self.assertRaises(ValueError) as e:
self._DoReadFile('322_empty_capsule_type_missing.dts')
self.assertIn("entry is missing properties: capsule-type",
str(e.exception))
def testCapsuleGenAcceptOrRevertMissing(self):
"""Test that both accept and revert capsule are not specified"""
with self.assertRaises(ValueError) as e:
self._DoReadFile('323_capsule_accept_revert_missing.dts')
if __name__ == "__main__":
unittest.main()
-3
View File
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
image-index = <0x1>;
-3
View File
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
image-index = <0x1>;
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
image-index = <0x1>;
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
image-index = <0x1>;
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
image-index = <0x1>;
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
image-index = <0x1>;
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
/* Image GUID for testing capsule update */
@@ -3,9 +3,6 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
efi-capsule {
image-index = <0x1>;
+13
View File
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
binman {
efi-empty-capsule {
/* Image GUID for testing capsule update */
image-guid = "binman-test";
capsule-type = "accept";
};
};
};
+11
View File
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
binman {
efi-empty-capsule {
capsule-type = "revert";
};
};
};
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
binman {
efi-empty-capsule {
capsule-type = "accept";
};
};
};
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
binman {
efi-empty-capsule {
/* Image GUID for testing capsule update */
image-guid = "binman-test";
};
};
};
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
binman {
efi-empty-capsule {
/* Image GUID for testing capsule update */
image-guid = "binman-test";
capsule-type = "foo";
};
};
};
+2
View File
@@ -22,6 +22,8 @@
#define __aligned(x) __attribute__((__aligned__(x)))
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
typedef struct {
uint8_t b[16];
} efi_guid_t __aligned(8);
+226 -1
View File
@@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule";
efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
static const char *opts_short = "g:i:I:v:p:c:m:o:dhARD";
enum {
CAPSULE_NORMAL_BLOB = 0,
@@ -49,6 +49,7 @@ static struct option options[] = {
{"fw-accept", no_argument, NULL, 'A'},
{"fw-revert", no_argument, NULL, 'R'},
{"capoemflag", required_argument, NULL, 'o'},
{"dump-capsule", no_argument, NULL, 'D'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0},
};
@@ -69,6 +70,7 @@ static void print_usage(void)
"\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n"
"\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n"
"\t-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff\n"
"\t-D, --dump-capsule dump the contents of the capsule headers\n"
"\t-h, --help print a help message\n",
tool_name);
}
@@ -647,6 +649,215 @@ err:
return ret;
}
static void print_guid(void *ptr)
{
int i;
efi_guid_t *guid = ptr;
const uint8_t seq[] = {
3, 2, 1, 0, '-', 5, 4, '-', 7, 6,
'-', 8, 9, '-', 10, 11, 12, 13, 14, 15 };
for (i = 0; i < ARRAY_SIZE(seq); i++) {
if (seq[i] == '-')
putchar(seq[i]);
else
printf("%02X", guid->b[seq[i]]);
}
printf("\n");
}
static uint32_t dump_fmp_payload_header(
struct fmp_payload_header *fmp_payload_hdr)
{
if (fmp_payload_hdr->signature == FMP_PAYLOAD_HDR_SIGNATURE) {
printf("--------\n");
printf("FMP_PAYLOAD_HDR.SIGNATURE\t\t\t: %08X\n",
FMP_PAYLOAD_HDR_SIGNATURE);
printf("FMP_PAYLOAD_HDR.HEADER_SIZE\t\t\t: %08X\n",
fmp_payload_hdr->header_size);
printf("FMP_PAYLOAD_HDR.FW_VERSION\t\t\t: %08X\n",
fmp_payload_hdr->fw_version);
printf("FMP_PAYLOAD_HDR.LOWEST_SUPPORTED_VERSION\t: %08X\n",
fmp_payload_hdr->lowest_supported_version);
return fmp_payload_hdr->header_size;
}
return 0;
}
static void dump_capsule_auth_header(
struct efi_firmware_image_authentication *capsule_auth_hdr)
{
printf("EFI_FIRMWARE_IMAGE_AUTH.MONOTONIC_COUNT\t\t: %08lX\n",
capsule_auth_hdr->monotonic_count);
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.dwLENGTH\t: %08X\n",
capsule_auth_hdr->auth_info.hdr.dwLength);
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wREVISION\t: %08X\n",
capsule_auth_hdr->auth_info.hdr.wRevision);
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wCERTTYPE\t: %08X\n",
capsule_auth_hdr->auth_info.hdr.wCertificateType);
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.CERT_TYPE\t: ");
print_guid(&capsule_auth_hdr->auth_info.cert_type);
}
static void dump_fmp_capsule_image_header(
struct efi_firmware_management_capsule_image_header *image_hdr)
{
void *capsule_auth_hdr;
void *fmp_payload_hdr;
uint64_t signature_size = 0;
uint32_t payload_size = 0;
uint32_t fmp_payload_hdr_size = 0;
struct efi_firmware_image_authentication *auth_hdr;
printf("--------\n");
printf("FMP_CAPSULE_IMAGE_HDR.VERSION\t\t\t: %08X\n",
image_hdr->version);
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID\t: ");
print_guid(&image_hdr->update_image_type_id);
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_INDEX\t: %08X\n",
image_hdr->update_image_index);
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_SIZE\t\t: %08X\n",
image_hdr->update_image_size);
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_VENDOR_CODE_SIZE\t: %08X\n",
image_hdr->update_vendor_code_size);
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_HARDWARE_INSTANCE\t: %08lX\n",
image_hdr->update_hardware_instance);
printf("FMP_CAPSULE_IMAGE_HDR.IMAGE_CAPSULE_SUPPORT\t: %08lX\n",
image_hdr->image_capsule_support);
printf("--------\n");
if (image_hdr->image_capsule_support & CAPSULE_SUPPORT_AUTHENTICATION) {
capsule_auth_hdr = (char *)image_hdr + sizeof(*image_hdr);
dump_capsule_auth_header(capsule_auth_hdr);
auth_hdr = capsule_auth_hdr;
signature_size = sizeof(auth_hdr->monotonic_count) +
auth_hdr->auth_info.hdr.dwLength;
fmp_payload_hdr = (char *)capsule_auth_hdr + signature_size;
} else {
printf("Capsule Authentication Not Enabled\n");
fmp_payload_hdr = (char *)image_hdr + sizeof(*image_hdr);
}
fmp_payload_hdr_size = dump_fmp_payload_header(fmp_payload_hdr);
payload_size = image_hdr->update_image_size - signature_size -
fmp_payload_hdr_size;
printf("--------\n");
printf("Payload Image Size\t\t\t\t: %08X\n", payload_size);
}
static void dump_fmp_header(
struct efi_firmware_management_capsule_header *fmp_hdr)
{
int i;
void *capsule_image_hdr;
printf("EFI_FMP_HDR.VERSION\t\t\t\t: %08X\n", fmp_hdr->version);
printf("EFI_FMP_HDR.EMBEDDED_DRIVER_COUNT\t\t: %08X\n",
fmp_hdr->embedded_driver_count);
printf("EFI_FMP_HDR.PAYLOAD_ITEM_COUNT\t\t\t: %08X\n",
fmp_hdr->payload_item_count);
/*
* We currently don't support Embedded Drivers.
* Only worry about the payload items.
*/
for (i = 0; i < fmp_hdr->payload_item_count; i++) {
capsule_image_hdr = (char *)fmp_hdr +
fmp_hdr->item_offset_list[i];
dump_fmp_capsule_image_header(capsule_image_hdr);
}
}
static void dump_capsule_header(struct efi_capsule_header *capsule_hdr)
{
printf("EFI_CAPSULE_HDR.CAPSULE_GUID\t\t\t: ");
print_guid((void *)&capsule_hdr->capsule_guid);
printf("EFI_CAPSULE_HDR.HEADER_SIZE\t\t\t: %08X\n",
capsule_hdr->header_size);
printf("EFI_CAPSULE_HDR.FLAGS\t\t\t\t: %08X\n", capsule_hdr->flags);
printf("EFI_CAPSULE_HDR.CAPSULE_IMAGE_SIZE\t\t: %08X\n",
capsule_hdr->capsule_image_size);
}
static void normal_capsule_dump(void *capsule_buf)
{
void *fmp_hdr;
struct efi_capsule_header *hdr = capsule_buf;
dump_capsule_header(hdr);
printf("--------\n");
fmp_hdr = (char *)capsule_buf + sizeof(*hdr);
dump_fmp_header(fmp_hdr);
}
static void empty_capsule_dump(void *capsule_buf)
{
efi_guid_t *accept_image_guid;
struct efi_capsule_header *hdr = capsule_buf;
efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID;
dump_capsule_header(hdr);
if (!memcmp(&efi_empty_accept_capsule, &hdr->capsule_guid,
sizeof(efi_guid_t))) {
accept_image_guid = (void *)(char *)capsule_buf +
sizeof(struct efi_capsule_header);
printf("--------\n");
printf("ACCEPT_IMAGE_GUID\t\t\t\t: ");
print_guid(accept_image_guid);
}
}
static void dump_capsule_contents(char *capsule_file)
{
int fd;
char *ptr;
efi_guid_t efi_fmp_guid = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID;
efi_guid_t efi_empty_revert_capsule = FW_REVERT_OS_GUID;
struct stat sbuf;
if (!capsule_file) {
fprintf(stderr, "No capsule file provided\n");
exit(EXIT_FAILURE);
}
if ((fd = open(capsule_file, O_RDONLY)) < 0) {
fprintf(stderr, "Error opening capsule file: %s\n",
capsule_file);
exit(EXIT_FAILURE);
}
if (fstat(fd, &sbuf) < 0) {
fprintf(stderr, "Can't stat capsule file: %s\n", capsule_file);
exit(EXIT_FAILURE);
}
if ((ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0))
== MAP_FAILED) {
fprintf(stderr, "Can't mmap capsule file: %s\n", capsule_file);
exit(EXIT_FAILURE);
}
if (!memcmp(&efi_fmp_guid, ptr, sizeof(efi_guid_t))) {
normal_capsule_dump(ptr);
} else if (!memcmp(&efi_empty_accept_capsule, ptr,
sizeof(efi_guid_t)) ||
!memcmp(&efi_empty_revert_capsule, ptr,
sizeof(efi_guid_t))) {
empty_capsule_dump(ptr);
} else {
fprintf(stderr, "Unable to decode the capsule file: %s\n",
capsule_file);
exit(EXIT_FAILURE);
}
}
/**
* main - main entry function of mkeficapsule
* @argc: Number of arguments
@@ -666,6 +877,7 @@ int main(int argc, char **argv)
unsigned long index, instance;
uint64_t mcount;
unsigned long oemflags;
bool capsule_dump;
char *privkey_file, *cert_file;
int c, idx;
struct fmp_payload_header_params fmp_ph_params = { 0 };
@@ -676,6 +888,7 @@ int main(int argc, char **argv)
mcount = 0;
privkey_file = NULL;
cert_file = NULL;
capsule_dump = false;
dump_sig = 0;
capsule_type = CAPSULE_NORMAL_BLOB;
oemflags = 0;
@@ -754,12 +967,24 @@ int main(int argc, char **argv)
exit(1);
}
break;
case 'D':
capsule_dump = true;
break;
default:
print_usage();
exit(EXIT_SUCCESS);
}
}
if (capsule_dump) {
if (argc != optind + 1) {
fprintf(stderr, "Must provide the capsule file to parse\n");
exit(EXIT_FAILURE);
}
dump_capsule_contents(argv[argc - 1]);
exit(EXIT_SUCCESS);
}
/* check necessary parameters */
if ((capsule_type == CAPSULE_NORMAL_BLOB &&
((argc != optind + 2) || !guid ||