Merge branch 'next'

Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
Tom Rini
2023-10-02 10:55:44 -04:00
1001 changed files with 20163 additions and 5805 deletions

View File

@@ -3,14 +3,25 @@ menu "Boot options"
menu "Boot images"
config ANDROID_BOOT_IMAGE
bool "Enable support for Android Boot Images"
bool "Android Boot Images"
default y if FASTBOOT
help
This enables support for booting images which use the Android
image format header.
config FIT
bool "Support Flattened Image Tree"
config TIMESTAMP
bool "Show image date and time when displaying image information"
default y if CMD_DATE
help
When CONFIG_TIMESTAMP is selected, the timestamp (date and time) of
an image is printed by image commands like bootm or iminfo. This
is shown as 'Timestamp: xxx' and 'Created: xxx'. If this option is
enabled, then U-Boot requires FITs to have a timestamp. If a FIT is
loaded that does not, the message 'Wrong FIT format: no timestamp'
is shown.
menuconfig FIT
bool "Flattened Image Tree (FIT)"
select HASH
select MD5
select SHA1
@@ -25,20 +36,10 @@ config FIT
multiple configurations, verification through hashing and also
verified boot (secure boot using RSA).
config TIMESTAMP
bool "Show image date and time when displaying image information"
default y if CMD_DATE
help
When CONFIG_TIMESTAMP is selected, the timestamp (date and time) of
an image is printed by image commands like bootm or iminfo. This
is shown as 'Timestamp: xxx' and 'Created: xxx'. If this option is
enabled, then U-Boot requires FITs to have a timestamp. If a FIT is
loaded that does not, the message 'Wrong FIT format: no timestamp'
is shown.
if FIT
config FIT_EXTERNAL_OFFSET
hex "FIT external data offset"
depends on FIT
default 0x0
help
This specifies a data offset in fit image.
@@ -49,7 +50,6 @@ config FIT_EXTERNAL_OFFSET
config FIT_FULL_CHECK
bool "Do a full check of the FIT before using it"
depends on FIT
default y
help
Enable this do a full check of the FIT to make sure it is valid. This
@@ -59,7 +59,7 @@ config FIT_FULL_CHECK
config FIT_SIGNATURE
bool "Enable signature verification of FIT uImages"
depends on DM && FIT
depends on DM
select HASH
imply RSA
imply RSA_VERIFY
@@ -97,7 +97,7 @@ config FIT_RSASSA_PSS
config FIT_CIPHER
bool "Enable ciphering data in a FIT uImages"
depends on DM && FIT
depends on DM
select AES
help
Enable the feature of data ciphering/unciphering in the tool mkimage
@@ -105,7 +105,6 @@ config FIT_CIPHER
config FIT_VERBOSE
bool "Show verbose messages when FIT images fail"
depends on FIT
help
Generally a system will have valid FIT images so debug messages
are a waste of code space. If you are debugging your images then
@@ -114,7 +113,6 @@ config FIT_VERBOSE
config FIT_BEST_MATCH
bool "Select the best match for the kernel device tree"
depends on FIT
help
When no configuration is explicitly selected, default to the
one whose fdt's compatibility field best matches that of
@@ -124,7 +122,6 @@ config FIT_BEST_MATCH
config FIT_IMAGE_POST_PROCESS
bool "Enable post-processing of FIT artifacts after loading by U-Boot"
depends on FIT
depends on SOCFPGA_SECURE_VAB_AUTH
help
Allows doing any sort of manipulation to blobs after they got extracted
@@ -139,14 +136,13 @@ config FIT_IMAGE_POST_PROCESS
config FIT_PRINT
bool "Support FIT printing"
depends on FIT
default y
help
Support printing the content of the fitImage in a verbose manner.
config SPL_FIT
bool "Support Flattened Image Tree within SPL"
depends on SPL && FIT
depends on SPL
select SPL_HASH
select SPL_OF_LIBFDT
@@ -197,7 +193,7 @@ config SPL_FIT_RSASSA_PSS
config SPL_LOAD_FIT
bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)"
depends on SPL && FIT
depends on SPL
select SPL_FIT
help
Normally with the SPL framework a legacy image is generated as part
@@ -219,7 +215,7 @@ config SPL_LOAD_FIT
config SPL_LOAD_FIT_ADDRESS
hex "load address of fit image"
depends on SPL_LOAD_FIT || SPL_RAM_SUPPORT || TPL_RAM_SUPPORT
depends on SPL_LOAD_FIT
default 0x0
help
Specify the load address of the fit image that will be loaded
@@ -245,7 +241,6 @@ config SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ
config SPL_LOAD_FIT_FULL
bool "Enable SPL loading U-Boot as a FIT (full fitImage features)"
depends on FIT
select SPL_FIT
help
Normally with the SPL framework a legacy image is generated as part
@@ -343,6 +338,8 @@ config VPL_FIT_SIGNATURE_MAX_SIZE
endif # VPL
endif # FIT
config PXE_UTILS
bool
select MENU
@@ -375,8 +372,8 @@ config BOOT_DEFAULTS
of U-Boot to boot various images. Currently much functionality is
tied to enabling the command that exercises it.
config BOOTSTD
bool "Standard boot support"
menuconfig BOOTSTD
bool "Standard boot"
default y
depends on DM && OF_CONTROL && BLK
help
@@ -396,6 +393,8 @@ config BOOTSTD
U-Boot)
- bootflow - a description of how to boot (owned by the distro)
if BOOTSTD
config SPL_BOOTSTD
bool "Standard boot support in SPL"
depends on SPL && SPL_DM && SPL_OF_CONTROL && SPL_BLK
@@ -416,8 +415,6 @@ config VPL_BOOTSTD
boot. It is enabled by default since the main purpose of VPL is to
handle the firmware part of VBE.
if BOOTSTD
config BOOTSTD_FULL
bool "Enhanced features for standard boot"
default y if SANDBOX
@@ -464,8 +461,11 @@ config BOOTMETH_GLOBAL
config BOOTMETH_CROS
bool "Bootdev support for Chromium OS"
depends on X86 || SANDBOX
default y
depends on X86 || ARM || SANDBOX
default y if !ARM
select EFI_PARTITION
select PARTITION_TYPE_GUID
select PARTITION_UUIDS
help
Enables support for booting Chromium OS using bootdevs. This uses the
kernel A slot and obtains the kernel command line from the parameters
@@ -673,7 +673,7 @@ config BOOTMETH_SCRIPT
This provides a way to try out standard boot on an existing boot flow.
It is not enabled by default to save space.
endif
endif # BOOTSTD
config LEGACY_IMAGE_FORMAT
bool "Enable support for the legacy image format"
@@ -693,108 +693,6 @@ config SUPPORT_RAW_INITRD
address of the initrd must be augmented by it's size, in the following
format: "<initrd address>:<initrd size>".
config OF_BOARD_SETUP
bool "Set up board-specific details in device tree before boot"
depends on OF_LIBFDT
help
This causes U-Boot to call ft_board_setup() before booting into
the Operating System. This function can set up various
board-specific information in the device tree for use by the OS.
The device tree is then passed to the OS.
config OF_SYSTEM_SETUP
bool "Set up system-specific details in device tree before boot"
depends on OF_LIBFDT
help
This causes U-Boot to call ft_system_setup() before booting into
the Operating System. This function can set up various
system-specific information in the device tree for use by the OS.
The device tree is then passed to the OS.
config OF_STDOUT_VIA_ALIAS
bool "Update the device-tree stdout alias from U-Boot"
depends on OF_LIBFDT
help
This uses U-Boot's serial alias from the aliases node to update
the device tree passed to the OS. The "linux,stdout-path" property
in the chosen node is set to point to the correct serial node.
This option currently references CONFIG_CONS_INDEX, which is
incorrect when used with device tree as this option does not
exist / should not be used.
config HAVE_TEXT_BASE
bool
depends on !NIOS2 && !XTENSA
depends on !EFI_APP
default y
config TEXT_BASE
depends on HAVE_TEXT_BASE
default 0x0 if POSITION_INDEPENDENT
default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3
default 0x81700000 if MACH_SUNIV
default 0x2a000000 if MACH_SUN9I
default 0x4a000000 if SUNXI_MINIMUM_DRAM_MB >= 256
default 0x42e00000 if SUNXI_MINIMUM_DRAM_MB >= 64
hex "Text Base"
help
The address in memory that U-Boot will be running from, initially.
config HAVE_SYS_MONITOR_BASE
bool
depends on ARC || MIPS || M68K || NIOS2 || PPC || XTENSA || X86 \
|| ENV_IS_IN_FLASH || MTD_NOR_FLASH
depends on !EFI_APP
default y
config SYS_MONITOR_BASE
depends on HAVE_SYS_MONITOR_BASE
hex "Physical start address of boot monitor code"
default TEXT_BASE
help
The physical start address of boot monitor code (which is the same as
CONFIG_TEXT_BASE when linking) and the same as CFG_SYS_FLASH_BASE
when booting from flash.
config SPL_SYS_MONITOR_BASE
depends on MPC85xx && SPL && HAVE_SYS_MONITOR_BASE
hex "Physical start address of SPL monitor code"
default SPL_TEXT_BASE
config TPL_SYS_MONITOR_BASE
depends on MPC85xx && TPL && HAVE_SYS_MONITOR_BASE
hex "Physical start address of TPL monitor code"
config DYNAMIC_SYS_CLK_FREQ
bool "Determine CPU clock frequency at run-time"
help
Implement a get_board_sys_clk function that will determine the CPU
clock frequency at run time, rather than define it statically.
config SYS_CLK_FREQ
depends on !DYNAMIC_SYS_CLK_FREQ
int "CPU clock frequency"
default 125000000 if ARCH_LS1012A
default 100000000 if ARCH_P2020 || ARCH_T1024 || ARCH_T1042 || \
ARCH_LS1021A || FSL_LSCH2 || FSL_LSCH3
default 66666666 if ARCH_P1010 || ARCH_P1020 || ARCH_T4240
default 66660000 if ARCH_T2080
default 33333333 if RCAR_GEN3
default 24000000 if ARCH_EXYNOS
default 20000000 if RCAR_GEN2
default 0
help
A static value for the CPU frequency. Note that if not required
for a given SoC, this can be left at 0.
config ARCH_FIXUP_FDT_MEMORY
bool "Enable arch_fixup_memory_banks() call"
default y
help
Enable FDT memory map syncup before OS boot. This feature can be
used for booting OS with different memory setup where the part of
the memory location should be used for different purpose.
config CHROMEOS
bool "Support booting Chrome OS"
help
@@ -878,7 +776,7 @@ config SYS_BOOT_RAMDISK_HIGH
endmenu # Boot images
config DISTRO_DEFAULTS
bool "Select defaults suitable for booting general purpose Linux distributions"
bool "(deprecated) Script-based booting of Linux distributions"
select BOOT_DEFAULTS
select AUTO_COMPLETE
select CMDLINE_EDITING
@@ -886,6 +784,10 @@ config DISTRO_DEFAULTS
select HUSH_PARSER
select SYS_LONGHELP
help
Note: These scripts have been replaced by Standard Boot. Do not use
them on new boards. See 'Migrating from distro_boot' at
doc/develop/bootstd.rst
Select this to enable various options and commands which are suitable
for building u-boot for booting general purpose Linux distributions.
@@ -1007,7 +909,7 @@ config BOOTSTAGE_STASH
config BOOTSTAGE_STASH_ADDR
hex "Address to stash boot timing information"
default 0
default 0x0
help
Provide an address which will not be overwritten by the OS when it
starts, so that it can read this information when ready.
@@ -1535,6 +1437,63 @@ config SPL_IMAGE_PRE_LOAD_SIG
endmenu
if OF_LIBFDT
menu "Devicetree fixup"
config OF_BOARD_SETUP
bool "Set up board-specific details in device tree before boot"
help
This causes U-Boot to call ft_board_setup() before booting into
the Operating System. This function can set up various
board-specific information in the device tree for use by the OS.
The device tree is then passed to the OS.
config OF_SYSTEM_SETUP
bool "Set up system-specific details in device tree before boot"
help
This causes U-Boot to call ft_system_setup() before booting into
the Operating System. This function can set up various
system-specific information in the device tree for use by the OS.
The device tree is then passed to the OS.
config OF_STDOUT_VIA_ALIAS
bool "Update the device-tree stdout alias from U-Boot"
help
This uses U-Boot's serial alias from the aliases node to update
the device tree passed to the OS. The "linux,stdout-path" property
in the chosen node is set to point to the correct serial node.
This option currently references CONFIG_CONS_INDEX, which is
incorrect when used with device tree as this option does not
exist / should not be used.
config FDT_FIXUP_PARTITIONS
bool "Overwrite MTD partitions in DTS through defined in 'mtdparts'"
help
Allow overwriting defined partitions in the device tree blob
using partition info defined in the 'mtdparts' environment
variable.
config FDT_SIMPLEFB
bool "FDT tools for simplefb support"
help
Enable the fdt tools to manage the simple fb nodes in device tree.
These functions can be used by board to indicate to the OS
the presence of the simple frame buffer with associated reserved
memory
config ARCH_FIXUP_FDT_MEMORY
bool "Enable arch_fixup_memory_banks() call"
default y
help
Enable FDT memory map syncup before OS boot. This feature can be
used for booting OS with different memory setup where the part of
the memory location should be used for different purpose.
endmenu
endif # OF_LIBFDT
config USE_BOOTARGS
bool "Enable boot arguments"
help

