mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
231
boot/Kconfig
231
boot/Kconfig
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
37
boot/bootm.c
37
boot/bootm.c
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
197
boot/bootmeth_cros.h
Normal 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 */
|
||||
569
boot/cedit.c
569
boot/cedit.c
@@ -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;
|
||||
}
|
||||
|
||||
15
boot/expo.c
15
boot/expo.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
116
boot/fdt_simplefb.c
Normal 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
2150
boot/fdt_support.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
11
boot/image.c
11
boot/image.c
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
18
boot/scene.c
18
boot/scene.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user