View File

@@ -16,6 +16,7 @@ obj-$(CONFIG_QFW) += bootmeth_qfw.o
endif
obj-y += image.o image-board.o
obj-$(CONFIG_ANDROID_AB) += android_ab.o
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
@@ -37,6 +38,9 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o
obj-$(CONFIG_$(SPL_TPL_)CEDIT) += cedit.o
endif
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o
obj-$(CONFIG_$(SPL_TPL_)FDT_SIMPLEFB) += fdt_simplefb.o
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o

View File

@@ -12,7 +12,6 @@
#include <memalign.h>
#include <linux/err.h>
#include <u-boot/crc.h>
#include <u-boot/crc.h>
/**
* Compute the CRC-32 of the bootloader control struct.

View File

@@ -111,6 +111,8 @@ int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name,
int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
struct bootflow_iter *iter, struct bootflow *bflow)
{
struct bootmeth_uc_plat *plat = dev_get_uclass_plat(bflow->method);
bool allow_any_part = plat->flags & BOOTMETHF_ANY_PART;
struct blk_desc *desc = dev_get_uclass_plat(blk);
struct disk_partition info;
char partstr[20];
@@ -142,6 +144,7 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
* us whether there is valid media there
*/
ret = part_get_info(desc, iter->part, &info);
log_debug("part_get_info() returned %d\n", ret);
if (!iter->part && ret == -ENOENT)
ret = 0;
@@ -154,7 +157,7 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
ret = -ESHUTDOWN;
else
bflow->state = BOOTFLOWST_MEDIA;
if (ret) {
if (ret && !allow_any_part) {
/* allow partition 1 to be missing */
if (iter->part == 1) {
iter->max_part = 3;
@@ -174,9 +177,15 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
if (!iter->part) {
iter->first_bootable = part_get_bootable(desc);
log_debug("checking bootable=%d\n", iter->first_bootable);
} else if (allow_any_part) {
/*
* allow any partition to be scanned, by skipping any checks
* for filesystems or partition contents on this disk
*/
/* if there are bootable partitions, scan only those */
} else if (iter->first_bootable ? !info.bootable : iter->part != 1) {
} else if (iter->first_bootable >= 0 &&
(iter->first_bootable ? !info.bootable : iter->part != 1)) {
return log_msg_ret("boot", -EINVAL);
} else {
ret = fs_set_blk_dev_with_part(desc, bflow->part);
@@ -184,16 +193,16 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
if (ret)
return log_msg_ret("fs", ret);
/* Use an #ifdef due to info.sys_ind */
#ifdef CONFIG_DOS_PARTITION
log_debug("%s: Found partition %x type %x fstype %d\n",
blk->name, bflow->part, info.sys_ind,
blk->name, bflow->part,
IS_ENABLED(CONFIG_DOS_PARTITION) ?
disk_partition_sys_ind(&info) : 0,
ret ? -1 : fs_get_type());
#endif
bflow->blk = blk;
bflow->state = BOOTFLOWST_FS;
}
log_debug("method %s\n", bflow->method->name);
ret = bootmeth_read_bootflow(bflow->method, bflow);
if (ret)
return log_msg_ret("method", ret);
@@ -560,7 +569,8 @@ int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
{
const struct bootdev_ops *ops = bootdev_get_ops(dev);
log_debug("->get_bootflow %s=%p\n", dev->name, ops->get_bootflow);
log_debug("->get_bootflow %s,%x=%p\n", dev->name, iter->part,
ops->get_bootflow);
bootflow_init(bflow, dev, iter->method);
if (!ops->get_bootflow)
return default_get_bootflow(dev, iter, bflow);
@@ -820,6 +830,33 @@ int bootdev_hunt(const char *spec, bool show)
return result;
}
int bootdev_unhunt(enum uclass_id id)
{
struct bootdev_hunter *start;
int n_ent, i;
start = ll_entry_start(struct bootdev_hunter, bootdev_hunter);
n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter);
for (i = 0; i < n_ent; i++) {
struct bootdev_hunter *info = start + i;
if (info->uclass == id) {
struct bootstd_priv *std;
int ret;
ret = bootstd_get_priv(&std);
if (ret)
return log_msg_ret("std", ret);
if (!(std->hunters_used & BIT(i)))
return -EALREADY;
std->hunters_used &= ~BIT(i);
return 0;
}
}
return -ENOENT;
}
int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show)
{
struct bootdev_hunter *start;

View File

@@ -432,6 +432,7 @@ void bootflow_free(struct bootflow *bflow)
free(bflow->buf);
free(bflow->os_name);
free(bflow->fdt_fname);
free(bflow->bootmeth_priv);
}
void bootflow_remove(struct bootflow *bflow)
@@ -444,6 +445,22 @@ void bootflow_remove(struct bootflow *bflow)
free(bflow);
}
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
int bootflow_read_all(struct bootflow *bflow)
{
int ret;
if (bflow->state != BOOTFLOWST_READY)
return log_msg_ret("rd", -EPROTO);
ret = bootmeth_read_all(bflow->method, bflow);
if (ret)
return log_msg_ret("rd2", ret);
return 0;
}
#endif /* BOOTSTD_FULL */
int bootflow_boot(struct bootflow *bflow)
{
int ret;

View File

@@ -823,6 +823,43 @@ err:
return ret;
}
int bootm_boot_start(ulong addr, const char *cmdline)
{
static struct cmd_tbl cmd = {"bootm"};
char addr_str[30];
char *argv[] = {addr_str, NULL};
int states;
int ret;
/*
* TODO(sjg@chromium.org): This uses the command-line interface, but
* should not. To clean this up, the various bootm states need to be
* passed an info structure instead of cmdline flags. Then this can
* set up the required info and move through the states without needing
* the command line.
*/
states = BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_PRE_LOAD |
BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS |
BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
BOOTM_STATE_OS_GO;
if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
states |= BOOTM_STATE_RAMDISK;
if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
states |= BOOTM_STATE_OS_CMDLINE;
images.state |= states;
snprintf(addr_str, sizeof(addr_str), "%lx", addr);
ret = env_set("bootargs", cmdline);
if (ret) {
printf("Failed to set cmdline\n");
return ret;
}
ret = do_bootm_states(&cmd, 0, 1, argv, states, &images, 1);
return ret;
}
#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
/**
* image_get_kernel - verify legacy format kernel image

View File

@@ -609,19 +609,5 @@ int boot_selected_os(int argc, char *const argv[], int state,
boot_os_fn *bootm_os_get_boot_func(int os)
{
#ifdef CONFIG_NEEDS_MANUAL_RELOC
static bool relocated;
if (!relocated) {
int i;
/* relocate boot function table */
for (i = 0; i < ARRAY_SIZE(boot_os); i++)
if (boot_os[i] != NULL)
boot_os[i] += gd->reloc_off;
relocated = true;
}
#endif
return boot_os[os];
}

View File

@@ -61,6 +61,18 @@ int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow,
return ops->set_bootflow(dev, bflow, buf, size);
}
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
int bootmeth_read_all(struct udevice *dev, struct bootflow *bflow)
{
const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
if (!ops->read_all)
return -ENOSYS;
return ops->read_all(dev, bflow);
}
#endif /* BOOTSTD_FULL */
int bootmeth_boot(struct udevice *dev, struct bootflow *bflow)
{
const struct bootmeth_ops *ops = bootmeth_get_ops(dev);

View File

@@ -12,24 +12,79 @@
#include <blk.h>
#include <bootdev.h>
#include <bootflow.h>
#include <bootm.h>
#include <bootmeth.h>
#include <display_options.h>
#include <dm.h>
#include <efi.h>
#include <malloc.h>
#include <mapmem.h>
#include <part.h>
#ifdef CONFIG_X86
#include <asm/zimage.h>
#endif
#include <linux/sizes.h>
#include "bootmeth_cros.h"
static const efi_guid_t cros_kern_type = PARTITION_CROS_KERNEL;
/*
* Layout of the ChromeOS kernel
*
* Partitions 2 and 4 contain kernels with type GUID_CROS_KERNEL
*
* Contents are:
*
* Offset Contents
* 0 struct vb2_keyblock
* m struct vb2_kernel_preamble
* m + n kernel buffer
*
* m is keyblock->keyblock_size
* n is preamble->preamble_size
*
* The kernel buffer itself consists of various parts:
*
* Offset Contents
* m + n kernel image (Flat vmlinux binary or FIT)
* b - 8KB Command line text
* b - 4KB X86 setup block (struct boot_params, extends for about 16KB)
* b X86 bootloader (continuation of setup block)
* b + 16KB X86 setup block (copy, used for hold data pointed to)
*
* b is m + n + preamble->bootloader_address - preamble->body_load_address
*
* Useful metadata extends from b - 8KB through to b + 32 KB
*/
enum {
/* Offsets in the kernel-partition header */
KERN_START = 0x4f0,
KERN_SIZE = 0x518,
PROBE_SIZE = SZ_4K, /* initial bytes read from partition */
SETUP_OFFSET = 0x1000, /* bytes before base */
CMDLINE_OFFSET = 0x2000, /* bytes before base */
OFFSET_BASE = 0x100000, /* assumed kernel load-address */
X86_SETUP_OFFSET = -0x1000, /* setup offset relative to base */
CMDLINE_OFFSET = -0x2000, /* cmdline offset relative to base */
X86_KERNEL_OFFSET = 0x4000, /* kernel offset relative to base */
};
/**
* struct cros_priv - Private data
*
* This is read from the disk and recorded for use when the full kernel must
* be loaded and booted
*
* @body_offset: Offset of kernel body from start of partition (in bytes)
* @body_size: Size of kernel body in bytes
* @part_start: Block offset of selected partition from the start of the disk
* @body_load_address: Nominal load address for kernel body
* @bootloader_address: Address of bootloader, after body is loaded at
* body_load_address
* @bootloader_size: Size of bootloader in bytes
* @info_buf: Buffer containing ChromiumOS info
*/
struct cros_priv {
ulong body_offset;
ulong body_size;
lbaint_t part_start;
ulong body_load_address;
ulong bootloader_address;
ulong bootloader_size;
void *info_buf;
};
static int cros_check(struct udevice *dev, struct bootflow_iter *iter)
@@ -77,61 +132,96 @@ static int copy_cmdline(const char *from, const char *uuid, char **bufp)
return 0;
}
static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
/**
* scan_part() - Scan a kernel partition to see if has a ChromeOS header
*
* This reads the first PROBE_SIZE of a partition, loookng for
* VB2_KEYBLOCK_MAGIC
*
* @blk: Block device to scan
* @partnum: Partition number to scan
* @info: Please to put partition info
* @hdrp: Return allocated keyblock header on success
*/
static int scan_part(struct udevice *blk, int partnum,
struct disk_partition *info, struct vb2_keyblock **hdrp)
{
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
ulong base, start, size, setup, cmdline, num_blks, kern_base;
struct disk_partition info;
const char *uuid = NULL;
void *buf, *hdr;
struct blk_desc *desc = dev_get_uclass_plat(blk);
struct vb2_keyblock *hdr;
struct uuid type;
ulong num_blks;
int ret;
log_debug("starting, part=%d\n", bflow->part);
if (!partnum)
return log_msg_ret("efi", -ENOENT);
/* We consider the whole disk, not any one partition */
if (bflow->part)
return log_msg_ret("max", -ENOENT);
/* Check partition 2 */
ret = part_get_info(desc, 2, &info);
ret = part_get_info(desc, partnum, info);
if (ret)
return log_msg_ret("part", ret);
/* Check for kernel partition type */
log_debug("part %x: type=%s\n", partnum, info->type_guid);
if (uuid_str_to_bin(info->type_guid, (u8 *)&type, UUID_STR_FORMAT_GUID))
return log_msg_ret("typ", -EINVAL);
if (memcmp(&cros_kern_type, &type, sizeof(type)))
return log_msg_ret("typ", -ENOEXEC);
/* Make a buffer for the header information */
num_blks = SZ_4K >> desc->log2blksz;
num_blks = PROBE_SIZE >> desc->log2blksz;
log_debug("Reading header, blk=%s, start=%lx, blocks=%lx\n",
bflow->blk->name, (ulong)info.start, num_blks);
hdr = memalign(SZ_1K, SZ_4K);
blk->name, (ulong)info->start, num_blks);
hdr = memalign(SZ_1K, PROBE_SIZE);
if (!hdr)
return log_msg_ret("hdr", -ENOMEM);
ret = blk_read(bflow->blk, info.start, num_blks, hdr);
if (ret != num_blks)
return log_msg_ret("inf", ret);
ret = blk_read(blk, info->start, num_blks, hdr);
if (ret != num_blks) {
free(hdr);
return log_msg_ret("inf", -EIO);
}
if (memcmp("CHROMEOS", hdr, 8))
if (memcmp(VB2_KEYBLOCK_MAGIC, hdr->magic, VB2_KEYBLOCK_MAGIC_SIZE)) {
free(hdr);
log_debug("no magic\n");
return -ENOENT;
}
log_info("Header at %lx\n", (ulong)map_to_sysmem(hdr));
start = *(u32 *)(hdr + KERN_START);
size = ALIGN(*(u32 *)(hdr + KERN_SIZE), desc->blksz);
log_debug("Reading start %lx size %lx\n", start, size);
bflow->size = size;
*hdrp = hdr;
return 0;
}
/**
* cros_read_buf() - Read information into a buf and parse it
*
* @bflow: Bootflow to update
* @buf: Buffer to use
* @size: Size of buffer and number of bytes to read thereinto
* @start: Start offset to read from on disk
* @before_base: Number of bytes to read before the bootloader base
* @uuid: UUID string if supported, else NULL
* Return: 0 if OK, -ENOMEM if out of memory, -EIO on read failure
*/
static int cros_read_buf(struct bootflow *bflow, void *buf, ulong size,
loff_t start, ulong before_base, const char *uuid)
{
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
ulong base, setup, cmdline, kern_base;
ulong num_blks;
int ret;
buf = memalign(SZ_1K, size);
if (!buf)
return log_msg_ret("buf", -ENOMEM);
num_blks = size >> desc->log2blksz;
log_debug("Reading data, blk=%s, start=%lx, blocks=%lx\n",
bflow->blk->name, (ulong)info.start, num_blks);
ret = blk_read(bflow->blk, (ulong)info.start + 0x80, num_blks, buf);
log_debug("Reading info to %lx, blk=%s, size=%lx, blocks=%lx\n",
(ulong)map_to_sysmem(buf), bflow->blk->name, size, num_blks);
ret = blk_read(bflow->blk, start, num_blks, buf);
if (ret != num_blks)
return log_msg_ret("inf", ret);
base = map_to_sysmem(buf);
return log_msg_ret("inf", -EIO);
base = map_to_sysmem(buf) + before_base;
setup = base + start - OFFSET_BASE - SETUP_OFFSET;
cmdline = base + start - OFFSET_BASE - CMDLINE_OFFSET;
kern_base = base + start - OFFSET_BASE + SZ_16K;
log_debug("base %lx setup %lx, cmdline %lx, kern_base %lx\n", base,
setup = base + X86_SETUP_OFFSET;
cmdline = base + CMDLINE_OFFSET;
kern_base = base + X86_KERNEL_OFFSET;
log_debug("base %lx setup %lx cmdline %lx kern_base %lx\n", base,
setup, cmdline, kern_base);
#ifdef CONFIG_X86
@@ -151,35 +241,206 @@ static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
if (!bflow->os_name)
return log_msg_ret("os", -ENOMEM);
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
uuid = info.uuid;
#endif
ret = copy_cmdline(map_sysmem(cmdline, 0), uuid, &bflow->cmdline);
if (ret)
return log_msg_ret("cmd", ret);
bflow->x86_setup = map_sysmem(setup, 0);
return 0;
}
/**
* cros_read_info() - Read information and fill out the bootflow
*
* @bflow: Bootflow to update
* @uuid: UUID string if supported, else NULL
* @preamble: Kernel preamble information
* Return: 0 if OK, -ENOMEM if out of memory, -EIO on read failure
*/
static int cros_read_info(struct bootflow *bflow, const char *uuid,
const struct vb2_kernel_preamble *preamble)
{
struct cros_priv *priv = bflow->bootmeth_priv;
struct udevice *blk = bflow->blk;
struct blk_desc *desc = dev_get_uclass_plat(blk);
ulong offset, size, before_base;
void *buf;
int ret;
log_debug("Kernel preamble at %lx, version major %x, minor %x\n",
(ulong)map_to_sysmem(preamble),
preamble->header_version_major,
preamble->header_version_minor);
log_debug(" - load_address %lx, bl_addr %lx, bl_size %lx\n",
(ulong)preamble->body_load_address,
(ulong)preamble->bootloader_address,
(ulong)preamble->bootloader_size);
priv->body_size = preamble->body_signature.data_size;
priv->body_load_address = preamble->body_load_address;
priv->bootloader_address = preamble->bootloader_address;
priv->bootloader_size = preamble->bootloader_size;
log_debug("Kernel body at %lx size %lx\n", priv->body_offset,
priv->body_size);
/* Work out how many bytes to read before the bootloader base */
before_base = -CMDLINE_OFFSET;
/* Read the cmdline through to the end of the bootloader */
size = priv->bootloader_size + before_base;
offset = priv->body_offset +
(priv->bootloader_address - priv->body_load_address) +
CMDLINE_OFFSET;
buf = malloc(size);
if (!buf)
return log_msg_ret("buf", -ENOMEM);
ret = cros_read_buf(bflow, buf, size,
priv->part_start + (offset >> desc->log2blksz),
before_base, uuid);
if (ret) {
/* Clear this since the buffer is invalid */
bflow->x86_setup = NULL;
free(buf);
return log_msg_ret("pro", ret);
}
priv->info_buf = buf;
return 0;
}
static int cros_read_kernel(struct bootflow *bflow)
{
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
struct cros_priv *priv = bflow->bootmeth_priv;
ulong base, setup;
ulong num_blks;
void *buf;
int ret;
bflow->size = priv->body_size;
buf = memalign(SZ_1K, priv->body_size);
if (!buf)
return log_msg_ret("buf", -ENOMEM);
/* Check that the header is not smaller than permitted */
if (priv->body_offset < PROBE_SIZE)
return log_msg_ret("san", EFAULT);
/* Read kernel body */
num_blks = priv->body_size >> desc->log2blksz;
log_debug("Reading body to %lx, blk=%s, size=%lx, blocks=%lx\n",
(ulong)map_to_sysmem(buf), bflow->blk->name, priv->body_size,
num_blks);
ret = blk_read(bflow->blk,
priv->part_start + (priv->body_offset >> desc->log2blksz),
num_blks, buf);
if (ret != num_blks)
return log_msg_ret("inf", -EIO);
base = map_to_sysmem(buf) + priv->bootloader_address -
priv->body_load_address;
setup = base + X86_SETUP_OFFSET;
bflow->state = BOOTFLOWST_READY;
bflow->buf = buf;
bflow->x86_setup = map_sysmem(setup, 0);
return 0;
}
static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
{
const struct vb2_kernel_preamble *preamble;
struct disk_partition info;
struct vb2_keyblock *hdr;
const char *uuid = NULL;
struct cros_priv *priv;
int ret;
log_debug("starting, part=%x\n", bflow->part);
/* Check for kernel partitions */
ret = scan_part(bflow->blk, bflow->part, &info, &hdr);
if (ret) {
log_debug("- scan failed: err=%d\n", ret);
return log_msg_ret("scan", ret);
}
priv = malloc(sizeof(struct cros_priv));
if (!priv) {
free(hdr);
return log_msg_ret("buf", -ENOMEM);
}
bflow->bootmeth_priv = priv;
log_debug("Selected partition %d, header at %lx\n", bflow->part,
(ulong)map_to_sysmem(hdr));
/* Grab a few things from the preamble */
preamble = (void *)hdr + hdr->keyblock_size;
priv->body_offset = hdr->keyblock_size + preamble->preamble_size;
priv->part_start = info.start;
/* Now read everything we can learn about kernel */
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
uuid = info.uuid;
#endif
ret = cros_read_info(bflow, uuid, preamble);
preamble = NULL;
free(hdr);
if (ret) {
free(priv->info_buf);
free(priv);
return log_msg_ret("inf", ret);
}
bflow->size = priv->body_size;
bflow->state = BOOTFLOWST_READY;
return 0;
}
static int cros_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr, ulong *sizep)
{
return -ENOSYS;
}
#if CONFIG_IS_ENABLED(BOOSTD_FULL)
static int cros_read_all(struct udevice *dev, struct bootflow *bflow)
{
int ret;
if (bflow->buf)
return log_msg_ret("ld", -EALREADY);
ret = cros_read_kernel(bflow);
if (ret)
return log_msg_ret("rd", ret);
return 0;
}
#endif /* BOOSTD_FULL */
static int cros_boot(struct udevice *dev, struct bootflow *bflow)
{
#ifdef CONFIG_X86
zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0,
map_to_sysmem(bflow->x86_setup),
bflow->cmdline);
#endif
int ret;
return log_msg_ret("go", -EFAULT);
if (!bflow->buf) {
ret = cros_read_kernel(bflow);
if (ret)
return log_msg_ret("rd", ret);
}
if (IS_ENABLED(CONFIG_X86)) {
ret = zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0,
map_to_sysmem(bflow->x86_setup),
bflow->cmdline);
} else {
ret = bootm_boot_start(map_to_sysmem(bflow->buf),
bflow->cmdline);
}
return log_msg_ret("go", ret);
}
static int cros_bootmeth_bind(struct udevice *dev)
@@ -187,6 +448,7 @@ static int cros_bootmeth_bind(struct udevice *dev)
struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
plat->desc = "ChromiumOS boot";
plat->flags = BOOTMETHF_ANY_PART;
return 0;
}
@@ -196,6 +458,9 @@ static struct bootmeth_ops cros_bootmeth_ops = {
.read_bootflow = cros_read_bootflow,
.read_file = cros_read_file,
.boot = cros_boot,
#if CONFIG_IS_ENABLED(BOOSTD_FULL)
.read_all = cros_read_all,
#endif /* BOOSTD_FULL */
};
static const struct udevice_id cros_bootmeth_ids[] = {

197
boot/bootmeth_cros.h Normal file
View File

@@ -0,0 +1,197 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Structures used by the ChromiumOS bootmeth
*
* See docs at:
* https://www.chromium.org/chromium-os/chromiumos-design-docs/verified-boot-data-structures/
*
* Original code at:
* https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/refs/heads/main/firmware/2lib/include/2struct.h
*
* Code taken from vboot_reference commit 5b8596ce file 2struct.h
*
* Copyright 2023 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#ifndef __BOOTMETH_CROS_H
#define __BOOTMETH_CROS_H
/* Signature data (a secure hash, possibly signed) */
struct vb2_signature {
/* Offset of signature data from start of this struct */
uint32_t sig_offset;
uint32_t reserved0;
/* Size of signature data in bytes */
uint32_t sig_size;
uint32_t reserved1;
/* Size of the data block which was signed in bytes */
uint32_t data_size;
uint32_t reserved2;
} __attribute__((packed));
#define EXPECTED_VB2_SIGNATURE_SIZE 24
/* Packed public key data */
struct vb2_packed_key {
/* Offset of key data from start of this struct */
uint32_t key_offset;
uint32_t reserved0;
/* Size of key data in bytes (NOT strength of key in bits) */
uint32_t key_size;
uint32_t reserved1;
/* Signature algorithm used by the key (enum vb2_crypto_algorithm) */
uint32_t algorithm;
uint32_t reserved2;
/* Key version */
uint32_t key_version;
uint32_t reserved3;
/* TODO: when redoing this struct, add a text description of the key */
} __attribute__((packed));
#define EXPECTED_VB2_PACKED_KEY_SIZE 32
#define VB2_KEYBLOCK_MAGIC "CHROMEOS"
#define VB2_KEYBLOCK_MAGIC_SIZE 8
/*
* Keyblock, containing the public key used to sign some other chunk of data.
*
* This should be followed by:
* 1) The data_key key data, pointed to by data_key.key_offset.
* 2) The checksum data for (vb2_keyblock + data_key data), pointed to
* by keyblock_checksum.sig_offset.
* 3) The signature data for (vb2_keyblock + data_key data), pointed to
* by keyblock_signature.sig_offset.
*/
struct vb2_keyblock {
/* Magic number */
uint8_t magic[VB2_KEYBLOCK_MAGIC_SIZE];
/* Version of this header format */
uint32_t header_version_major;
uint32_t header_version_minor;
/*
* Length of this entire keyblock, including keys, signatures, and
* padding, in bytes
*/
uint32_t keyblock_size;
uint32_t reserved0;
/*
* Signature for this keyblock (header + data pointed to by data_key)
* For use with signed data keys
*/
struct vb2_signature keyblock_signature;
/*
* SHA-512 hash for this keyblock (header + data pointed to by
* data_key) For use with unsigned data keys.
*
* Only supported for kernel keyblocks, not firmware keyblocks.
*/
struct vb2_signature keyblock_hash;
/* Flags for key (VB2_KEYBLOCK_FLAG_*) */
uint32_t keyblock_flags;
uint32_t reserved1;
/* Key to verify the chunk of data */
struct vb2_packed_key data_key;
} __attribute__((packed));
#define EXPECTED_VB2_KEYBLOCK_SIZE 112
/*
* Preamble block for kernel, version 2.2
*
* This should be followed by:
* 1) The signature data for the kernel body, pointed to by
* body_signature.sig_offset.
* 2) The signature data for (vb2_kernel_preamble + body signature data),
* pointed to by preamble_signature.sig_offset.
* 3) The 16-bit vmlinuz header, which is used for reconstruction of
* vmlinuz image.
*/
struct vb2_kernel_preamble {
/*
* Size of this preamble, including keys, signatures, vmlinuz header,
* and padding, in bytes
*/
uint32_t preamble_size;
uint32_t reserved0;
/* Signature for this preamble (header + body signature) */
struct vb2_signature preamble_signature;
/* Version of this header format */
uint32_t header_version_major;
uint32_t header_version_minor;
/* Kernel version */
uint32_t kernel_version;
uint32_t reserved1;
/* Load address for kernel body */
uint64_t body_load_address;
/* TODO (vboot 2.1): we never used that */
/* Address of bootloader, after body is loaded at body_load_address */
uint64_t bootloader_address;
/* TODO (vboot 2.1): should be a 32-bit offset */
/* Size of bootloader in bytes */
uint32_t bootloader_size;
uint32_t reserved2;
/* Signature for the kernel body */
struct vb2_signature body_signature;
/*
* TODO (vboot 2.1): fields for kernel offset and size. Right now the
* size is implicitly the same as the size of data signed by the body
* signature, and the offset is implicitly at the end of the preamble.
* But that forces us to pad the preamble to 64KB rather than just
* having a tiny preamble and an offset field.
*/
/*
* Fields added in header version 2.1. You must verify the header
* version before reading these fields!
*/
/*
* Address of 16-bit header for vmlinuz reassembly. Readers should
* return 0 for header version < 2.1.
*/
uint64_t vmlinuz_header_address;
/* Size of 16-bit header for vmlinuz in bytes. Readers should return 0
for header version < 2.1 */
uint32_t vmlinuz_header_size;
uint32_t reserved3;
/*
* Fields added in header version 2.2. You must verify the header
* version before reading these fields!
*/
/*
* Flags; see VB2_KERNEL_PREAMBLE_*. Readers should return 0 for
* header version < 2.2. Flags field is currently defined as:
* [31:2] - Reserved (for future use)
* [1:0] - Kernel image type (0b00 - CrOS,
* 0b01 - bootimg,
* 0b10 - multiboot)
*/
uint32_t flags;
} __attribute__((packed));
#endif /* __BOOTMETH_CROS_H */

View File

@@ -6,15 +6,50 @@
* Written by Simon Glass <sjg@chromium.org>
*/
#define LOG_CATEGORY LOGC_EXPO
#include <common.h>
#include <abuf.h>
#include <cedit.h>
#include <cli.h>
#include <dm.h>
#include <env.h>
#include <expo.h>
#include <malloc.h>
#include <menu.h>
#include <rtc.h>
#include <video.h>
#include <linux/delay.h>
#include "scene_internal.h"
enum {
CMOS_MAX_BITS = 2048,
CMOS_MAX_BYTES = CMOS_MAX_BITS / 8,
};
#define CMOS_BYTE(bit) ((bit) / 8)
#define CMOS_BIT(bit) ((bit) % 8)
/**
* struct cedit_iter_priv - private data for cedit operations
*
* @buf: Buffer to use when writing settings to the devicetree
* @node: Node to read from when reading settings from devicetree
* @verbose: true to show writing to environment variables
* @mask: Mask bits for the CMOS RAM. If a bit is set the byte containing it
* will be written
* @value: Value bits for CMOS RAM. This is the actual value written
* @dev: RTC device to write to
*/
struct cedit_iter_priv {
struct abuf *buf;
ofnode node;
bool verbose;
u8 *mask;
u8 *value;
struct udevice *dev;
};
int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
{
struct scene_obj_txt *txt;
@@ -46,18 +81,15 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
return 0;
}
int cedit_run(struct expo *exp)
int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
struct scene **scnp)
{
struct cli_ch_state s_cch, *cch = &s_cch;
struct video_priv *vid_priv;
uint scene_id;
struct udevice *dev;
struct scene *scn;
bool done;
uint scene_id;
int ret;
cli_ch_init(cch);
/* For now we only support a video console */
ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
if (ret)
@@ -92,6 +124,27 @@ int cedit_run(struct expo *exp)
if (ret)
return log_msg_ret("dim", ret);
*vid_privp = vid_priv;
*scnp = scn;
return scene_id;
}
int cedit_run(struct expo *exp)
{
struct cli_ch_state s_cch, *cch = &s_cch;
struct video_priv *vid_priv;
uint scene_id;
struct scene *scn;
bool done;
int ret;
cli_ch_init(cch);
ret = cedit_prepare(exp, &vid_priv, &scn);
if (ret < 0)
return log_msg_ret("prep", ret);
scene_id = ret;
done = false;
do {
struct expo_action act;
@@ -161,3 +214,507 @@ int cedit_run(struct expo *exp)
return 0;
}
static int check_space(int ret, struct abuf *buf)
{
if (ret == -FDT_ERR_NOSPACE) {
if (!abuf_realloc_inc(buf, CEDIT_SIZE_INC))
return log_msg_ret("spc", -ENOMEM);
ret = fdt_resize(abuf_data(buf), abuf_data(buf),
abuf_size(buf));
if (ret)
return log_msg_ret("res", -EFAULT);
}
return 0;
}
static int get_cur_menuitem_text(const struct scene_obj_menu *menu,
const char **strp)
{
struct scene *scn = menu->obj.scene;
const struct scene_menitem *mi;
const struct scene_obj_txt *txt;
const char *str;
mi = scene_menuitem_find(menu, menu->cur_item_id);
if (!mi)
return log_msg_ret("mi", -ENOENT);
txt = scene_obj_find(scn, mi->label_id, SCENEOBJT_TEXT);
if (!txt)
return log_msg_ret("txt", -ENOENT);
str = expo_get_str(scn->expo, txt->str_id);
if (!str)
return log_msg_ret("str", -ENOENT);
*strp = str;
return 0;
}
static int h_write_settings(struct scene_obj *obj, void *vpriv)
{
struct cedit_iter_priv *priv = vpriv;
struct abuf *buf = priv->buf;
switch (obj->type) {
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
break;
case SCENEOBJT_MENU: {
const struct scene_obj_menu *menu;
const char *str;
char name[80];
int ret, i;
menu = (struct scene_obj_menu *)obj;
ret = -EAGAIN;
for (i = 0; ret && i < 2; i++) {
ret = fdt_property_u32(abuf_data(buf), obj->name,
menu->cur_item_id);
if (!i) {
ret = check_space(ret, buf);
if (ret)
return log_msg_ret("res", -ENOMEM);
}
}
/* this should not happen */
if (ret)
return log_msg_ret("wrt", -EFAULT);
ret = get_cur_menuitem_text(menu, &str);
if (ret)
return log_msg_ret("mis", ret);
snprintf(name, sizeof(name), "%s-str", obj->name);
ret = -EAGAIN;
for (i = 0; ret && i < 2; i++) {
ret = fdt_property_string(abuf_data(buf), name, str);
if (!i) {
ret = check_space(ret, buf);
if (ret)
return log_msg_ret("rs2", -ENOMEM);
}
}
/* this should not happen */
if (ret)
return log_msg_ret("wr2", -EFAULT);
break;
}
}
return 0;
}
int cedit_write_settings(struct expo *exp, struct abuf *buf)
{
struct cedit_iter_priv priv;
void *fdt;
int ret;
abuf_init(buf);
if (!abuf_realloc(buf, CEDIT_SIZE_INC))
return log_msg_ret("buf", -ENOMEM);
fdt = abuf_data(buf);
ret = fdt_create(fdt, abuf_size(buf));
if (!ret)
ret = fdt_finish_reservemap(fdt);
if (!ret)
ret = fdt_begin_node(fdt, "");
if (!ret)
ret = fdt_begin_node(fdt, CEDIT_NODE_NAME);
if (ret) {
log_debug("Failed to start FDT (err=%d)\n", ret);
return log_msg_ret("sta", -EINVAL);
}
/* write out the items */
priv.buf = buf;
ret = expo_iter_scene_objs(exp, h_write_settings, &priv);
if (ret) {
log_debug("Failed to write settings (err=%d)\n", ret);
return log_msg_ret("set", ret);
}
ret = fdt_end_node(fdt);
if (!ret)
ret = fdt_end_node(fdt);
if (!ret)
ret = fdt_finish(fdt);
if (ret) {
log_debug("Failed to finish FDT (err=%d)\n", ret);
return log_msg_ret("fin", -EINVAL);
}
return 0;
}
static int h_read_settings(struct scene_obj *obj, void *vpriv)
{
struct cedit_iter_priv *priv = vpriv;
ofnode node = priv->node;
switch (obj->type) {
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
uint val;
if (ofnode_read_u32(node, obj->name, &val))
return log_msg_ret("rd", -ENOENT);
menu = (struct scene_obj_menu *)obj;
menu->cur_item_id = val;
break;
}
}
return 0;
}
int cedit_read_settings(struct expo *exp, oftree tree)
{
struct cedit_iter_priv priv;
ofnode root, node;
int ret;
root = oftree_root(tree);
if (!ofnode_valid(root))
return log_msg_ret("roo", -ENOENT);
node = ofnode_find_subnode(root, CEDIT_NODE_NAME);
if (!ofnode_valid(node))
return log_msg_ret("pat", -ENOENT);
/* read in the items */
priv.node = node;
ret = expo_iter_scene_objs(exp, h_read_settings, &priv);
if (ret) {
log_debug("Failed to read settings (err=%d)\n", ret);
return log_msg_ret("set", ret);
}
return 0;
}
static int h_write_settings_env(struct scene_obj *obj, void *vpriv)
{
const struct scene_obj_menu *menu;
struct cedit_iter_priv *priv = vpriv;
char name[80], var[60];
const char *str;
int val, ret;
if (obj->type != SCENEOBJT_MENU)
return 0;
menu = (struct scene_obj_menu *)obj;
val = menu->cur_item_id;
snprintf(var, sizeof(var), "c.%s", obj->name);
if (priv->verbose)
printf("%s=%d\n", var, val);
ret = env_set_ulong(var, val);
if (ret)
return log_msg_ret("set", ret);
ret = get_cur_menuitem_text(menu, &str);
if (ret)
return log_msg_ret("mis", ret);
snprintf(name, sizeof(name), "c.%s-str", obj->name);
if (priv->verbose)
printf("%s=%s\n", name, str);
ret = env_set(name, str);
if (ret)
return log_msg_ret("st2", ret);
return 0;
}
int cedit_write_settings_env(struct expo *exp, bool verbose)
{
struct cedit_iter_priv priv;
int ret;
/* write out the items */
priv.verbose = verbose;
ret = expo_iter_scene_objs(exp, h_write_settings_env, &priv);
if (ret) {
log_debug("Failed to write settings to env (err=%d)\n", ret);
return log_msg_ret("set", ret);
}
return 0;
}
static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
{
struct cedit_iter_priv *priv = vpriv;
struct scene_obj_menu *menu;
char var[60];
int val;
if (obj->type != SCENEOBJT_MENU)
return 0;
menu = (struct scene_obj_menu *)obj;
val = menu->cur_item_id;
snprintf(var, sizeof(var), "c.%s", obj->name);
val = env_get_ulong(var, 10, 0);
if (priv->verbose)
printf("%s=%d\n", var, val);
if (!val)
return log_msg_ret("get", -ENOENT);
/*
* note that no validation is done here, to make sure the ID is valid
* and actually points to a menu item
*/
menu->cur_item_id = val;
return 0;
}
int cedit_read_settings_env(struct expo *exp, bool verbose)
{
struct cedit_iter_priv priv;
int ret;
/* write out the items */
priv.verbose = verbose;
ret = expo_iter_scene_objs(exp, h_read_settings_env, &priv);
if (ret) {
log_debug("Failed to read settings from env (err=%d)\n", ret);
return log_msg_ret("set", ret);
}
return 0;
}
/**
* get_cur_menuitem_seq() - Get the sequence number of a menu's current item
*
* Enumerates the items of a menu (0, 1, 2) and returns the sequence number of
* the currently selected item. If the first item is selected, this returns 0;
* if the second, 1; etc.
*
* @menu: Menu to check
* Return: Sequence number on success, else -ve error value
*/
static int get_cur_menuitem_seq(const struct scene_obj_menu *menu)
{
const struct scene_menitem *mi;
int seq, found;
seq = 0;
found = -1;
list_for_each_entry(mi, &menu->item_head, sibling) {
if (mi->id == menu->cur_item_id) {
found = seq;
break;
}
seq++;
}
if (found == -1)
return log_msg_ret("nf", -ENOENT);
return found;
}
static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv)
{
const struct scene_obj_menu *menu;
struct cedit_iter_priv *priv = vpriv;
int val, ret;
uint i, seq;
if (obj->type != SCENEOBJT_MENU)
return 0;
menu = (struct scene_obj_menu *)obj;
val = menu->cur_item_id;
ret = get_cur_menuitem_seq(menu);
if (ret < 0)
return log_msg_ret("cur", ret);
seq = ret;
log_debug("%s: seq=%d\n", menu->obj.name, seq);
/* figure out where to place this item */
if (!obj->bit_length)
return log_msg_ret("len", -EINVAL);
if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS)
return log_msg_ret("bit", -E2BIG);
for (i = 0; i < obj->bit_length; i++, seq >>= 1) {
uint bitnum = obj->start_bit + i;
priv->mask[CMOS_BYTE(bitnum)] |= 1 << CMOS_BIT(bitnum);
if (seq & 1)
priv->value[CMOS_BYTE(bitnum)] |= BIT(CMOS_BIT(bitnum));
log_debug("bit %x %x %x\n", bitnum,
priv->mask[CMOS_BYTE(bitnum)],
priv->value[CMOS_BYTE(bitnum)]);
}
return 0;
}
int cedit_write_settings_cmos(struct expo *exp, struct udevice *dev,
bool verbose)
{
struct cedit_iter_priv priv;
int ret, i, count, first, last;
/* write out the items */
priv.mask = calloc(1, CMOS_MAX_BYTES);
if (!priv.mask)
return log_msg_ret("mas", -ENOMEM);
priv.value = calloc(1, CMOS_MAX_BYTES);
if (!priv.value) {
free(priv.mask);
return log_msg_ret("val", -ENOMEM);
}
ret = expo_iter_scene_objs(exp, h_write_settings_cmos, &priv);
if (ret) {
log_debug("Failed to write CMOS (err=%d)\n", ret);
ret = log_msg_ret("set", ret);
goto done;
}
/* write the data to the RTC */
first = CMOS_MAX_BYTES;
last = -1;
for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
if (priv.mask[i]) {
log_debug("Write byte %x: %x\n", i, priv.value[i]);
ret = rtc_write8(dev, i, priv.value[i]);
if (ret) {
ret = log_msg_ret("wri", ret);
goto done;
}
count++;
first = min(first, i);
last = max(last, i);
}
}
if (verbose) {
printf("Write %d bytes from offset %x to %x\n", count, first,
last);
}
done:
free(priv.mask);
free(priv.value);
return ret;
}
static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv)
{
struct cedit_iter_priv *priv = vpriv;
const struct scene_menitem *mi;
struct scene_obj_menu *menu;
int val, ret;
uint i;
if (obj->type != SCENEOBJT_MENU)
return 0;
menu = (struct scene_obj_menu *)obj;
/* figure out where to place this item */
if (!obj->bit_length)
return log_msg_ret("len", -EINVAL);
if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS)
return log_msg_ret("bit", -E2BIG);
val = 0;
for (i = 0; i < obj->bit_length; i++) {
uint bitnum = obj->start_bit + i;
uint offset = CMOS_BYTE(bitnum);
/* read the byte if not already read */
if (!priv->mask[offset]) {
ret = rtc_read8(priv->dev, offset);
if (ret < 0)
return log_msg_ret("rea", ret);
priv->value[offset] = ret;
/* mark it as read */
priv->mask[offset] = 0xff;
}
if (priv->value[offset] & BIT(CMOS_BIT(bitnum)))
val |= BIT(i);
log_debug("bit %x %x\n", bitnum, val);
}
/* update the current item */
mi = scene_menuitem_find_seq(menu, val);
if (!mi)
return log_msg_ret("seq", -ENOENT);
menu->cur_item_id = mi->id;
log_debug("Update menu %d cur_item_id %d\n", menu->obj.id, mi->id);
return 0;
}
int cedit_read_settings_cmos(struct expo *exp, struct udevice *dev,
bool verbose)
{
struct cedit_iter_priv priv;
int ret, i, count, first, last;
/* read in the items */
priv.mask = calloc(1, CMOS_MAX_BYTES);
if (!priv.mask)
return log_msg_ret("mas", -ENOMEM);
priv.value = calloc(1, CMOS_MAX_BYTES);
if (!priv.value) {
free(priv.mask);
return log_msg_ret("val", -ENOMEM);
}
priv.dev = dev;
ret = expo_iter_scene_objs(exp, h_read_settings_cmos, &priv);
if (ret) {
log_debug("Failed to read CMOS (err=%d)\n", ret);
ret = log_msg_ret("set", ret);
goto done;
}
/* read the data to the RTC */
first = CMOS_MAX_BYTES;
last = -1;
for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
if (priv.mask[i]) {
log_debug("Read byte %x: %x\n", i, priv.value[i]);
count++;
first = min(first, i);
last = max(last, i);
}
}
if (verbose) {
printf("Read %d bytes from offset %x to %x\n", count, first,
last);
}
done:
free(priv.mask);
free(priv.value);
return ret;
}

View File

@@ -266,3 +266,18 @@ int expo_apply_theme(struct expo *exp, ofnode node)
return 0;
}
int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
void *priv)
{
struct scene *scn;
int ret;
list_for_each_entry(scn, &exp->scene_head, sibling) {
ret = scene_iter_objs(scn, iter, priv);
if (ret)
return log_msg_ret("wr", ret);
}
return 0;
}

View File

@@ -214,22 +214,21 @@ static void list_strings(struct build_info *info)
* @info: Build information
* @node: Node containing the menu description
* @scn: Scene to add the menu to
* @id: ID for the menu
* @objp: Returns the object pointer
* Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format
* error, -ENOENT if there is a references to a non-existent string
*/
static int menu_build(struct build_info *info, ofnode node, struct scene *scn)
static int menu_build(struct build_info *info, ofnode node, struct scene *scn,
uint id, struct scene_obj **objp)
{
struct scene_obj_menu *menu;
uint title_id, menu_id;
const u32 *item_ids;
int ret, size, i;
const char *name;
u32 id;
name = ofnode_get_name(node);
ret = ofnode_read_u32(node, "id", &id);
if (ret)
return log_msg_ret("id", -EINVAL);
ret = scene_menu(scn, name, id, &menu);
if (ret < 0)
@@ -275,12 +274,13 @@ static int menu_build(struct build_info *info, ofnode node, struct scene *scn)
if (ret < 0)
return log_msg_ret("mi", ret);
}
*objp = &menu->obj;
return 0;
}
/**
* menu_build() - Build an expo object and add it to a scene
* obj_build() - Build an expo object and add it to a scene
*
* See doc/develop/expo.rst for a description of the format
*
@@ -292,8 +292,9 @@ static int menu_build(struct build_info *info, ofnode node, struct scene *scn)
*/
static int obj_build(struct build_info *info, ofnode node, struct scene *scn)
{
struct scene_obj *obj;
const char *type;
u32 id;
u32 id, val;
int ret;
log_debug("- object %s\n", ofnode_get_name(node));
@@ -306,12 +307,17 @@ static int obj_build(struct build_info *info, ofnode node, struct scene *scn)
return log_msg_ret("typ", -EINVAL);
if (!strcmp("menu", type))
ret = menu_build(info, node, scn);
ret = menu_build(info, node, scn, id, &obj);
else
ret = -EINVAL;
if (ret)
return log_msg_ret("bld", ret);
if (!ofnode_read_u32(node, "start-bit", &val))
obj->start_bit = val;
if (!ofnode_read_u32(node, "bit-length", &val))
obj->bit_length = val;
return 0;
}

116
boot/fdt_simplefb.c Normal file
View File

@@ -0,0 +1,116 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Simplefb device tree support
*
* (C) Copyright 2015
* Stephen Warren <swarren@wwwdotorg.org>
*/
#include <common.h>
#include <dm.h>
#include <fdt_support.h>
#include <asm/global_data.h>
#include <linux/libfdt.h>
#include <video.h>
DECLARE_GLOBAL_DATA_PTR;
static int fdt_simplefb_configure_node(void *blob, int off)
{
int xsize, ysize;
int bpix; /* log2 of bits per pixel */
const char *name;
ulong fb_base;
struct video_uc_plat *plat;
struct video_priv *uc_priv;
struct udevice *dev;
int ret;
ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
if (ret)
return ret;
uc_priv = dev_get_uclass_priv(dev);
plat = dev_get_uclass_plat(dev);
xsize = uc_priv->xsize;
ysize = uc_priv->ysize;
bpix = uc_priv->bpix;
fb_base = plat->base;
switch (bpix) {
case 4: /* VIDEO_BPP16 */
name = "r5g6b5";
break;
case 5: /* VIDEO_BPP32 */
name = "a8r8g8b8";
break;
default:
return -EINVAL;
}
return fdt_setup_simplefb_node(blob, off, fb_base, xsize, ysize,
xsize * (1 << bpix) / 8, name);
}
int fdt_simplefb_add_node(void *blob)
{
static const char compat[] = "simple-framebuffer";
static const char disabled[] = "disabled";
int off, ret;
off = fdt_add_subnode(blob, 0, "framebuffer");
if (off < 0)
return -1;
ret = fdt_setprop(blob, off, "status", disabled, sizeof(disabled));
if (ret < 0)
return -1;
ret = fdt_setprop(blob, off, "compatible", compat, sizeof(compat));
if (ret < 0)
return -1;
return fdt_simplefb_configure_node(blob, off);
}
/**
* fdt_simplefb_enable_existing_node() - enable simple-framebuffer DT node
*
* @blob: device-tree
* Return: 0 on success, non-zero otherwise
*/
static int fdt_simplefb_enable_existing_node(void *blob)
{
int off;
off = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer");
if (off < 0)
return -1;
return fdt_simplefb_configure_node(blob, off);
}
#if IS_ENABLED(CONFIG_VIDEO)
int fdt_simplefb_enable_and_mem_rsv(void *blob)
{
struct fdt_memory mem;
int ret;
/* nothing to do when video is not active */
if (!video_is_active())
return 0;
ret = fdt_simplefb_enable_existing_node(blob);
if (ret)
return ret;
/* nothing to do when the frame buffer is not defined */
if (gd->video_bottom == gd->video_top)
return 0;
/* reserved with no-map tag the video buffer */
mem.start = gd->video_bottom;
mem.end = gd->video_top - 1;
return fdtdec_add_reserved_memory(blob, "framebuffer", &mem, NULL, 0, NULL,
FDTDEC_RESERVED_MEMORY_NO_MAP);
}
#endif

2150
boot/fdt_support.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -57,20 +57,6 @@ struct checksum_algo *image_get_checksum_algo(const char *full_name)
int i;
const char *name;
if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
static bool done;
if (!done) {
done = true;
for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) {
struct checksum_algo *algo = &checksum_algos[i];
MANUAL_RELOC(algo->name);
MANUAL_RELOC(algo->calculate);
}
}
}
for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) {
name = checksum_algos[i].name;
/* Make sure names match and next char is a comma */
@@ -87,20 +73,6 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name)
struct crypto_algo *crypto, *end;
const char *name;
if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
static bool done;
if (!done) {
done = true;
crypto = ll_entry_start(struct crypto_algo, cryptos);
end = ll_entry_end(struct crypto_algo, cryptos);
for (; crypto < end; crypto++) {
MANUAL_RELOC(crypto->name);
MANUAL_RELOC(crypto->verify);
}
}
}
/* Move name to after the comma */
name = strchr(full_name, ',');
if (!name)

View File

@@ -182,6 +182,7 @@ static const table_entry_t uimage_type[] = {
{ IH_TYPE_SUNXI_TOC0, "sunxi_toc0", "Allwinner TOC0 Boot Image" },
{ IH_TYPE_FDT_LEGACY, "fdt_legacy", "legacy Image with Flat Device Tree ", },
{ IH_TYPE_RENESAS_SPKG, "spkgimage", "Renesas SPKG Image" },
{ IH_TYPE_STARFIVE_SPL, "sfspl", "StarFive SPL Image" },
{ -1, "", "", },
};
@@ -571,7 +572,7 @@ const char *genimg_get_cat_name(enum ih_category category, uint id)
entry = get_table_entry(table_info[category].table, id);
if (!entry)
return unknown_msg(category);
return manual_reloc(entry->lname);
return entry->lname;
}
/**
@@ -591,7 +592,7 @@ const char *genimg_get_cat_short_name(enum ih_category category, uint id)
entry = get_table_entry(table_info[category].table, id);
if (!entry)
return unknown_msg(category);
return manual_reloc(entry->sname);
return entry->sname;
}
int genimg_get_cat_count(enum ih_category category)
@@ -641,7 +642,7 @@ char *get_table_entry_name(const table_entry_t *table, char *msg, int id)
table = get_table_entry(table, id);
if (!table)
return msg;
return manual_reloc(table->lname);
return table->lname;
}
const char *genimg_get_os_name(uint8_t os)
@@ -676,7 +677,7 @@ static const char *genimg_get_short_name(const table_entry_t *table, int val)
table = get_table_entry(table, val);
if (!table)
return "unknown";
return manual_reloc(table->sname);
return table->sname;
}
const char *genimg_get_type_short_name(uint8_t type)
@@ -719,7 +720,7 @@ int get_table_entry_id(const table_entry_t *table,
const table_entry_t *t;
for (t = table; t->id >= 0; ++t) {
if (t->sname && !strcasecmp(manual_reloc(t->sname), name))
if (t->sname && !strcasecmp(t->sname, name))
return t->id;
}
debug("Invalid %s Type: %s\n", table_name, name);

View File

@@ -554,7 +554,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
label->name);
goto cleanup;
}
strcpy(initrd_filesize, simple_xtoa(size));
initrd_addr_str = env_get("ramdisk_addr_r");
size = snprintf(initrd_str, sizeof(initrd_str), "%s:%lx",
initrd_addr_str, size);
@@ -702,8 +702,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
}
}
if (label->kaslrseed)
label_boot_kaslrseed();
if (label->kaslrseed)
label_boot_kaslrseed();
#ifdef CONFIG_OF_LIBFDT_OVERLAY
if (label->fdtoverlays)

View File

@@ -79,7 +79,7 @@ int scene_obj_count(struct scene *scn)
return count;
}
void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type)
void *scene_obj_find(const struct scene *scn, uint id, enum scene_obj_t type)
{
struct scene_obj *obj;
@@ -681,3 +681,19 @@ int scene_set_open(struct scene *scn, uint id, bool open)
return 0;
}
int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter,
void *priv)
{
struct scene_obj *obj;
list_for_each_entry(obj, &scn->obj_head, sibling) {
int ret;
ret = iter(obj, priv);
if (ret)
return log_msg_ret("itr", ret);
}
return 0;
}

View File

@@ -9,6 +9,8 @@
#ifndef __SCENE_INTERNAL_H
#define __SCENE_INTERNAL_H
typedef int (*expo_scene_obj_iterator)(struct scene_obj *obj, void *priv);
/**
* expo_lookup_scene_id() - Look up a scene ID
*
@@ -38,7 +40,7 @@ uint resolve_id(struct expo *exp, uint id);
* @type: Type of the object, or SCENEOBJT_NONE to match any type
* Returns: Object found, or NULL if not found
*/
void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type);
void *scene_obj_find(const struct scene *scn, uint id, enum scene_obj_t type);
/**
* scene_obj_find_by_name() - Find an object in a scene by name
@@ -198,4 +200,50 @@ int scene_menu_render_deps(struct scene *scn, struct scene_obj_menu *menu);
*/
int scene_menu_calc_dims(struct scene_obj_menu *menu);
/**
* scene_iter_objs() - Iterate through all scene objects
*
* @scn: Scene to process
* @iter: Iterator to call on each object
* @priv: Private data to pass to the iterator, in addition to the object
* Return: 0 if OK, -ve on error
*/
int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter,
void *priv);
/**
* expo_iter_scene_objects() - Iterate through all scene objects
*
* @exp: Expo to process
* @iter: Iterator to call on each object
* @priv: Private data to pass to the iterator, in addition to the object
* Return: 0 if OK, -ve on error
*/
int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
void *priv);
/**
* scene_menuitem_find() - Find the menu item for an ID
*
* Looks up the menu to find the item with the given ID
*
* @menu: Menu to check
* @id: ID to look for
* Return: Menu item, or NULL if not found
*/
struct scene_menitem *scene_menuitem_find(const struct scene_obj_menu *menu,
int id);
/**
* scene_menuitem_find_seq() - Find the menu item at a sequential position
*
* This numbers the items from 0 and returns the seq'th one
*
* @menu: Menu to check
* @seq: Sequence number to look for
* Return: menu item if found, else NULL
*/
struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu,
uint seq);
#endif /* __SCENE_INTERNAL_H */

View File

@@ -33,8 +33,8 @@ void scene_menu_destroy(struct scene_obj_menu *menu)
scene_menuitem_destroy(item);
}
static struct scene_menitem *scene_menuitem_find(struct scene_obj_menu *menu,
int id)
struct scene_menitem *scene_menuitem_find(const struct scene_obj_menu *menu,
int id)
{
struct scene_menitem *item;
@@ -46,6 +46,22 @@ static struct scene_menitem *scene_menuitem_find(struct scene_obj_menu *menu,
return NULL;
}
struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu,
uint seq)
{
struct scene_menitem *item;
uint i;
i = 0;
list_for_each_entry(item, &menu->item_head, sibling) {
if (i == seq)
return item;
i++;
}
return NULL;
}
/**
* update_pointers() - Update the pointer object and handle highlights
*
@@ -416,7 +432,7 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id,
if (!scene_obj_find(scn, label_id, SCENEOBJT_TEXT))
return log_msg_ret("txt", -EINVAL);
item = calloc(1, sizeof(struct scene_obj_menu));
item = calloc(1, sizeof(struct scene_menitem));
if (!item)
return log_msg_ret("item", -ENOMEM);
item->name = strdup(name);

View File

@@ -230,4 +230,4 @@ static int bootmeth_vbe_ft_fixup(void *ctx, struct event *event)
return 0;
}
EVENT_SPY(EVT_FT_FIXUP, bootmeth_vbe_ft_fixup);
EVENT_SPY_FULL(EVT_FT_FIXUP, bootmeth_vbe_ft_fixup);

View File

@@ -109,4 +109,4 @@ static int bootmeth_vbe_simple_ft_fixup(void *ctx, struct event *event)
return 0;
}
EVENT_SPY(EVT_FT_FIXUP, bootmeth_vbe_simple_ft_fixup);
EVENT_SPY_FULL(EVT_FT_FIXUP, bootmeth_vbe_simple_ft_fixup);