summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/Kconfig77
-rw-r--r--boot/Makefile3
-rw-r--r--boot/bootflow_internal.h11
-rw-r--r--boot/bootflow_menu.c382
-rw-r--r--boot/bootm.c27
-rw-r--r--boot/bootm_os.c11
-rw-r--r--boot/bootmeth-uclass.c25
-rw-r--r--boot/bootmeth_android.c1
-rw-r--r--boot/bootmeth_efi.c1
-rw-r--r--boot/bootmeth_pxe.c1
-rw-r--r--boot/bootmeth_rauc.c432
-rw-r--r--boot/cedit.c163
-rw-r--r--boot/expo.c72
-rw-r--r--boot/fdt_support.c17
-rw-r--r--boot/image-android.c11
-rw-r--r--boot/image-board.c56
-rw-r--r--boot/image-fdt.c96
-rw-r--r--boot/image-pre-load.c1
-rw-r--r--boot/image.c1
-rw-r--r--boot/pxe_utils.c4
-rw-r--r--boot/scene.c477
-rw-r--r--boot/scene_internal.h71
-rw-r--r--boot/scene_menu.c169
-rw-r--r--boot/scene_textedit.c61
-rw-r--r--boot/scene_textline.c47
25 files changed, 1699 insertions, 518 deletions
diff --git a/boot/Kconfig b/boot/Kconfig
index 30eb5b328d7..2ff6f003738 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -11,6 +11,17 @@ config ANDROID_BOOT_IMAGE
This enables support for booting images which use the Android
image format header.
+config ANDROID_BOOT_IMAGE_IGNORE_BLOB_ADDR
+ bool "Android Boot Image ignore addr"
+ default n
+ help
+ This ignore kernel/ramdisk load addr specified in androidboot header.
+
+ There is a concern on exposing the whole memory to image loading is
+ dangerous. Also, since it's not always possible to change the load
+ addr by repacking the boot.img (mainly due to AVB signature mismatch),
+ we need a way to use kernel_addr_r and ramdisk_addr_r.
+
config TIMESTAMP
bool "Show image date and time when displaying image information"
default y if CMD_DATE
@@ -855,6 +866,56 @@ config EXPO
The expo can be presented in graphics form using a vidconsole, or in
text form on a serial console.
+config BOOTMETH_RAUC
+ bool "Bootdev support for RAUC A/B systems"
+ depends on CMDLINE
+ select BOOTMETH_GLOBAL
+ select HUSH_PARSER
+ help
+ Enables support for booting RAUC A/B systems from MMC devices. This
+ makes the bootdevs look for a 'boot.scr.uimg' or 'boot.scr' in the
+ respective boot partitions, describing how to boot the distro.
+
+if BOOTMETH_RAUC
+
+config BOOTMETH_RAUC_BOOT_ORDER
+ string "RAUC boot order"
+ default "A B"
+ help
+ Sets the default boot order. This must be list of space-separated
+ strings naming the individual boot slots. Each entry in this string
+ should correspond to an existing slot on the target's flash device.
+
+config BOOTMETH_RAUC_PARTITIONS
+ string "RAUC boot and root partitions indexes"
+ default "1,2 3,4"
+ help
+ Sets the partition indexes of boot and root slots. This must be a list
+ of comma-separated pair values, which in turn are separated by spaces.
+ The first value in pair is for the boot partition and second for the
+ root partition.
+
+config BOOTMETH_RAUC_DEFAULT_TRIES
+ int "RAUC slot default tries"
+ default 3
+ help
+ Sets how many times a slot should be tried booting, before considering
+ it to be bad.
+
+config BOOTMETH_RAUC_RESET_ALL_ZERO_TRIES
+ bool "Reset slot tries when all RAUC slots have zero tries left"
+ default y
+ help
+ When all slots have zero tries left or no valid slot was found, reset
+ to the default boot order set by BOOTMETH_RAUC_BOOT_ORDER and set the
+ slot tries to their default value specified by
+ BOOTMETH_RAUC_DEFAULT_TRIES.
+
+ This prevents a system from remaining in an unbootable state, after
+ all slot tries were decremented to zero.
+
+endif # BOOTMETH_RAUC
+
config BOOTMETH_SANDBOX
def_bool y
depends on SANDBOX
@@ -1789,6 +1850,16 @@ config OF_BOARD_SETUP
board-specific information in the device tree for use by the OS.
The device tree is then passed to the OS.
+config OF_BOARD_SETUP_EXTENDED
+ bool "Set up latest board-specific details in device tree before boot"
+ imply OF_BOARD_SETUP
+ help
+ This causes U-Boot to call ft_board_setup_ex() before booting into
+ the Operating System. Similar function as ft_board_setup(). However,
+ its modifications are not overwritten by other system changes and are
+ applied to the device tree as the very last step before boot.
+ 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
@@ -1845,7 +1916,7 @@ config USE_BOOTARGS
config BOOTARGS
string "Boot arguments"
- depends on USE_BOOTARGS && !USE_DEFAULT_ENV_FILE
+ depends on USE_BOOTARGS && !ENV_USE_DEFAULT_ENV_TEXT_FILE
help
This can be used to pass arguments to the bootm command. The value of
CONFIG_BOOTARGS goes into the environment value "bootargs". Note that
@@ -1880,7 +1951,7 @@ config USE_BOOTCOMMAND
config BOOTCOMMAND
string "bootcmd value"
- depends on USE_BOOTCOMMAND && !USE_DEFAULT_ENV_FILE
+ depends on USE_BOOTCOMMAND && !ENV_USE_DEFAULT_ENV_TEXT_FILE
default "bootflow scan -lb" if BOOTSTD_DEFAULTS && CMD_BOOTFLOW_FULL
default "bootflow scan" if BOOTSTD_DEFAULTS && !CMD_BOOTFLOW_FULL
default "run distro_bootcmd" if !BOOTSTD_BOOTCOMMAND && DISTRO_DEFAULTS
@@ -1903,7 +1974,7 @@ config USE_PREBOOT
config PREBOOT
string "preboot default value"
- depends on USE_PREBOOT && !USE_DEFAULT_ENV_FILE
+ depends on USE_PREBOOT && !ENV_USE_DEFAULT_ENV_TEXT_FILE
default "usb start" if USB_KEYBOARD
default ""
help
diff --git a/boot/Makefile b/boot/Makefile
index 71dafaefa76..3da6f7a0914 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_$(PHASE_)BOOTMETH_EXTLINUX_PXE) += bootmeth_pxe.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_EFILOADER) += bootmeth_efi.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_CROS) += bootm.o bootm_os.o bootmeth_cros.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_QFW) += bootmeth_qfw.o
+obj-$(CONFIG_$(PHASE_)BOOTMETH_RAUC) += bootmeth_rauc.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_SCRIPT) += bootmeth_script.o
obj-$(CONFIG_$(PHASE_)CEDIT) += cedit.o
@@ -58,7 +59,7 @@ obj-$(CONFIG_CMD_ADTIMG) += image-android-dt.o
obj-$(CONFIG_$(PHASE_)LOAD_FIT) += common_fit.o
obj-$(CONFIG_$(PHASE_)EXPO) += expo.o scene.o expo_build.o
-obj-$(CONFIG_$(PHASE_)EXPO) += scene_menu.o scene_textline.o
+obj-$(CONFIG_$(PHASE_)EXPO) += scene_menu.o scene_textline.o scene_textedit.o
ifdef CONFIG_COREBOOT_SYSINFO
obj-$(CONFIG_$(PHASE_)EXPO) += expo_build_cb.o
endif
diff --git a/boot/bootflow_internal.h b/boot/bootflow_internal.h
index 38cf02a55b5..4cdb6966a7b 100644
--- a/boot/bootflow_internal.h
+++ b/boot/bootflow_internal.h
@@ -14,7 +14,10 @@ enum {
START,
/* strings */
- STR_PROMPT,
+ STR_PROMPT1A,
+ STR_PROMPT1B,
+ STR_PROMPT2,
+ STR_AUTOBOOT,
STR_MENU_TITLE,
STR_POINTER,
@@ -23,10 +26,14 @@ enum {
/* objects */
OBJ_U_BOOT_LOGO,
+ OBJ_BOX,
OBJ_MENU,
- OBJ_PROMPT,
+ OBJ_PROMPT1A,
+ OBJ_PROMPT1B,
+ OBJ_PROMPT2,
OBJ_MENU_TITLE,
OBJ_POINTER,
+ OBJ_AUTOBOOT,
/* strings for menu items */
STR_LABEL = 100,
diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 9d0dc352f97..4a442e16850 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -25,21 +25,22 @@
* struct menu_priv - information about the menu
*
* @num_bootflows: Number of bootflows in the menu
+ * @last_bootdev: bootdev of the last bootflow added to the menu, NULL if none
*/
struct menu_priv {
int num_bootflows;
+ struct udevice *last_bootdev;
};
int bootflow_menu_new(struct expo **expp)
{
- struct udevice *last_bootdev;
struct scene_obj_menu *menu;
struct menu_priv *priv;
- struct bootflow *bflow;
struct scene *scn;
struct expo *exp;
+ bool use_font;
void *logo;
- int ret, i;
+ int ret;
priv = calloc(1, sizeof(*priv));
if (!priv)
@@ -53,153 +54,177 @@ int bootflow_menu_new(struct expo **expp)
if (ret < 0)
return log_msg_ret("scn", ret);
- ret |= scene_txt_str(scn, "prompt", OBJ_PROMPT, STR_PROMPT,
- "UP and DOWN to choose, ENTER to select", NULL);
+ ret = scene_box(scn, "box", OBJ_BOX, 2, NULL);
+ if (ret < 0)
+ return log_msg_ret("bmb", ret);
+ ret |= scene_obj_set_bbox(scn, OBJ_BOX, 30, 90, 1366 - 30, 720);
ret = scene_menu(scn, "main", OBJ_MENU, &menu);
ret |= scene_obj_set_pos(scn, OBJ_MENU, MARGIN_LEFT, 100);
ret |= scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
"U-Boot - Boot Menu", NULL);
- ret |= scene_menu_set_title(scn, OBJ_MENU, OBJ_PROMPT);
+ ret |= scene_obj_set_bbox(scn, OBJ_MENU_TITLE, 0, 32,
+ SCENEOB_DISPLAY_MAX, 30);
+ ret |= scene_obj_set_halign(scn, OBJ_MENU_TITLE, SCENEOA_CENTRE);
logo = video_get_u_boot_logo();
if (logo) {
ret |= scene_img(scn, "ulogo", OBJ_U_BOOT_LOGO, logo, NULL);
- ret |= scene_obj_set_pos(scn, OBJ_U_BOOT_LOGO, -4, 4);
+ ret |= scene_obj_set_pos(scn, OBJ_U_BOOT_LOGO, 1165, 100);
}
+ ret |= scene_txt_str(scn, "prompt1a", OBJ_PROMPT1A, STR_PROMPT1A,
+ "Use the \x18 and \x19 keys to select which entry is highlighted.",
+ NULL);
+ ret |= scene_txt_str(scn, "prompt1b", OBJ_PROMPT1B, STR_PROMPT1B,
+ "Use the UP and DOWN keys to select which entry is highlighted.",
+ NULL);
+ ret |= scene_txt_str(scn, "prompt2", OBJ_PROMPT2, STR_PROMPT2,
+ "Press enter to boot the selected OS, 'e' to edit the commands "
+ "before booting or 'c' for a command-line. ESC to return to "
+ "previous menu", NULL);
+ ret |= scene_txt_str(scn, "autoboot", OBJ_AUTOBOOT, STR_AUTOBOOT,
+ "The highlighted entry will be executed automatically in %ds.",
+ NULL);
+ ret |= scene_obj_set_bbox(scn, OBJ_PROMPT1A, 0, 590,
+ SCENEOB_DISPLAY_MAX, 30);
+ ret |= scene_obj_set_bbox(scn, OBJ_PROMPT1B, 0, 620,
+ SCENEOB_DISPLAY_MAX, 30);
+ ret |= scene_obj_set_bbox(scn, OBJ_PROMPT2, 100, 650,
+ 1366 - 100, 700);
+ ret |= scene_obj_set_bbox(scn, OBJ_AUTOBOOT, 0, 720,
+ SCENEOB_DISPLAY_MAX, 750);
+ ret |= scene_obj_set_halign(scn, OBJ_PROMPT1A, SCENEOA_CENTRE);
+ ret |= scene_obj_set_halign(scn, OBJ_PROMPT1B, SCENEOA_CENTRE);
+ ret |= scene_obj_set_halign(scn, OBJ_PROMPT2, SCENEOA_CENTRE);
+ ret |= scene_obj_set_valign(scn, OBJ_PROMPT2, SCENEOA_CENTRE);
+ ret |= scene_obj_set_halign(scn, OBJ_AUTOBOOT, SCENEOA_CENTRE);
+
+ use_font = IS_ENABLED(CONFIG_CONSOLE_TRUETYPE);
+ scene_obj_set_hide(scn, OBJ_PROMPT1A, use_font);
+ scene_obj_set_hide(scn, OBJ_PROMPT1B, !use_font);
+ scene_obj_set_hide(scn, OBJ_AUTOBOOT, use_font);
+
ret |= scene_txt_str(scn, "cur_item", OBJ_POINTER, STR_POINTER, ">",
NULL);
ret |= scene_menu_set_pointer(scn, OBJ_MENU, OBJ_POINTER);
if (ret < 0)
return log_msg_ret("new", -EINVAL);
- last_bootdev = NULL;
- for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
- ret = bootflow_next_glob(&bflow), i++) {
- struct bootmeth_uc_plat *ucp;
- char str[2], *label, *key;
- uint preview_id;
- bool add_gap;
+ exp->show_highlight = true;
- if (bflow->state != BOOTFLOWST_READY)
- continue;
+ *expp = exp;
- /* No media to show for BOOTMETHF_GLOBAL bootmeths */
- ucp = dev_get_uclass_plat(bflow->method);
- if (ucp->flags & BOOTMETHF_GLOBAL)
- continue;
+ return 0;
+}
- *str = i < 10 ? '0' + i : 'A' + i - 10;
- str[1] = '\0';
- key = strdup(str);
- if (!key)
- return log_msg_ret("key", -ENOMEM);
- label = strdup(dev_get_parent(bflow->dev)->name);
- if (!label) {
- free(key);
- return log_msg_ret("nam", -ENOMEM);
- }
-
- add_gap = last_bootdev != bflow->dev;
- last_bootdev = bflow->dev;
-
- ret = expo_str(exp, "prompt", STR_POINTER, ">");
- ret |= scene_txt_str(scn, "label", ITEM_LABEL + i,
- STR_LABEL + i, label, NULL);
- ret |= scene_txt_str(scn, "desc", ITEM_DESC + i, STR_DESC + i,
- bflow->os_name ? bflow->os_name :
- bflow->name, NULL);
- ret |= scene_txt_str(scn, "key", ITEM_KEY + i, STR_KEY + i, key,
- NULL);
- preview_id = 0;
- if (bflow->logo) {
- preview_id = ITEM_PREVIEW + i;
- ret |= scene_img(scn, "preview", preview_id,
- bflow->logo, NULL);
- }
- ret |= scene_menuitem(scn, OBJ_MENU, "item", ITEM + i,
- ITEM_KEY + i, ITEM_LABEL + i,
- ITEM_DESC + i, preview_id,
- add_gap ? SCENEMIF_GAP_BEFORE : 0,
- NULL);
-
- if (ret < 0)
- return log_msg_ret("itm", -EINVAL);
- priv->num_bootflows++;
+int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq,
+ struct scene **scnp)
+{
+ struct menu_priv *priv = exp->priv;
+ char str[2], *label, *key;
+ struct udevice *media;
+ struct scene *scn;
+ const char *name;
+ uint preview_id;
+ uint scene_id;
+ bool add_gap;
+ int ret;
+
+ ret = expo_first_scene_id(exp);
+ if (ret < 0)
+ return log_msg_ret("scn", ret);
+ scene_id = ret;
+ scn = expo_lookup_scene_id(exp, scene_id);
+
+ *str = seq < 10 ? '0' + seq : 'A' + seq - 10;
+ str[1] = '\0';
+ key = strdup(str);
+ if (!key)
+ return log_msg_ret("key", -ENOMEM);
+
+ media = dev_get_parent(bflow->dev);
+ if (device_get_uclass_id(media) == UCLASS_MASS_STORAGE)
+ name = "usb";
+ else
+ name = media->name;
+ label = strdup(name);
+
+ if (!label) {
+ free(key);
+ return log_msg_ret("nam", -ENOMEM);
}
- ret = scene_arrange(scn);
- if (ret)
- return log_msg_ret("arr", ret);
+ add_gap = priv->last_bootdev != bflow->dev;
+
+ /* disable this gap for now, since it looks a little ugly */
+ add_gap = false;
+ priv->last_bootdev = bflow->dev;
+
+ ret = expo_str(exp, "prompt", STR_POINTER, ">");
+ ret |= scene_txt_str(scn, "label", ITEM_LABEL + seq,
+ STR_LABEL + seq, label, NULL);
+ ret |= scene_txt_str(scn, "desc", ITEM_DESC + seq, STR_DESC + seq,
+ bflow->os_name ? bflow->os_name :
+ bflow->name, NULL);
+ ret |= scene_txt_str(scn, "key", ITEM_KEY + seq, STR_KEY + seq, key,
+ NULL);
+ preview_id = 0;
+ if (bflow->logo) {
+ preview_id = ITEM_PREVIEW + seq;
+ ret |= scene_img(scn, "preview", preview_id,
+ bflow->logo, NULL);
+ }
+ ret |= scene_menuitem(scn, OBJ_MENU, "item", ITEM + seq,
+ ITEM_KEY + seq, ITEM_LABEL + seq,
+ ITEM_DESC + seq, preview_id,
+ add_gap ? SCENEMIF_GAP_BEFORE : 0,
+ NULL);
- *expp = exp;
+ if (ret < 0)
+ return log_msg_ret("itm", -EINVAL);
+ priv->num_bootflows++;
+ *scnp = scn;
return 0;
}
-int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
+int bootflow_menu_add_all(struct expo *exp)
{
- struct menu_priv *priv = exp->priv;
+ struct bootflow *bflow;
struct scene *scn;
- u32 font_size;
- int ret;
+ int ret, i;
- log_debug("Applying theme %s\n", ofnode_get_name(node));
- scn = expo_lookup_scene_id(exp, MAIN);
- if (!scn)
- return log_msg_ret("scn", -ENOENT);
-
- /* Avoid error-checking optional items */
- if (!ofnode_read_u32(node, "font-size", &font_size)) {
- int i;
-
- log_debug("font size %d\n", font_size);
- scene_txt_set_font(scn, OBJ_PROMPT, NULL, font_size);
- scene_txt_set_font(scn, OBJ_POINTER, NULL, font_size);
- for (i = 0; i < priv->num_bootflows; i++) {
- ret = scene_txt_set_font(scn, ITEM_DESC + i, NULL,
- font_size);
- if (ret)
- return log_msg_ret("des", ret);
- scene_txt_set_font(scn, ITEM_KEY + i, NULL, font_size);
- scene_txt_set_font(scn, ITEM_LABEL + i, NULL,
- font_size);
- }
- }
+ for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
+ ret = bootflow_next_glob(&bflow), i++) {
+ struct bootmeth_uc_plat *ucp;
- ret = scene_arrange(scn);
- if (ret)
- return log_msg_ret("arr", ret);
+ if (bflow->state != BOOTFLOWST_READY)
+ continue;
+
+ /* No media to show for BOOTMETHF_GLOBAL bootmeths */
+ ucp = dev_get_uclass_plat(bflow->method);
+ if (ucp->flags & BOOTMETHF_GLOBAL)
+ continue;
+
+ ret = bootflow_menu_add(exp, bflow, i, &scn);
+ if (ret)
+ return log_msg_ret("bao", ret);
+ }
return 0;
}
-int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
- struct bootflow **bflowp)
+int bootflow_menu_setup(struct bootstd_priv *std, bool text_mode,
+ struct expo **expp)
{
- struct cli_ch_state s_cch, *cch = &s_cch;
- struct bootflow *sel_bflow;
struct udevice *dev;
struct expo *exp;
- uint sel_id;
- bool done;
int ret;
- cli_ch_init(cch);
-
- sel_bflow = NULL;
- *bflowp = NULL;
-
ret = bootflow_menu_new(&exp);
if (ret)
- return log_msg_ret("exp", ret);
-
- if (ofnode_valid(std->theme)) {
- ret = bootflow_menu_apply_theme(exp, std->theme);
- if (ret)
- return log_msg_ret("thm", ret);
- }
+ return log_msg_ret("bmn", ret);
/* For now we only support a video console */
ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
@@ -216,78 +241,91 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
if (text_mode)
expo_set_text_mode(exp, text_mode);
- done = false;
- do {
- struct expo_action act;
- int ichar, key;
+ *expp = exp;
- ret = expo_render(exp);
- if (ret)
- break;
-
- ichar = cli_ch_process(cch, 0);
- if (!ichar) {
- while (!ichar && !tstc()) {
- schedule();
- mdelay(2);
- ichar = cli_ch_process(cch, -ETIMEDOUT);
- }
- if (!ichar) {
- ichar = getchar();
- ichar = cli_ch_process(cch, ichar);
- }
- }
-
- key = 0;
- if (ichar) {
- key = bootmenu_conv_key(ichar);
- if (key == BKEY_NONE)
- key = ichar;
- }
- if (!key)
- continue;
+ return 0;
+}
- ret = expo_send_key(exp, key);
- if (ret)
- break;
-
- ret = expo_action_get(exp, &act);
- if (!ret) {
- switch (act.type) {
- case EXPOACT_SELECT:
- sel_id = act.select.id;
- done = true;
- break;
- case EXPOACT_QUIT:
- done = true;
- break;
- default:
- break;
- }
- }
- } while (!done);
+int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
+ struct expo **expp)
+{
+ struct scene *scn;
+ struct expo *exp;
+ uint scene_id;
+ int ret;
+ ret = bootflow_menu_setup(std, text_mode, &exp);
if (ret)
- return log_msg_ret("end", ret);
-
- if (sel_id) {
- struct bootflow *bflow;
- int i;
-
- for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
- ret = bootflow_next_glob(&bflow), i++) {
- if (i == sel_id - ITEM) {
- sel_bflow = bflow;
- break;
- }
- }
+ return log_msg_ret("bmd", ret);
+
+ ret = bootflow_menu_add_all(exp);
+ if (ret)
+ return log_msg_ret("bma", ret);
+
+ if (ofnode_valid(std->theme)) {
+ ret = expo_apply_theme(exp, std->theme);
+ if (ret)
+ return log_msg_ret("thm", ret);
}
- expo_destroy(exp);
+ ret = expo_calc_dims(exp);
+ if (ret)
+ return log_msg_ret("bmd", ret);
+
+ ret = expo_first_scene_id(exp);
+ if (ret < 0)
+ return log_msg_ret("scn", ret);
+ scene_id = ret;
+ scn = expo_lookup_scene_id(exp, scene_id);
+
+ scene_set_highlight_id(scn, OBJ_MENU);
+
+ ret = scene_arrange(scn);
+ if (ret)
+ return log_msg_ret("arr", ret);
+
+ *expp = exp;
+
+ return 0;
+}
+
+int bootflow_menu_poll(struct expo *exp, int *seqp)
+{
+ struct bootflow *sel_bflow;
+ struct expo_action act;
+ struct scene *scn;
+ int item, ret;
+
+ sel_bflow = NULL;
- if (!sel_bflow)
+ scn = expo_lookup_scene_id(exp, exp->scene_id);
+
+ item = scene_menu_get_cur_item(scn, OBJ_MENU);
+ *seqp = item > 0 ? item - ITEM : -1;
+
+ ret = expo_poll(exp, &act);
+ if (ret)
+ return log_msg_ret("bmp", ret);
+
+ switch (act.type) {
+ case EXPOACT_SELECT:
+ *seqp = act.select.id - ITEM;
+ break;
+ case EXPOACT_POINT_ITEM: {
+ struct scene *scn = expo_lookup_scene_id(exp, MAIN);
+
+ if (!scn)
+ return log_msg_ret("bms", -ENOENT);
+ ret = scene_menu_select_item(scn, OBJ_MENU, act.select.id);
+ if (ret)
+ return log_msg_ret("bmp", ret);
+ return -ERESTART;
+ }
+ case EXPOACT_QUIT:
+ return -EPIPE;
+ default:
return -EAGAIN;
- *bflowp = sel_bflow;
+ }
return 0;
}
diff --git a/boot/bootm.c b/boot/bootm.c
index 108ca7fb472..4bdca22ea8c 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -623,12 +623,16 @@ static int bootm_load_os(struct bootm_headers *images, int boot_progress)
*/
if (os.type == IH_TYPE_KERNEL_NOLOAD && os.comp != IH_COMP_NONE) {
ulong req_size = ALIGN(image_len * 4, SZ_1M);
+ phys_addr_t addr;
- load = lmb_alloc(req_size, SZ_2M);
- if (!load)
+ err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, &addr,
+ req_size, LMB_NONE);
+ if (err)
return 1;
- os.load = load;
- images->ep = load;
+
+ load = (ulong)addr;
+ os.load = (ulong)addr;
+ images->ep = (ulong)addr;
debug("Allocated %lx bytes at %lx for kernel (size %lx) decompression\n",
req_size, load, image_len);
}
@@ -698,9 +702,18 @@ static int bootm_load_os(struct bootm_headers *images, int boot_progress)
images->os.end = relocated_addr + image_size;
}
- if (CONFIG_IS_ENABLED(LMB))
- lmb_reserve(images->os.load, (load_end - images->os.load),
- LMB_NONE);
+ if (CONFIG_IS_ENABLED(LMB)) {
+ phys_addr_t load;
+
+ load = (phys_addr_t)images->os.load;
+ err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &load,
+ (load_end - images->os.load), LMB_NONE);
+ if (err) {
+ log_err("Unable to allocate memory %#lx for loading OS\n",
+ images->os.load);
+ return 1;
+ }
+ }
return 0;
}
diff --git a/boot/bootm_os.c b/boot/bootm_os.c
index a3c7cb5332e..88f7c183867 100644
--- a/boot/bootm_os.c
+++ b/boot/bootm_os.c
@@ -402,6 +402,17 @@ static int do_bootm_elf(int flag, struct bootm_info *bmi)
if (flag != BOOTM_STATE_OS_GO)
return 0;
+ /*
+ * Required per RISC-V boot protocol:
+ * a0(argc) = hartid of the current core
+ * a1(argv) = address of the devicetree in memory
+ * https://www.kernel.org/doc/html/latest/arch/riscv/boot.html#register-state
+ */
+#if defined(CONFIG_RISCV)
+ bmi->argc = gd->arch.boot_hart;
+ bmi->argv = (char **)bmi->images->ft_addr;
+#endif
+
bootelf(bmi->images->ep, flags, bmi->argc, bmi->argv);
return 1;
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index 014b7588e8d..188f6ea1895 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -12,6 +12,7 @@
#include <bootmeth.h>
#include <bootstd.h>
#include <dm.h>
+#include <dm/device-internal.h>
#include <env_internal.h>
#include <fs.h>
#include <malloc.h>
@@ -135,10 +136,12 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
* We don't support skipping global bootmeths. Instead, the user
* should omit them from the ordering
*/
- if (!include_global)
- return log_msg_ret("glob", -EPERM);
+ if (!include_global) {
+ ret = log_msg_ret("glob", -EPERM);
+ goto err_order;
+ }
memcpy(order, std->bootmeth_order,
- count * sizeof(struct bootmeth *));
+ count * sizeof(struct udevice *));
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL)) {
for (i = 0; i < count; i++) {
@@ -146,6 +149,12 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
struct bootmeth_uc_plat *ucp;
bool is_global;
+ ret = device_probe(dev);
+ if (ret) {
+ ret = log_msg_ret("probe", ret);
+ goto err_order;
+ }
+
ucp = dev_get_uclass_plat(dev);
is_global = ucp->flags &
BOOTMETHF_GLOBAL;
@@ -190,8 +199,10 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
}
count = upto;
}
- if (!count)
- return log_msg_ret("count2", -ENOENT);
+ if (!count) {
+ ret = log_msg_ret("count2", -ENOENT);
+ goto err_order;
+ }
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && include_global &&
iter->first_glob_method != -1 && iter->first_glob_method != count) {
@@ -202,6 +213,10 @@ int bootmeth_setup_iter_order(struct bootflow_iter *iter, bool include_global)
iter->num_methods = count;
return 0;
+
+err_order:
+ free(order);
+ return ret;
}
int bootmeth_set_order(const char *order_str)
diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
index 654ebfdf1fc..8c2bde10e17 100644
--- a/boot/bootmeth_android.c
+++ b/boot/bootmeth_android.c
@@ -18,6 +18,7 @@
#include <bootm.h>
#include <bootmeth.h>
#include <dm.h>
+#include <env.h>
#include <image.h>
#include <malloc.h>
#include <mapmem.h>
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index 0c9b4c3d59d..0af23df3a4a 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -15,6 +15,7 @@
#include <dm.h>
#include <efi.h>
#include <efi_loader.h>
+#include <env.h>
#include <fs.h>
#include <malloc.h>
#include <mapmem.h>
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c
index 6e5e0f99ea4..faa8d729b15 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -13,6 +13,7 @@
#include <bootmeth.h>
#include <command.h>
#include <dm.h>
+#include <env.h>
#include <extlinux.h>
#include <fs.h>
#include <log.h>
diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c
new file mode 100644
index 00000000000..fc60e6e355d
--- /dev/null
+++ b/boot/bootmeth_rauc.c
@@ -0,0 +1,432 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for distro boot with RAUC
+ *
+ * Copyright 2025 PHYTEC Messtechnik GmbH
+ * Written by Martin Schwan <m.schwan@phytec.de>
+ */
+
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <blk.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <bootstd.h>
+#include <dm.h>
+#include <env.h>
+#include <fs.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <string.h>
+#include <asm/cache.h>
+
+/* Length of env var "BOOT_*_LEFT" */
+#define BOOT_LEFT_LEN (5 + 32 + 5)
+
+static const char * const script_names[] = { "boot.scr", "boot.scr.uimg", NULL };
+
+/**
+ * struct distro_rauc_slot - Slot information
+ *
+ * A slot describes the unit of a bootable system consisting of one or multiple
+ * partitions. This usually includes a root filesystem, kernel and potentially other
+ * files, like device trees and boot scripts for that particular distribution.
+ *
+ * @name The slot name
+ * @boot_part The boot partition number on disk
+ * @root_part The root partition number on disk
+ */
+struct distro_rauc_slot {
+ char *name;
+ int boot_part;
+ int root_part;
+};
+
+/**
+ * struct distro_rauc_priv - Private data
+ *
+ * @slots All slots of the device in default order
+ * @boot_order String of the current boot order containing the active slot names
+ */
+struct distro_rauc_priv {
+ struct distro_rauc_slot **slots;
+};
+
+static struct distro_rauc_slot *get_slot(struct distro_rauc_priv *priv,
+ const char *slot_name)
+{
+ int i;
+
+ for (i = 0; priv->slots[i]->name; i++) {
+ if (!strcmp(priv->slots[i]->name, slot_name))
+ return priv->slots[i];
+ }
+
+ return NULL;
+}
+
+static int distro_rauc_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+ /*
+ * This distro only works on whole MMC devices, as multiple partitions
+ * are needed for an A/B system.
+ */
+ if (bootflow_iter_check_mmc(iter))
+ return log_msg_ret("mmc", -EOPNOTSUPP);
+ if (iter->part)
+ return log_msg_ret("part", -EOPNOTSUPP);
+
+ return 0;
+}
+
+static int distro_rauc_scan_boot_part(struct bootflow *bflow)
+{
+ struct blk_desc *desc;
+ struct distro_rauc_priv *priv;
+ char *boot_order;
+ const char **boot_order_list;
+ bool exists;
+ int ret;
+ int i;
+ int j;
+
+ desc = dev_get_uclass_plat(bflow->blk);
+
+ priv = bflow->bootmeth_priv;
+ if (!priv || !priv->slots)
+ return log_msg_ret("priv", -EINVAL);
+
+ boot_order = env_get("BOOT_ORDER");
+ boot_order_list = str_to_list(boot_order);
+ for (i = 0; boot_order_list[i]; i++) {
+ exists = false;
+ for (j = 0; script_names[j]; j++) {
+ const struct distro_rauc_slot *slot;
+
+ slot = get_slot(priv, boot_order_list[i]);
+ if (!slot)
+ return log_msg_ret("env", -ENOENT);
+ ret = fs_set_blk_dev_with_part(desc, slot->boot_part);
+ if (ret)
+ return log_msg_ret("blk", ret);
+ exists |= fs_exists(script_names[j]);
+ }
+ if (!exists)
+ return log_msg_ret("fs", -ENOENT);
+ }
+ str_free_list(boot_order_list);
+
+ return 0;
+}
+
+static int distro_rauc_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+ struct distro_rauc_priv *priv;
+ int ret;
+ char *slot;
+ int i;
+ char *partitions;
+ char *boot_order;
+ const char *default_boot_order;
+ const char **default_boot_order_list;
+ char *boot_order_copy;
+ char boot_left[BOOT_LEFT_LEN];
+ char *parts;
+
+ /* Get RAUC variables or set their default values */
+ boot_order = env_get("BOOT_ORDER");
+ if (!boot_order) {
+ log_debug("BOOT_ORDER did not exist yet, setting default value\n");
+ if (env_set("BOOT_ORDER", CONFIG_BOOTMETH_RAUC_BOOT_ORDER))
+ return log_msg_ret("env", -EPERM);
+ boot_order = CONFIG_BOOTMETH_RAUC_BOOT_ORDER;
+ }
+ default_boot_order = CONFIG_BOOTMETH_RAUC_BOOT_ORDER;
+ default_boot_order_list = str_to_list(default_boot_order);
+ for (i = 0; default_boot_order_list[i]; i++) {
+ sprintf(boot_left, "BOOT_%s_LEFT", default_boot_order_list[i]);
+ if (!env_get(boot_left)) {
+ log_debug("%s did not exist yet, setting default value\n",
+ boot_left);
+ if (env_set_ulong(boot_left, CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES))
+ return log_msg_ret("env", -EPERM);
+ }
+ }
+ str_free_list(default_boot_order_list);
+
+ priv = calloc(1, sizeof(struct distro_rauc_priv));
+ if (!priv)
+ return log_msg_ret("buf", -ENOMEM);
+ priv->slots = calloc(1, sizeof(struct distro_rauc_slot));
+
+ /* Copy default boot_order, so we can leave the original unmodified */
+ boot_order_copy = strdup(default_boot_order);
+ partitions = strdup(CONFIG_BOOTMETH_RAUC_PARTITIONS);
+
+ for (i = 1;
+ (parts = strsep(&partitions, " ")) &&
+ (slot = strsep(&boot_order_copy, " "));
+ i++) {
+ struct distro_rauc_slot *s;
+
+ s = calloc(1, sizeof(struct distro_rauc_slot));
+ s->name = strdup(slot);
+ s->boot_part = simple_strtoul(strsep(&parts, ","), NULL, 10);
+ s->root_part = simple_strtoul(strsep(&parts, ","), NULL, 10);
+ priv->slots = realloc(priv->slots, (i + 1) *
+ sizeof(struct distro_rauc_slot));
+ priv->slots[i - 1] = s;
+ priv->slots[i]->name = NULL;
+ }
+
+ bflow->bootmeth_priv = priv;
+
+ ret = distro_rauc_scan_boot_part(bflow);
+ if (ret < 0) {
+ for (i = 0; priv->slots[i]->name; i++) {
+ free(priv->slots[i]->name);
+ free(priv->slots[i]);
+ }
+ free(priv);
+ free(boot_order_copy);
+ bflow->bootmeth_priv = NULL;
+ return ret;
+ }
+
+ bflow->state = BOOTFLOWST_READY;
+
+ return 0;
+}
+
+static int distro_rauc_read_file(struct udevice *dev, struct bootflow *bflow,
+ const char *file_path, ulong addr,
+ enum bootflow_img_t type, ulong *sizep)
+{
+ /*
+ * Reading individual files is not supported since we only operate on
+ * whole MMC devices (because we require multiple partitions).
+ */
+ return log_msg_ret("Unsupported", -ENOSYS);
+}
+
+static int distro_rauc_load_boot_script(struct bootflow *bflow,
+ const struct distro_rauc_slot *slot)
+{
+ struct blk_desc *desc;
+ struct distro_rauc_priv *priv;
+ struct udevice *bootstd;
+ const char *const *prefixes;
+ int ret;
+ int i;
+ int j;
+
+ ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
+ if (ret)
+ return log_msg_ret("std", ret);
+ prefixes = bootstd_get_prefixes(bootstd);
+
+ desc = dev_get_uclass_plat(bflow->blk);
+ priv = bflow->bootmeth_priv;
+ if (!priv || !priv->slots)
+ return log_msg_ret("priv", -EINVAL);
+
+ bflow->part = slot->boot_part;
+ if (!bflow->part)
+ return log_msg_ret("part", -ENOENT);
+
+ ret = bootmeth_setup_fs(bflow, desc);
+ if (ret)
+ return log_msg_ret("set", ret);
+
+ for (i = 0; prefixes[i] && bflow->state != BOOTFLOWST_FILE; i++) {
+ for (j = 0; script_names[j] && bflow->state != BOOTFLOWST_FILE; j++) {
+ if (!bootmeth_try_file(bflow, desc, prefixes[i], script_names[j])) {
+ log_debug("Found file '%s%s' in %s.part_%x\n",
+ prefixes[i], script_names[j],
+ bflow->dev->name, bflow->part);
+ bflow->subdir = strdup(prefixes[i]);
+ }
+ }
+ }
+ if (bflow->state != BOOTFLOWST_FILE)
+ return log_msg_ret("file", -ENOENT);
+
+ ret = bootmeth_alloc_file(bflow, 0x10000, ARCH_DMA_MINALIGN,
+ (enum bootflow_img_t)IH_TYPE_SCRIPT);
+ if (ret)
+ return log_msg_ret("read", ret);
+
+ return 0;
+}
+
+static int find_active_slot(char **slot_name, ulong *slot_tries)
+{
+ ulong tries;
+ char boot_left[BOOT_LEFT_LEN];
+ char *boot_order;
+ const char **boot_order_list;
+ bool slot_found = false;
+ int ret;
+ int i;
+
+ boot_order = env_get("BOOT_ORDER");
+ if (!boot_order)
+ return log_msg_ret("env", -ENOENT);
+ boot_order_list = str_to_list(boot_order);
+ for (i = 0; boot_order_list[i] && !slot_found; i++) {
+ sprintf(boot_left, "BOOT_%s_LEFT", boot_order_list[i]);
+ tries = env_get_ulong(boot_left, 10, ULONG_MAX);
+ if (tries == ULONG_MAX)
+ return log_msg_ret("env", -ENOENT);
+
+ if (tries) {
+ ret = env_set_ulong(boot_left, tries - 1);
+ if (ret)
+ return log_msg_ret("env", ret);
+ *slot_name = strdup(boot_order_list[i]);
+ *slot_tries = tries;
+ slot_found = true;
+ }
+ }
+ str_free_list(boot_order_list);
+
+ if (!slot_found) {
+ if (IS_ENABLED(CONFIG_BOOTMETH_RAUC_RESET_ALL_ZERO_TRIES)) {
+ log_warning("WARNING: No valid slot found\n");
+ log_info("INFO: Resetting boot order and all slot tries\n");
+ boot_order_list = str_to_list(CONFIG_BOOTMETH_RAUC_BOOT_ORDER);
+ for (i = 0; boot_order_list[i]; i++) {
+ sprintf(boot_left, "BOOT_%s_LEFT", boot_order_list[i]);
+ ret = env_set_ulong(boot_left, CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES);
+ if (ret)
+ return log_msg_ret("env", ret);
+ }
+ str_free_list(boot_order_list);
+ ret = env_save();
+ if (ret)
+ return log_msg_ret("env", ret);
+ do_reset(NULL, 0, 0, NULL);
+ }
+ log_err("ERROR: No valid slot found\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int distro_rauc_boot(struct udevice *dev, struct bootflow *bflow)
+{
+ struct blk_desc *desc;
+ struct distro_rauc_priv *priv;
+ const struct distro_rauc_slot *slot;
+ char *boot_order;
+ const char **boot_order_list;
+ char *active_slot;
+ ulong active_slot_tries;
+ char raucargs[64];
+ char boot_left[BOOT_LEFT_LEN];
+ ulong addr;
+ int ret = 0;
+ int i;
+
+ desc = dev_get_uclass_plat(bflow->blk);
+ if (desc->uclass_id != UCLASS_MMC)
+ return log_msg_ret("blk", -EINVAL);
+ priv = bflow->bootmeth_priv;
+
+ /* Device info variables */
+ ret = env_set("devtype", blk_get_devtype(bflow->blk));
+ if (ret)
+ return log_msg_ret("env", ret);
+
+ ret = env_set_hex("devnum", desc->devnum);
+ if (ret)
+ return log_msg_ret("env", ret);
+
+ /* Find active, valid slot */
+ ret = find_active_slot(&active_slot, &active_slot_tries);
+ if (ret)
+ return log_msg_ret("env", ret);
+
+ /* Kernel command line arguments */
+ sprintf(raucargs, "rauc.slot=%s", active_slot);
+ ret = env_set("raucargs", raucargs);
+ if (ret)
+ return log_msg_ret("env", ret);
+
+ /* Active slot info */
+ slot = get_slot(priv, active_slot);
+ if (!slot)
+ return log_msg_ret("env", -ENOENT);
+ ret = env_set_hex("distro_bootpart", slot->boot_part);
+ if (ret)
+ return log_msg_ret("env", ret);
+ ret = env_set_hex("distro_rootpart", slot->root_part);
+ if (ret)
+ return log_msg_ret("env", ret);
+ ret = env_save();
+ if (ret)
+ return log_msg_ret("env", ret);
+
+ /* Load distro boot script */
+ ret = distro_rauc_load_boot_script(bflow, slot);
+ if (ret)
+ return log_msg_ret("load", ret);
+
+ log_info("INFO: Booting slot %s, %lu of %d tries left\n",
+ active_slot, active_slot_tries, CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES);
+
+ log_debug("devtype: %s\n", env_get("devtype"));
+ log_debug("devnum: %s\n", env_get("devnum"));
+ log_debug("distro_bootpart: %s\n", env_get("distro_bootpart"));
+ log_debug("distro_rootpart: %s\n", env_get("distro_rootpart"));
+ log_debug("raucargs: %s\n", env_get("raucargs"));
+ boot_order = env_get("BOOT_ORDER");
+ if (!boot_order)
+ return log_msg_ret("env", -EPERM);
+ log_debug("BOOT_ORDER: %s\n", boot_order);
+ boot_order_list = str_to_list(boot_order);
+ for (i = 0; boot_order_list[i]; i++) {
+ sprintf(boot_left, "BOOT_%s_LEFT", boot_order_list[i]);
+ log_debug("%s: %s\n", boot_left, env_get(boot_left));
+ }
+ str_free_list(boot_order_list);
+
+ /* Run distro boot script */
+ addr = map_to_sysmem(bflow->buf);
+ ret = cmd_source_script(addr, NULL, NULL);
+ if (ret)
+ return log_msg_ret("boot", ret);
+
+ return 0;
+}
+
+static int distro_rauc_bootmeth_bind(struct udevice *dev)
+{
+ struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+ plat->desc = "RAUC distro boot from MMC";
+ plat->flags = BOOTMETHF_GLOBAL;
+
+ return 0;
+}
+
+static struct bootmeth_ops distro_rauc_bootmeth_ops = {
+ .check = distro_rauc_check,
+ .read_bootflow = distro_rauc_read_bootflow,
+ .read_file = distro_rauc_read_file,
+ .boot = distro_rauc_boot,
+};
+
+static const struct udevice_id distro_rauc_bootmeth_ids[] = {
+ { .compatible = "u-boot,distro-rauc" },
+ { }
+};
+
+U_BOOT_DRIVER(bootmeth_rauc) = {
+ .name = "bootmeth_rauc",
+ .id = UCLASS_BOOTMETH,
+ .of_match = distro_rauc_bootmeth_ids,
+ .ops = &distro_rauc_bootmeth_ops,
+ .bind = distro_rauc_bootmeth_bind,
+};
diff --git a/boot/cedit.c b/boot/cedit.c
index d69290c172e..56dc7c6af15 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -81,6 +81,8 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
scene_obj_set_pos(scn, obj->id, 50, y);
@@ -100,19 +102,16 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
return 0;
}
-int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
+int cedit_prepare(struct expo *exp, struct udevice *vid_dev,
struct scene **scnp)
{
+ struct udevice *dev = vid_dev;
struct video_priv *vid_priv;
- struct udevice *dev;
struct scene *scn;
uint scene_id;
int ret;
/* For now we only support a video console */
- ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
- if (ret)
- return log_msg_ret("vid", ret);
ret = expo_set_display(exp, dev);
if (ret)
return log_msg_ret("dis", ret);
@@ -127,6 +126,7 @@ int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
return log_msg_ret("sid", ret);
exp->popup = true;
+ exp->show_highlight = true;
/* This is not supported for now */
if (0)
@@ -143,104 +143,96 @@ int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
if (ret)
return log_msg_ret("dim", ret);
- *vid_privp = vid_priv;
*scnp = scn;
return scene_id;
}
+int cedit_do_action(struct expo *exp, struct scene *scn,
+ struct video_priv *vid_priv, struct expo_action *act)
+{
+ int ret;
+
+ switch (act->type) {
+ case EXPOACT_NONE:
+ return -EAGAIN;
+ case EXPOACT_POINT_ITEM:
+ ret = scene_menu_select_item(scn, scn->highlight_id,
+ act->select.id);
+ if (ret)
+ return log_msg_ret("cdp", ret);
+ break;
+ case EXPOACT_POINT_OBJ:
+ scene_set_highlight_id(scn, act->select.id);
+ cedit_arange(exp, vid_priv, scn->id);
+ break;
+ case EXPOACT_OPEN:
+ scene_set_open(scn, act->select.id, true);
+ cedit_arange(exp, vid_priv, scn->id);
+ switch (scn->highlight_id) {
+ case EXPOID_SAVE:
+ exp->done = true;
+ exp->save = true;
+ break;
+ case EXPOID_DISCARD:
+ exp->done = true;
+ break;
+ }
+ break;
+ case EXPOACT_CLOSE:
+ scene_set_open(scn, act->select.id, false);
+ cedit_arange(exp, vid_priv, scn->id);
+ break;
+ case EXPOACT_SELECT:
+ scene_set_open(scn, scn->highlight_id, false);
+ cedit_arange(exp, vid_priv, scn->id);
+ break;
+ case EXPOACT_QUIT:
+ log_debug("quitting\n");
+ exp->done = true;
+ break;
+ }
+
+ return 0;
+}
+
int cedit_run(struct expo *exp)
{
- 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, save;
+ uint scene_id;
int ret;
- cli_ch_init(cch);
- ret = cedit_prepare(exp, &vid_priv, &scn);
+ ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
+ if (ret)
+ return log_msg_ret("vid", ret);
+ vid_priv = dev_get_uclass_priv(dev);
+
+ ret = cedit_prepare(exp, dev, &scn);
if (ret < 0)
return log_msg_ret("prep", ret);
scene_id = ret;
- done = false;
- save = false;
+ exp->done = false;
+ exp->save = false;
do {
struct expo_action act;
- int ichar, key;
ret = expo_render(exp);
if (ret)
- break;
+ return log_msg_ret("cer", ret);
- ichar = cli_ch_process(cch, 0);
- if (!ichar) {
- while (!ichar && !tstc()) {
- schedule();
- mdelay(2);
- ichar = cli_ch_process(cch, -ETIMEDOUT);
- }
- if (!ichar) {
- ichar = getchar();
- ichar = cli_ch_process(cch, ichar);
- }
- }
-
- key = 0;
- if (ichar) {
- key = bootmenu_conv_key(ichar);
- if (key == BKEY_NONE || key >= BKEY_FIRST_EXTRA)
- key = ichar;
- }
- if (!key)
- continue;
-
- ret = expo_send_key(exp, key);
- if (ret)
- break;
-
- ret = expo_action_get(exp, &act);
- if (!ret) {
- switch (act.type) {
- case EXPOACT_POINT_OBJ:
- scene_set_highlight_id(scn, act.select.id);
- cedit_arange(exp, vid_priv, scene_id);
- break;
- case EXPOACT_OPEN:
- scene_set_open(scn, act.select.id, true);
- cedit_arange(exp, vid_priv, scene_id);
- switch (scn->highlight_id) {
- case EXPOID_SAVE:
- done = true;
- save = true;
- break;
- case EXPOID_DISCARD:
- done = true;
- break;
- }
- break;
- case EXPOACT_CLOSE:
- scene_set_open(scn, act.select.id, false);
- cedit_arange(exp, vid_priv, scene_id);
- break;
- case EXPOACT_SELECT:
- scene_set_open(scn, scn->highlight_id, false);
- cedit_arange(exp, vid_priv, scene_id);
- break;
- case EXPOACT_QUIT:
- log_debug("quitting\n");
- done = true;
- break;
- default:
- break;
- }
- }
- } while (!done);
+ ret = expo_poll(exp, &act);
+ if (!ret)
+ cedit_do_action(exp, scn, vid_priv, &act);
+ else if (ret != -EAGAIN)
+ return log_msg_ret("cep", ret);
+ } while (!exp->done);
if (ret)
return log_msg_ret("end", ret);
- if (!save)
+ if (!exp->save)
return -EACCES;
return 0;
@@ -286,7 +278,7 @@ static int get_cur_menuitem_text(const struct scene_obj_menu *menu,
if (!txt)
return log_msg_ret("txt", -ENOENT);
- str = expo_get_str(scn->expo, txt->str_id);
+ str = expo_get_str(scn->expo, txt->gen.str_id);
if (!str)
return log_msg_ret("str", -ENOENT);
*strp = str;
@@ -396,6 +388,8 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_TEXTLINE: {
const struct scene_obj_textline *tline;
@@ -449,8 +443,7 @@ int cedit_write_settings(struct expo *exp, struct abuf *buf)
void *fdt;
int ret;
- abuf_init(buf);
- if (!abuf_realloc(buf, CEDIT_SIZE_INC))
+ if (!abuf_init_size(buf, CEDIT_SIZE_INC))
return log_msg_ret("buf", -ENOMEM);
fdt = abuf_data(buf);
@@ -496,6 +489,8 @@ static int h_read_settings(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_TEXTLINE: {
const struct scene_obj_textline *tline;
@@ -567,6 +562,8 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
menu = (struct scene_obj_menu *)obj;
@@ -650,6 +647,8 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
menu = (struct scene_obj_menu *)obj;
diff --git a/boot/expo.c b/boot/expo.c
index 8ce645e5a8f..94413acd381 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -10,8 +10,12 @@
#include <dm.h>
#include <expo.h>
+#include <log.h>
#include <malloc.h>
+#include <menu.h>
#include <video.h>
+#include <watchdog.h>
+#include <linux/delay.h>
#include "scene_internal.h"
int expo_new(const char *name, void *priv, struct expo **expp)
@@ -30,6 +34,7 @@ int expo_new(const char *name, void *priv, struct expo **expp)
INIT_LIST_HEAD(&exp->scene_head);
INIT_LIST_HEAD(&exp->str_head);
exp->next_id = EXPOID_BASE_ID;
+ cli_ch_init(&exp->cch);
*expp = exp;
@@ -81,7 +86,7 @@ int expo_str(struct expo *exp, const char *name, uint id, const char *str)
return log_msg_ret("obj", -ENOMEM);
estr->id = resolve_id(exp, id);
- estr->str = str;
+ abuf_init_const(&estr->buf, str, strlen(str) + 1);
list_add_tail(&estr->sibling, &exp->str_head);
return estr->id;
@@ -93,12 +98,33 @@ const char *expo_get_str(struct expo *exp, uint id)
list_for_each_entry(estr, &exp->str_head, sibling) {
if (estr->id == id)
- return estr->str;
+ return estr->buf.data;
}
return NULL;
}
+int expo_edit_str(struct expo *exp, uint id, struct abuf *orig,
+ struct abuf **copyp)
+{
+ struct expo_string *estr;
+ struct abuf old;
+
+ list_for_each_entry(estr, &exp->str_head, sibling) {
+ if (estr->id == id) {
+ old = estr->buf;
+ if (!abuf_copy(&old, &estr->buf))
+ return -ENOMEM;
+ *copyp = &estr->buf;
+ if (orig)
+ *orig = old;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
int expo_set_display(struct expo *exp, struct udevice *dev)
{
struct udevice *cons;
@@ -251,6 +277,7 @@ int expo_apply_theme(struct expo *exp, ofnode node)
{
struct scene *scn;
struct expo_theme *theme = &exp->theme;
+ bool white_on_black;
int ret;
log_debug("Applying theme %s\n", ofnode_get_name(node));
@@ -261,6 +288,9 @@ int expo_apply_theme(struct expo *exp, ofnode node)
ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y);
ofnode_read_u32(node, "menu-title-margin-x",
&theme->menu_title_margin_x);
+ white_on_black = ofnode_read_bool(node, "white-on-black");
+ if (exp->display)
+ video_set_white_on_black(exp->display, white_on_black);
list_for_each_entry(scn, &exp->scene_head, sibling) {
ret = scene_apply_theme(scn, theme);
@@ -285,3 +315,41 @@ int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
return 0;
}
+
+int expo_poll(struct expo *exp, struct expo_action *act)
+{
+ int ichar, key, ret;
+
+ ichar = cli_ch_process(&exp->cch, 0);
+ if (!ichar) {
+ int i;
+
+ for (i = 0; i < 10 && !ichar && !tstc(); i++) {
+ schedule();
+ mdelay(2);
+ ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
+ }
+ while (!ichar && tstc()) {
+ ichar = getchar();
+ ichar = cli_ch_process(&exp->cch, ichar);
+ }
+ }
+
+ key = 0;
+ if (ichar) {
+ key = bootmenu_conv_key(ichar);
+ if (key == BKEY_NONE || key >= BKEY_FIRST_EXTRA)
+ key = ichar;
+ }
+ if (!key)
+ return -EAGAIN;
+
+ ret = expo_send_key(exp, key);
+ if (ret)
+ return log_msg_ret("epk", ret);
+ ret = expo_action_get(exp, act);
+ if (ret)
+ return log_msg_ret("eag", ret);
+
+ return 0;
+}
diff --git a/boot/fdt_support.c b/boot/fdt_support.c
index 92f2f534ee0..b7331bb76b3 100644
--- a/boot/fdt_support.c
+++ b/boot/fdt_support.c
@@ -224,15 +224,24 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
int is_u64;
uint64_t addr, size;
- /* just return if the size of initrd is zero */
- if (initrd_start == initrd_end)
- return 0;
-
/* find or create "/chosen" node. */
nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
if (nodeoffset < 0)
return nodeoffset;
+ /*
+ * Although we didn't setup an initrd, there could be a stale
+ * initrd setting from the previous boot firmware in the live
+ * device tree. So, make sure there is no setting left if we
+ * don't want an initrd.
+ */
+ if (initrd_start == initrd_end) {
+ fdt_delprop(fdt, nodeoffset, "linux,initrd-start");
+ fdt_delprop(fdt, nodeoffset, "linux,initrd-end");
+
+ return 0;
+ }
+
total = fdt_num_mem_rsv(fdt);
/*
diff --git a/boot/image-android.c b/boot/image-android.c
index 459cdb8456c..1cd2060bb3f 100644
--- a/boot/image-android.c
+++ b/boot/image-android.c
@@ -268,7 +268,8 @@ static ulong android_image_get_kernel_addr(struct andr_image_data *img_data,
*
* Otherwise, we will return the actual value set by the user.
*/
- if (img_data->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR) {
+ if (img_data->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR ||
+ IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE_IGNORE_BLOB_ADDR)) {
if (comp == IH_COMP_NONE)
return img_data->kernel_ptr;
return env_get_ulong("kernel_addr_r", 16, 0);
@@ -464,7 +465,8 @@ int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img,
*/
if (img_data.header_version > 2) {
/* Ramdisk can't be used in-place, copy it to ramdisk_addr_r */
- if (img_data.ramdisk_addr == ANDROID_IMAGE_DEFAULT_RAMDISK_ADDR) {
+ if (img_data.ramdisk_addr == ANDROID_IMAGE_DEFAULT_RAMDISK_ADDR ||
+ IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE_IGNORE_BLOB_ADDR)) {
ramdisk_ptr = env_get_ulong("ramdisk_addr_r", 16, 0);
if (!ramdisk_ptr) {
printf("Invalid ramdisk_addr_r to copy ramdisk into\n");
@@ -489,7 +491,8 @@ int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img,
/* Ramdisk can be used in-place, use current ptr */
if (img_data.ramdisk_addr == 0 ||
img_data.ramdisk_addr == ANDROID_IMAGE_DEFAULT_RAMDISK_ADDR ||
- img_data.ramdisk_addr == img_data.kernel_addr) {
+ img_data.ramdisk_addr == img_data.kernel_addr ||
+ IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE_IGNORE_BLOB_ADDR)) {
*rd_data = img_data.ramdisk_ptr;
} else {
ramdisk_ptr = img_data.ramdisk_addr;
@@ -677,7 +680,7 @@ bool android_image_get_dtb_by_index(ulong hdr_addr, ulong vendor_boot_img,
{
struct andr_image_data img_data;
const struct andr_boot_img_hdr_v0 *hdr;
- const struct andr_vnd_boot_img_hdr *vhdr;
+ const struct andr_vnd_boot_img_hdr *vhdr = NULL;
hdr = map_sysmem(hdr_addr, sizeof(*hdr));
if (vendor_boot_img != -1)
diff --git a/boot/image-board.c b/boot/image-board.c
index 514f8e63f9c..005d60caf5c 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -16,6 +16,7 @@
#include <fpga.h>
#include <image.h>
#include <init.h>
+#include <lmb.h>
#include <log.h>
#include <mapmem.h>
#include <rtc.h>
@@ -538,6 +539,7 @@ int boot_get_ramdisk(char const *select, struct bootm_headers *images,
int boot_ramdisk_high(ulong rd_data, ulong rd_len, ulong *initrd_start,
ulong *initrd_end)
{
+ int err;
char *s;
phys_addr_t initrd_high;
int initrd_copy_to_ram = 1;
@@ -559,25 +561,30 @@ int boot_ramdisk_high(ulong rd_data, ulong rd_len, ulong *initrd_start,
if (rd_data) {
if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */
+ phys_addr_t initrd_addr;
+
debug(" in-place initrd\n");
*initrd_start = rd_data;
*initrd_end = rd_data + rd_len;
- lmb_reserve(rd_data, rd_len, LMB_NONE);
+ initrd_addr = (phys_addr_t)rd_data;
+ err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &initrd_addr,
+ rd_len, LMB_NONE);
+ if (err) {
+ puts("in-place initrd alloc failed\n");
+ goto error;
+ }
} else {
- if (initrd_high)
- *initrd_start =
- (ulong)lmb_alloc_base(rd_len,
- 0x1000,
- initrd_high,
- LMB_NONE);
- else
- *initrd_start = (ulong)lmb_alloc(rd_len,
- 0x1000);
+ enum lmb_mem_type type = initrd_high ?
+ LMB_MEM_ALLOC_MAX : LMB_MEM_ALLOC_ANY;
- if (*initrd_start == 0) {
+ err = lmb_alloc_mem(type, 0x1000, &initrd_high, rd_len,
+ LMB_NONE);
+ if (err) {
puts("ramdisk - allocation error\n");
goto error;
}
+
+ *initrd_start = (ulong)initrd_high;
bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);
*initrd_end = *initrd_start + rd_len;
@@ -828,9 +835,10 @@ int boot_get_loadable(struct bootm_headers *images)
*/
int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
{
- int barg;
+ int barg, err;
char *cmdline;
char *s;
+ phys_addr_t addr;
/*
* Help the compiler detect that this function is only called when
@@ -840,12 +848,14 @@ int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
return 0;
barg = IF_ENABLED_INT(CONFIG_SYS_BOOT_GET_CMDLINE, CONFIG_SYS_BARGSIZE);
- cmdline = (char *)(ulong)lmb_alloc_base(barg, 0xf,
- env_get_bootm_mapsize() + env_get_bootm_low(),
- LMB_NONE);
- if (!cmdline)
+ addr = env_get_bootm_mapsize() + env_get_bootm_low();
+
+ err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0xf, &addr, barg, LMB_NONE);
+ if (err)
return -1;
+ cmdline = (char *)(uintptr_t)addr;
+
s = env_get("bootargs");
if (!s)
s = "";
@@ -874,14 +884,16 @@ int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
*/
int boot_get_kbd(struct bd_info **kbd)
{
- *kbd = (struct bd_info *)(ulong)lmb_alloc_base(sizeof(struct bd_info),
- 0xf,
- env_get_bootm_mapsize() +
- env_get_bootm_low(),
- LMB_NONE);
- if (!*kbd)
+ int err;
+ phys_addr_t addr;
+
+ addr = env_get_bootm_mapsize() + env_get_bootm_low();
+ err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0xf, &addr,
+ sizeof(struct bd_info), LMB_NONE);
+ if (err)
return -1;
+ *kbd = (struct bd_info *)(uintptr_t)addr;
**kbd = *gd->bd;
debug("## kernel board info at 0x%08lx\n", (ulong)*kbd);
diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index 8f718ad29f6..3f0ac54f76f 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -72,13 +72,15 @@ static const struct legacy_img_hdr *image_get_fdt(ulong fdt_addr)
static void boot_fdt_reserve_region(u64 addr, u64 size, u32 flags)
{
long ret;
+ phys_addr_t rsv_addr;
- ret = lmb_reserve(addr, size, flags);
+ rsv_addr = (phys_addr_t)addr;
+ ret = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &rsv_addr, size, flags);
if (!ret) {
debug(" reserving fdt memory region: addr=%llx size=%llx flags=%x\n",
(unsigned long long)addr,
(unsigned long long)size, flags);
- } else if (ret != -EEXIST) {
+ } else if (ret != -EEXIST && ret != -EINVAL) {
puts("ERROR: reserving fdt memory region failed ");
printf("(addr=%llx size=%llx flags=%x)\n",
(unsigned long long)addr,
@@ -155,7 +157,7 @@ void boot_fdt_add_mem_rsv_regions(void *fdt_blob)
*/
int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
{
- u64 start, size, usable, addr, low, mapsize;
+ u64 start, size, usable, low, mapsize;
void *fdt_blob = *of_flat_tree;
void *of_start = NULL;
char *fdt_high;
@@ -163,6 +165,7 @@ int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
int bank;
int err;
int disable_relocation = 0;
+ phys_addr_t addr;
/* nothing to do */
if (*of_size == 0)
@@ -180,23 +183,32 @@ int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
/* If fdt_high is set use it to select the relocation address */
fdt_high = env_get("fdt_high");
if (fdt_high) {
- ulong desired_addr = hextoul(fdt_high, NULL);
+ ulong high_addr = hextoul(fdt_high, NULL);
- if (desired_addr == ~0UL) {
+ if (high_addr == ~0UL) {
/* All ones means use fdt in place */
of_start = fdt_blob;
- lmb_reserve(map_to_sysmem(of_start), of_len, LMB_NONE);
- disable_relocation = 1;
- } else if (desired_addr) {
- addr = lmb_alloc_base(of_len, 0x1000, desired_addr,
- LMB_NONE);
- of_start = map_sysmem(addr, of_len);
- if (of_start == NULL) {
- puts("Failed using fdt_high value for Device Tree");
+ addr = map_to_sysmem(fdt_blob);
+ err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &addr,
+ of_len, LMB_NONE);
+ if (err) {
+ printf("Failed to reserve memory for fdt at %#llx\n",
+ (u64)addr);
goto error;
}
+
+ disable_relocation = 1;
} else {
- addr = lmb_alloc(of_len, 0x1000);
+ enum lmb_mem_type type = high_addr ?
+ LMB_MEM_ALLOC_MAX : LMB_MEM_ALLOC_ANY;
+
+ addr = high_addr;
+ err = lmb_alloc_mem(type, 0x1000, &addr, of_len,
+ LMB_NONE);
+ if (err) {
+ puts("Failed to allocate memory for Device Tree relocation\n");
+ goto error;
+ }
of_start = map_sysmem(addr, of_len);
}
} else {
@@ -218,11 +230,15 @@ int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
* for LMB allocation.
*/
usable = min(start + size, low + mapsize);
- addr = lmb_alloc_base(of_len, 0x1000, usable, LMB_NONE);
- of_start = map_sysmem(addr, of_len);
- /* Allocation succeeded, use this block. */
- if (of_start != NULL)
- break;
+ addr = usable;
+ err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0x1000,
+ &addr, of_len, LMB_NONE);
+ if (!err) {
+ of_start = map_sysmem(addr, of_len);
+ /* Allocation succeeded, use this block. */
+ if (of_start)
+ break;
+ }
/*
* Reduce the mapping size in the next bank
@@ -571,6 +587,7 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb)
{
ulong *initrd_start = &images->initrd_start;
ulong *initrd_end = &images->initrd_end;
+ bool skip_board_fixup = false;
int ret, fdt_ret, of_size;
if (IS_ENABLED(CONFIG_OF_ENV_SETUP)) {
@@ -621,18 +638,18 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb)
fdt_fixup_pstore(blob);
#endif
if (IS_ENABLED(CONFIG_OF_BOARD_SETUP)) {
- const char *skip_board_fixup;
+ skip_board_fixup = (env_get_ulong("skip_board_fixup", 10, 0) == 1);
- skip_board_fixup = env_get("skip_board_fixup");
- if (skip_board_fixup && ((int)simple_strtol(skip_board_fixup, NULL, 10) == 1)) {
- printf("skip board fdt fixup\n");
- } else {
- fdt_ret = ft_board_setup(blob, gd->bd);
- if (fdt_ret) {
- printf("ERROR: board-specific fdt fixup failed: %s\n",
- fdt_strerror(fdt_ret));
- goto err;
- }
+ if (skip_board_fixup)
+ printf("skip all board fdt fixup\n");
+ }
+
+ if (IS_ENABLED(CONFIG_OF_BOARD_SETUP) && !skip_board_fixup) {
+ fdt_ret = ft_board_setup(blob, gd->bd);
+ if (fdt_ret) {
+ printf("ERROR: board-specific fdt fixup failed: %s\n",
+ fdt_strerror(fdt_ret));
+ goto err;
}
}
if (IS_ENABLED(CONFIG_OF_SYSTEM_SETUP)) {
@@ -674,7 +691,7 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb)
/* Delete the old LMB reservation */
if (CONFIG_IS_ENABLED(LMB) && lmb)
- lmb_free(map_to_sysmem(blob), fdt_totalsize(blob));
+ lmb_free(map_to_sysmem(blob), fdt_totalsize(blob), LMB_NONE);
ret = fdt_shrink_to_minimum(blob, 0);
if (ret < 0)
@@ -682,13 +699,20 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb)
of_size = ret;
/* Create a new LMB reservation */
- if (CONFIG_IS_ENABLED(LMB) && lmb)
- lmb_reserve(map_to_sysmem(blob), of_size, LMB_NONE);
+ if (CONFIG_IS_ENABLED(LMB) && lmb) {
+ phys_addr_t fdt_addr;
+
+ fdt_addr = map_to_sysmem(blob);
+ ret = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &fdt_addr,
+ of_size, LMB_NONE);
+ if (ret) {
+ printf("Failed to reserve memory for the fdt at %#llx\n",
+ (u64)fdt_addr);
+ }
+ }
-#if defined(CONFIG_ARCH_KEYSTONE)
- if (IS_ENABLED(CONFIG_OF_BOARD_SETUP))
+ if (IS_ENABLED(CONFIG_OF_BOARD_SETUP_EXTENDED) && !skip_board_fixup)
ft_board_setup_ex(blob, gd->bd);
-#endif
return 0;
err:
diff --git a/boot/image-pre-load.c b/boot/image-pre-load.c
index adf3b341a20..2f851ebb28c 100644
--- a/boot/image-pre-load.c
+++ b/boot/image-pre-load.c
@@ -7,6 +7,7 @@
#include "mkimage.h"
#else
#include <asm/global_data.h>
+#include <env.h>
#include <mapmem.h>
DECLARE_GLOBAL_DATA_PTR;
#endif /* !USE_HOSTCC*/
diff --git a/boot/image.c b/boot/image.c
index 139c5bd035a..abac2c7034b 100644
--- a/boot/image.c
+++ b/boot/image.c
@@ -184,6 +184,7 @@ static const table_entry_t uimage_type[] = {
{ IH_TYPE_RENESAS_SPKG, "spkgimage", "Renesas SPKG Image" },
{ IH_TYPE_STARFIVE_SPL, "sfspl", "StarFive SPL Image" },
{ IH_TYPE_TFA_BL31, "tfa-bl31", "TFA BL31 Image", },
+ { IH_TYPE_STM32IMAGE_V2, "stm32imagev2", "STMicroelectronics STM32 Image V2.0" },
{ -1, "", "", },
};
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 82f217aaf86..eb4d7723481 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -1348,7 +1348,7 @@ static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long bas
case T_ONTIMEOUT:
err = parse_sliteral(&p, &label_name);
- if (label_name) {
+ if (err >= 0 && label_name) {
if (cfg->default_label)
free(cfg->default_label);
@@ -1360,7 +1360,7 @@ static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long bas
case T_FALLBACK:
err = parse_sliteral(&p, &label_name);
- if (label_name) {
+ if (err >= 0 && label_name) {
if (cfg->fallback_label)
free(cfg->fallback_label);
diff --git a/boot/scene.c b/boot/scene.c
index fb82ffe768c..fa8f540bfb0 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -8,6 +8,7 @@
#define LOG_CATEGORY LOGC_EXPO
+#include <alist.h>
#include <dm.h>
#include <expo.h>
#include <malloc.h>
@@ -31,8 +32,7 @@ int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp)
return log_msg_ret("name", -ENOMEM);
}
- abuf_init(&scn->buf);
- if (!abuf_realloc(&scn->buf, EXPO_MAX_CHARS + 1)) {
+ if (!abuf_init_size(&scn->buf, EXPO_MAX_CHARS + 1)) {
free(scn->name);
free(scn);
return log_msg_ret("buf", -ENOMEM);
@@ -143,6 +143,32 @@ int scene_img(struct scene *scn, const char *name, uint id, char *data,
return img->obj.id;
}
+int scene_txt_generic_init(struct expo *exp, struct scene_txt_generic *gen,
+ const char *name, uint str_id, const char *str)
+{
+ int ret;
+
+ if (str) {
+ ret = expo_str(exp, name, str_id, str);
+ if (ret < 0)
+ return log_msg_ret("str", ret);
+ if (str_id && ret != str_id)
+ return log_msg_ret("id", -EEXIST);
+ str_id = ret;
+ } else {
+ ret = resolve_id(exp, str_id);
+ if (ret < 0)
+ return log_msg_ret("nst", ret);
+ if (str_id && ret != str_id)
+ return log_msg_ret("nid", -EEXIST);
+ }
+
+ gen->str_id = str_id;
+ alist_init_struct(&gen->lines, struct vidconsole_mline);
+
+ return 0;
+}
+
int scene_txt(struct scene *scn, const char *name, uint id, uint str_id,
struct scene_obj_txt **txtp)
{
@@ -155,8 +181,9 @@ int scene_txt(struct scene *scn, const char *name, uint id, uint str_id,
if (ret < 0)
return log_msg_ret("obj", ret);
- txt->str_id = str_id;
-
+ ret = scene_txt_generic_init(scn->expo, &txt->gen, name, str_id, NULL);
+ if (ret)
+ return log_msg_ret("stg", ret);
if (txtp)
*txtp = txt;
@@ -169,27 +196,41 @@ int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id,
struct scene_obj_txt *txt;
int ret;
- ret = expo_str(scn->expo, name, str_id, str);
- if (ret < 0)
- return log_msg_ret("str", ret);
- if (str_id && ret != str_id)
- return log_msg_ret("id", -EEXIST);
- str_id = ret;
-
ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXT,
sizeof(struct scene_obj_txt),
(struct scene_obj **)&txt);
if (ret < 0)
return log_msg_ret("obj", ret);
- txt->str_id = str_id;
-
+ ret = scene_txt_generic_init(scn->expo, &txt->gen, name, str_id, str);
+ if (ret)
+ return log_msg_ret("tsg", ret);
if (txtp)
*txtp = txt;
return txt->obj.id;
}
+int scene_box(struct scene *scn, const char *name, uint id, uint width,
+ struct scene_obj_box **boxp)
+{
+ struct scene_obj_box *box;
+ int ret;
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_BOX,
+ sizeof(struct scene_obj_box),
+ (struct scene_obj **)&box);
+ if (ret < 0)
+ return log_msg_ret("obj", ret);
+
+ box->width = width;
+
+ if (boxp)
+ *boxp = box;
+
+ return box->obj.id;
+}
+
int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
uint font_size)
{
@@ -198,8 +239,8 @@ int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
if (!txt)
return log_msg_ret("find", -ENOENT);
- txt->font_name = font_name;
- txt->font_size = font_size;
+ txt->gen.font_name = font_name;
+ txt->gen.font_size = font_size;
return 0;
}
@@ -207,12 +248,17 @@ int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
{
struct scene_obj *obj;
+ int w, h;
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("find", -ENOENT);
- obj->dim.x = x;
- obj->dim.y = y;
+ w = obj->bbox.x1 - obj->bbox.x0;
+ h = obj->bbox.y1 - obj->bbox.y0;
+ obj->bbox.x0 = x;
+ obj->bbox.y0 = y;
+ obj->bbox.x1 = obj->bbox.x0 + w;
+ obj->bbox.y1 = obj->bbox.y0 + h;
return 0;
}
@@ -224,8 +270,62 @@ int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("find", -ENOENT);
- obj->dim.w = w;
- obj->dim.h = h;
+ obj->bbox.x1 = obj->bbox.x0 + w;
+ obj->bbox.y1 = obj->bbox.y0 + h;
+ obj->flags |= SCENEOF_SIZE_VALID;
+
+ return 0;
+}
+
+int scene_obj_set_width(struct scene *scn, uint id, int w)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->bbox.x1 = obj->bbox.x0 + w;
+
+ return 0;
+}
+
+int scene_obj_set_bbox(struct scene *scn, uint id, int x0, int y0, int x1,
+ int y1)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->bbox.x0 = x0;
+ obj->bbox.y0 = y0;
+ obj->bbox.x1 = x1;
+ obj->bbox.y1 = y1;
+ obj->flags |= SCENEOF_SIZE_VALID;
+
+ return 0;
+}
+
+int scene_obj_set_halign(struct scene *scn, uint id, enum scene_obj_align aln)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("osh", -ENOENT);
+ obj->horiz = aln;
+
+ return 0;
+}
+
+int scene_obj_set_valign(struct scene *scn, uint id, enum scene_obj_align aln)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("osv", -ENOENT);
+ obj->vert = aln;
return 0;
}
@@ -255,6 +355,49 @@ int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set)
return 0;
}
+static void handle_alignment(enum scene_obj_align horiz,
+ enum scene_obj_align vert,
+ struct scene_obj_bbox *bbox,
+ struct scene_obj_dims *dims,
+ int xsize, int ysize,
+ struct scene_obj_offset *offset)
+{
+ int width, height;
+
+ if (bbox->x1 == SCENEOB_DISPLAY_MAX)
+ bbox->x1 = xsize ?: 1280;
+ if (bbox->y1 == SCENEOB_DISPLAY_MAX)
+ bbox->y1 = ysize ?: 1024;
+
+ width = bbox->x1 - bbox->x0;
+ height = bbox->y1 - bbox->y0;
+
+ switch (horiz) {
+ case SCENEOA_CENTRE:
+ offset->xofs = (width - dims->x) / 2;
+ break;
+ case SCENEOA_RIGHT:
+ offset->xofs = width - dims->x;
+ break;
+ case SCENEOA_LEFT:
+ offset->xofs = 0;
+ break;
+ }
+
+ switch (vert) {
+ case SCENEOA_CENTRE:
+ offset->yofs = (height - dims->y) / 2;
+ break;
+ case SCENEOA_BOTTOM:
+ offset->yofs = height - dims->y;
+ break;
+ case SCENEOA_TOP:
+ default:
+ offset->yofs = 0;
+ break;
+ }
+}
+
int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
{
struct scene_obj *obj;
@@ -267,6 +410,7 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
case SCENEOBJT_NONE:
case SCENEOBJT_MENU:
case SCENEOBJT_TEXTLINE:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_IMAGE: {
struct scene_obj_img *img = (struct scene_obj_img *)obj;
@@ -278,14 +422,20 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
*widthp = width;
return height;
}
- case SCENEOBJT_TEXT: {
- struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
+ case SCENEOBJT_TEXT:
+ case SCENEOBJT_TEXTEDIT: {
+ struct scene_txt_generic *gen;
struct expo *exp = scn->expo;
struct vidconsole_bbox bbox;
+ int len, ret, limit;
const char *str;
- int len, ret;
- str = expo_get_str(exp, txt->str_id);
+ if (obj->type == SCENEOBJT_TEXT)
+ gen = &((struct scene_obj_txt *)obj)->gen;
+ else
+ gen = &((struct scene_obj_txtedit *)obj)->gen;
+
+ str = expo_get_str(exp, gen->str_id);
if (!str)
return log_msg_ret("str", -ENOENT);
len = strlen(str);
@@ -297,8 +447,12 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
return 16;
}
- ret = vidconsole_measure(scn->expo->cons, txt->font_name,
- txt->font_size, str, -1, &bbox, NULL);
+ limit = obj->flags & SCENEOF_SIZE_VALID ?
+ obj->bbox.x1 - obj->bbox.x0 : -1;
+
+ ret = vidconsole_measure(scn->expo->cons, gen->font_name,
+ gen->font_size, str, limit, &bbox,
+ &gen->lines);
if (ret)
return log_msg_ret("mea", ret);
if (widthp)
@@ -317,12 +471,14 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
* @obj: Object to render
* @box_only: true to show a box around the object, but keep the normal
* background colour inside
+ * @cur_item: true to render the background only for the current menu item
*/
-static void scene_render_background(struct scene_obj *obj, bool box_only)
+static void scene_render_background(struct scene_obj *obj, bool box_only,
+ bool cur_item)
{
+ struct vidconsole_bbox bbox[SCENEBB_count], *sel;
struct expo *exp = obj->scene->expo;
const struct expo_theme *theme = &exp->theme;
- struct vidconsole_bbox bbox, label_bbox;
struct udevice *dev = exp->display;
struct video_priv *vid_priv;
struct udevice *cons = exp->cons;
@@ -341,24 +497,113 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
}
/* see if this object wants to render a background */
- if (scene_obj_calc_bbox(obj, &bbox, &label_bbox))
+ if (scene_obj_calc_bbox(obj, bbox))
+ return;
+
+ sel = cur_item ? &bbox[SCENEBB_curitem] : &bbox[SCENEBB_label];
+ if (!sel->valid)
return;
vidconsole_push_colour(cons, fore, back, &old);
- video_fill_part(dev, label_bbox.x0 - inset, label_bbox.y0 - inset,
- label_bbox.x1 + inset, label_bbox.y1 + inset,
+ video_fill_part(dev, sel->x0 - inset, sel->y0 - inset,
+ sel->x1 + inset, sel->y1 + inset,
vid_priv->colour_fg);
vidconsole_pop_colour(cons, &old);
if (box_only) {
- video_fill_part(dev, label_bbox.x0, label_bbox.y0,
- label_bbox.x1, label_bbox.y1,
+ video_fill_part(dev, sel->x0, sel->y0, sel->x1, sel->y1,
vid_priv->colour_bg);
}
}
+static int scene_txt_render(struct expo *exp, struct udevice *dev,
+ struct udevice *cons, struct scene_obj *obj,
+ struct scene_txt_generic *gen, int x, int y,
+ int menu_inset)
+{
+ const struct vidconsole_mline *mline, *last;
+ struct video_priv *vid_priv;
+ struct vidconsole_colour old;
+ enum colour_idx fore, back;
+ struct scene_obj_dims dims;
+ struct scene_obj_bbox bbox;
+ const char *str;
+ int ret;
+
+ if (!cons)
+ return -ENOTSUPP;
+
+ if (gen->font_name || gen->font_size) {
+ ret = vidconsole_select_font(cons, gen->font_name,
+ gen->font_size);
+ } else {
+ ret = vidconsole_select_font(cons, NULL, 0);
+ }
+ if (ret && ret != -ENOSYS)
+ return log_msg_ret("font", ret);
+ str = expo_get_str(exp, gen->str_id);
+ if (!str)
+ return 0;
+
+ vid_priv = dev_get_uclass_priv(dev);
+ if (vid_priv->white_on_black) {
+ fore = VID_BLACK;
+ back = VID_WHITE;
+ } else {
+ fore = VID_LIGHT_GRAY;
+ back = VID_BLACK;
+ }
+
+ if (obj->flags & SCENEOF_POINT) {
+ int inset;
+
+ inset = exp->popup ? menu_inset : 0;
+ vidconsole_push_colour(cons, fore, back, &old);
+ video_fill_part(dev, x - inset, y,
+ obj->bbox.x1, obj->bbox.y1,
+ vid_priv->colour_bg);
+ }
+
+ mline = alist_get(&gen->lines, 0, typeof(*mline));
+ last = alist_get(&gen->lines, gen->lines.count - 1, typeof(*mline));
+ if (mline)
+ dims.y = last->bbox.y1 - mline->bbox.y0;
+ bbox.y0 = obj->bbox.y0;
+ bbox.y1 = obj->bbox.y1;
+
+ if (!mline) {
+ vidconsole_set_cursor_pos(cons, x, y);
+ vidconsole_put_string(cons, str);
+ }
+
+ alist_for_each(mline, &gen->lines) {
+ struct scene_obj_offset offset;
+
+ bbox.x0 = obj->bbox.x0;
+ bbox.x1 = obj->bbox.x1;
+ dims.x = mline->bbox.x1 - mline->bbox.x0;
+ handle_alignment(obj->horiz, obj->vert, &bbox, &dims,
+ obj->bbox.x1 - obj->bbox.x0,
+ obj->bbox.y1 - obj->bbox.y0, &offset);
+
+ x = obj->bbox.x0 + offset.xofs;
+ y = obj->bbox.y0 + offset.yofs + mline->bbox.y0;
+ if (y > bbox.y1)
+ break; /* clip this line and any following */
+ vidconsole_set_cursor_pos(cons, x, y);
+ vidconsole_put_stringn(cons, str + mline->start, mline->len);
+ }
+ if (obj->flags & SCENEOF_POINT)
+ vidconsole_pop_colour(cons, &old);
+
+ return 0;
+}
+
/**
* scene_obj_render() - Render an object
*
+ * @obj: Object to render
+ * @text_mode: true to use text mode
+ * Return: 0 if OK, -ve on error
*/
static int scene_obj_render(struct scene_obj *obj, bool text_mode)
{
@@ -367,10 +612,12 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
const struct expo_theme *theme = &exp->theme;
struct udevice *dev = exp->display;
struct udevice *cons = text_mode ? NULL : exp->cons;
+ struct video_priv *vid_priv;
int x, y, ret;
- x = obj->dim.x;
- y = obj->dim.y;
+ y = obj->bbox.y0;
+ x = obj->bbox.x0 + obj->ofs.xofs;
+ vid_priv = dev_get_uclass_priv(dev);
switch (obj->type) {
case SCENEOBJT_NONE:
@@ -388,59 +635,26 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
}
case SCENEOBJT_TEXT: {
struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
- const char *str;
-
- if (!cons)
- return -ENOTSUPP;
- if (txt->font_name || txt->font_size) {
- ret = vidconsole_select_font(cons,
- txt->font_name,
- txt->font_size);
- } else {
- ret = vidconsole_select_font(cons, NULL, 0);
- }
- if (ret && ret != -ENOSYS)
- return log_msg_ret("font", ret);
- str = expo_get_str(exp, txt->str_id);
- if (str) {
- struct video_priv *vid_priv;
- struct vidconsole_colour old;
- enum colour_idx fore, back;
-
- vid_priv = dev_get_uclass_priv(dev);
- if (vid_priv->white_on_black) {
- fore = VID_BLACK;
- back = VID_WHITE;
- } else {
- fore = VID_LIGHT_GRAY;
- back = VID_BLACK;
- }
-
- if (obj->flags & SCENEOF_POINT) {
- vidconsole_push_colour(cons, fore, back, &old);
- video_fill_part(dev, x - theme->menu_inset, y,
- x + obj->dim.w,
- y + obj->dim.h,
- vid_priv->colour_bg);
- }
- vidconsole_set_cursor_pos(cons, x, y);
- vidconsole_put_string(cons, str);
- if (obj->flags & SCENEOF_POINT)
- vidconsole_pop_colour(cons, &old);
- }
+ ret = scene_txt_render(exp, dev, cons, obj, &txt->gen, x, y,
+ theme->menu_inset);
break;
}
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
- if (exp->popup && (obj->flags & SCENEOF_OPEN)) {
- if (!cons)
- return -ENOTSUPP;
+ if (exp->popup) {
+ if (obj->flags & SCENEOF_OPEN) {
+ if (!cons)
+ return -ENOTSUPP;
- /* draw a background behind the menu items */
- scene_render_background(obj, false);
+ /* draw a background behind the menu items */
+ scene_render_background(obj, false, false);
+ }
+ } else if (exp->show_highlight) {
+ /* do nothing */
}
+
/*
* With a vidconsole, the text and item pointer are rendered as
* normal objects so we don't need to do anything here. The menu
@@ -457,9 +671,23 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
}
case SCENEOBJT_TEXTLINE:
if (obj->flags & SCENEOF_OPEN)
- scene_render_background(obj, true);
+ scene_render_background(obj, true, false);
+ break;
+ case SCENEOBJT_BOX: {
+ struct scene_obj_box *box = (struct scene_obj_box *)obj;
+
+ video_draw_box(dev, obj->bbox.x0, obj->bbox.y0, obj->bbox.x1,
+ obj->bbox.y1, box->width, vid_priv->colour_fg);
break;
}
+ case SCENEOBJT_TEXTEDIT: {
+ struct scene_obj_txtedit *ted = (struct scene_obj_txtedit *)obj;
+
+ ret = scene_txt_render(exp, dev, cons, obj, &ted->gen, x, y,
+ theme->menu_inset);
+ break;
+ }
+ }
return 0;
}
@@ -477,6 +705,8 @@ int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -510,18 +740,33 @@ int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr)
int scene_arrange(struct scene *scn)
{
struct expo_arrange_info arr;
+ int xsize = 0, ysize = 0;
struct scene_obj *obj;
+ struct udevice *dev;
int ret;
+ dev = scn->expo->display;
+ if (dev) {
+ struct video_priv *priv = dev_get_uclass_priv(dev);
+
+ xsize = priv->xsize;
+ ysize = priv->ysize;
+ }
+
ret = scene_calc_arrange(scn, &arr);
if (ret < 0)
return log_msg_ret("arr", ret);
list_for_each_entry(obj, &scn->obj_head, sibling) {
+ handle_alignment(obj->horiz, obj->vert, &obj->bbox, &obj->dims,
+ xsize, ysize, &obj->ofs);
+
switch (obj->type) {
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -567,6 +812,8 @@ int scene_render_deps(struct scene *scn, uint id)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
scene_menu_render_deps(scn,
@@ -686,6 +933,7 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -705,6 +953,9 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event)
return log_msg_ret("key", ret);
break;
}
+ case SCENEOBJT_TEXTEDIT:
+ /* TODO(sjg@chromium.org): Implement this */
+ break;
}
return 0;
}
@@ -724,25 +975,27 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event)
return 0;
}
-int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox)
+int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox bbox[])
{
switch (obj->type) {
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
return -ENOSYS;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
- scene_menu_calc_bbox(menu, bbox, label_bbox);
+ scene_menu_calc_bbox(menu, bbox);
break;
}
case SCENEOBJT_TEXTLINE: {
struct scene_obj_textline *tline;
tline = (struct scene_obj_textline *)obj;
- scene_textline_calc_bbox(tline, bbox, label_bbox);
+ scene_textline_calc_bbox(tline, &bbox[SCENEBB_all],
+ &bbox[SCENEBB_label]);
break;
}
}
@@ -759,6 +1012,8 @@ int scene_calc_dims(struct scene *scn, bool do_menus)
switch (obj->type) {
case SCENEOBJT_NONE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
case SCENEOBJT_IMAGE: {
int width;
@@ -766,8 +1021,13 @@ int scene_calc_dims(struct scene *scn, bool do_menus)
ret = scene_obj_get_hw(scn, obj->id, &width);
if (ret < 0)
return log_msg_ret("get", ret);
- obj->dim.w = width;
- obj->dim.h = ret;
+ obj->dims.x = width;
+ obj->dims.y = ret;
+ if (!(obj->flags & SCENEOF_SIZE_VALID)) {
+ obj->bbox.x1 = obj->bbox.x0 + width;
+ obj->bbox.y1 = obj->bbox.y0 + ret;
+ obj->flags |= SCENEOF_SIZE_VALID;
+ }
}
break;
}
@@ -812,8 +1072,13 @@ int scene_apply_theme(struct scene *scn, struct expo_theme *theme)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_MENU:
+ case SCENEOBJT_BOX:
case SCENEOBJT_TEXTLINE:
break;
+ case SCENEOBJT_TEXTEDIT:
+ scene_txted_set_font(scn, obj->id, NULL,
+ theme->font_size);
+ break;
case SCENEOBJT_TEXT:
scene_txt_set_font(scn, obj->id, NULL,
theme->font_size);
@@ -854,6 +1119,8 @@ static int scene_obj_open(struct scene *scn, struct scene_obj *obj)
case SCENEOBJT_IMAGE:
case SCENEOBJT_MENU:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_TEXTLINE:
ret = scene_textline_open(scn,
@@ -905,28 +1172,42 @@ int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter,
return 0;
}
+int scene_bbox_join(const struct vidconsole_bbox *src, int inset,
+ struct vidconsole_bbox *dst)
+{
+ if (dst->valid) {
+ dst->x0 = min(dst->x0, src->x0 - inset);
+ dst->y0 = min(dst->y0, src->y0);
+ dst->x1 = max(dst->x1, src->x1 + inset);
+ dst->y1 = max(dst->y1, src->y1);
+ } else {
+ dst->x0 = src->x0 - inset;
+ dst->y0 = src->y0;
+ dst->x1 = src->x1 + inset;
+ dst->y1 = src->y1;
+ dst->valid = true;
+ }
+
+ return 0;
+}
+
int scene_bbox_union(struct scene *scn, uint id, int inset,
struct vidconsole_bbox *bbox)
{
struct scene_obj *obj;
+ struct vidconsole_bbox local;
if (!id)
return 0;
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("obj", -ENOENT);
- if (bbox->valid) {
- bbox->x0 = min(bbox->x0, obj->dim.x - inset);
- bbox->y0 = min(bbox->y0, obj->dim.y);
- bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w + inset);
- bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h);
- } else {
- bbox->x0 = obj->dim.x - inset;
- bbox->y0 = obj->dim.y;
- bbox->x1 = obj->dim.x + obj->dim.w + inset;
- bbox->y1 = obj->dim.y + obj->dim.h;
- bbox->valid = true;
- }
+ local.x0 = obj->bbox.x0;
+ local.y0 = obj->bbox.y0;
+ local.x1 = obj->bbox.x1;
+ local.y1 = obj->bbox.y1;
+ local.valid = true;
+ scene_bbox_join(&local, inset, bbox);
return 0;
}
diff --git a/boot/scene_internal.h b/boot/scene_internal.h
index ec9008ea593..95927472875 100644
--- a/boot/scene_internal.h
+++ b/boot/scene_internal.h
@@ -9,11 +9,45 @@
#ifndef __SCENE_INTERNAL_H
#define __SCENE_INTERNAL_H
+#include <linux/types.h>
+
+struct expo;
+struct expo_action;
+struct expo_arrange_info;
+struct expo_theme;
+struct scene_obj;
+struct scene_obj_menu;
+struct scene_obj_textline;
+struct scene_obj_txtedit;
+struct scene_txt_generic;
struct vidconsole_bbox;
+enum scene_obj_t;
+
typedef int (*expo_scene_obj_iterator)(struct scene_obj *obj, void *priv);
/**
+ * enum scene_bbox_t - Parts of an object which can have a bounding box
+ *
+ * Objects can provide any or all of these bounding boxes
+ *
+ * @SCENEBB_label: Menu-item label
+ * @SCENEBB_key: Menu-item key label
+ * @SCENEBB_desc: Menu-item Description
+ * @SCENEBB_curitem: Current item (pointed to)
+ * @SCENEBB_all: All the above objects combined
+ */
+enum scene_bbox_t {
+ SCENEBB_label,
+ SCENEBB_key,
+ SCENEBB_desc,
+ SCENEBB_curitem,
+ SCENEBB_all,
+
+ SCENEBB_count,
+};
+
+/**
* expo_lookup_scene_id() - Look up a scene ID
*
* @exp: Expo to use
@@ -292,6 +326,19 @@ struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
int val);
/**
+ * scene_bbox_join() - update bouding box with a given src box
+ *
+ * Updates @dst so that it encompasses the bounding box @src
+ *
+ * @src: Input bounding box
+ * @inset: Amount of inset to use for width
+ * @dst: Bounding box to update
+ * Return: 0 if OK, -ve on error
+ */
+int scene_bbox_join(const struct vidconsole_bbox *src, int inset,
+ struct vidconsole_bbox *dst);
+
+/**
* scene_bbox_union() - update bouding box with the demensions of an object
*
* Updates @bbox so that it encompasses the bounding box of object @id
@@ -319,13 +366,11 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline);
* scene_menu_calc_bbox() - Calculate bounding boxes for the menu
*
* @menu: Menu to process
- * @bbox: Returns bounding box of menu including prompts
- * @label_bbox: Returns bounding box of labels
+ * @bbox: List of bounding box to fill in
* Return: 0 if OK, -ve on error
*/
void scene_menu_calc_bbox(struct scene_obj_menu *menu,
- struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox);
+ struct vidconsole_bbox *bbox);
/**
* scene_textline_calc_bbox() - Calculate bounding box for the textline
@@ -343,12 +388,10 @@ void scene_textline_calc_bbox(struct scene_obj_textline *menu,
* scene_obj_calc_bbox() - Calculate bounding boxes for an object
*
* @obj: Object to process
- * @bbox: Returns bounding box of object including prompts
- * @label_bbox: Returns bounding box of labels (active area)
+ * @bbox: Returns bounding boxes for object
* Return: 0 if OK, -ve on error
*/
-int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox);
+int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox);
/**
* scene_textline_open() - Open a textline object
@@ -384,4 +427,16 @@ int scene_textline_close(struct scene *scn, struct scene_obj_textline *tline);
*/
int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr);
+/**
+ * scene_txt_generic_init() - Set up the generic part of a text object
+ *
+ * @exp: Expo containing the object
+ * @gen: Generic text info
+ * @name: Object name
+ * @str_id: String ID for the text
+ * @str: Initial text string for the object, or NULL to just use str_id
+ */
+int scene_txt_generic_init(struct expo *exp, struct scene_txt_generic *gen,
+ const char *name, uint str_id, const char *str);
+
#endif /* __SCENE_INTERNAL_H */
diff --git a/boot/scene_menu.c b/boot/scene_menu.c
index 17150af145d..23404172093 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -87,7 +87,7 @@ struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
{
struct scene *scn = menu->obj.scene;
- const bool stack = scn->expo->popup;
+ const bool stack = scn->expo->show_highlight;
const struct scene_menitem *item;
int ret;
@@ -102,15 +102,23 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
label = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE);
ret = scene_obj_set_pos(scn, menu->pointer_id,
- menu->obj.dim.x + 200, label->dim.y);
+ menu->obj.bbox.x0 + 200, label->bbox.y0);
if (ret < 0)
return log_msg_ret("ptr", ret);
}
if (stack) {
+ uint id;
+ int val;
+
point &= scn->highlight_id == menu->obj.id;
- scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT,
- point ? SCENEOF_POINT : 0);
+ val = point ? SCENEOF_POINT : 0;
+ id = item->desc_id;
+ if (!id)
+ id = item->label_id;
+ if (!id)
+ id = item->key_id;
+ scene_obj_flag_clrset(scn, id, SCENEOF_POINT, val);
}
return 0;
@@ -121,64 +129,98 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
*
* Sets the currently pointed-to / highlighted menu item
*/
-static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
+static int menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
{
- if (menu->cur_item_id)
- update_pointers(menu, menu->cur_item_id, false);
+ int ret;
+
+ if (menu->cur_item_id) {
+ ret = update_pointers(menu, menu->cur_item_id, false);
+ if (ret)
+ return log_msg_ret("mpi", ret);
+ }
menu->cur_item_id = item_id;
- update_pointers(menu, item_id, true);
+ ret = update_pointers(menu, item_id, true);
+ if (ret)
+ return log_msg_ret("mpu", ret);
+
+ return 0;
}
void scene_menu_calc_bbox(struct scene_obj_menu *menu,
- struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox)
+ struct vidconsole_bbox *bbox)
{
const struct expo_theme *theme = &menu->obj.scene->expo->theme;
const struct scene_menitem *item;
+ int inset = theme->menu_inset;
+ int i;
- bbox->valid = false;
- scene_bbox_union(menu->obj.scene, menu->title_id, 0, bbox);
+ for (i = 0; i < SCENEBB_count; i++)
+ bbox[i].valid = false;
- label_bbox->valid = false;
+ scene_bbox_union(menu->obj.scene, menu->title_id, 0,
+ &bbox[SCENEBB_all]);
list_for_each_entry(item, &menu->item_head, sibling) {
- scene_bbox_union(menu->obj.scene, item->label_id,
- theme->menu_inset, bbox);
- scene_bbox_union(menu->obj.scene, item->key_id, 0, bbox);
- scene_bbox_union(menu->obj.scene, item->desc_id, 0, bbox);
- scene_bbox_union(menu->obj.scene, item->preview_id, 0, bbox);
-
- /* Get the bounding box of all labels */
- scene_bbox_union(menu->obj.scene, item->label_id,
- theme->menu_inset, label_bbox);
+ struct vidconsole_bbox local;
+
+ local.valid = false;
+ scene_bbox_union(menu->obj.scene, item->label_id, inset,
+ &local);
+ scene_bbox_union(menu->obj.scene, item->key_id, 0, &local);
+ scene_bbox_union(menu->obj.scene, item->desc_id, 0, &local);
+ scene_bbox_union(menu->obj.scene, item->preview_id, 0, &local);
+
+ scene_bbox_join(&local, 0, &bbox[SCENEBB_all]);
+
+ /* Get the bounding box of all individual fields */
+ scene_bbox_union(menu->obj.scene, item->label_id, inset,
+ &bbox[SCENEBB_label]);
+ scene_bbox_union(menu->obj.scene, item->key_id, inset,
+ &bbox[SCENEBB_key]);
+ scene_bbox_union(menu->obj.scene, item->desc_id, inset,
+ &bbox[SCENEBB_desc]);
+
+ if (menu->cur_item_id == item->id)
+ scene_bbox_join(&local, 0, &bbox[SCENEBB_curitem]);
}
/*
- * subtract the final menuitem's gap to keep the insert the same top
- * and bottom
+ * subtract the final menuitem's gap to keep the inset the same top and
+ * bottom
*/
- label_bbox->y1 -= theme->menuitem_gap_y;
+ bbox[SCENEBB_label].y1 -= theme->menuitem_gap_y;
}
int scene_menu_calc_dims(struct scene_obj_menu *menu)
{
- struct vidconsole_bbox bbox, label_bbox;
+ struct vidconsole_bbox bbox[SCENEBB_count], *cur;
const struct scene_menitem *item;
- scene_menu_calc_bbox(menu, &bbox, &label_bbox);
+ scene_menu_calc_bbox(menu, bbox);
- /* Make all labels the same size */
- if (label_bbox.valid) {
- list_for_each_entry(item, &menu->item_head, sibling) {
- scene_obj_set_size(menu->obj.scene, item->label_id,
- label_bbox.x1 - label_bbox.x0,
- label_bbox.y1 - label_bbox.y0);
- }
+ /* Make all field types the same width */
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ cur = &bbox[SCENEBB_label];
+ if (cur->valid)
+ scene_obj_set_width(menu->obj.scene, item->label_id,
+ cur->x1 - cur->x0);
+ cur = &bbox[SCENEBB_key];
+ if (cur->valid)
+ scene_obj_set_width(menu->obj.scene, item->key_id,
+ cur->x1 - cur->x0);
+ cur = &bbox[SCENEBB_desc];
+ if (cur->valid)
+ scene_obj_set_width(menu->obj.scene, item->desc_id,
+ cur->x1 - cur->x0);
}
- if (bbox.valid) {
- menu->obj.dim.w = bbox.x1 - bbox.x0;
- menu->obj.dim.h = bbox.y1 - bbox.y0;
+ cur = &bbox[SCENEBB_all];
+ if (cur->valid) {
+ menu->obj.dims.x = cur->x1 - cur->x0;
+ menu->obj.dims.y = cur->y1 - cur->y0;
+
+ menu->obj.bbox.x1 = cur->x1;
+ menu->obj.bbox.y1 = cur->y1;
}
return 0;
@@ -196,12 +238,12 @@ int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
int x, y;
int ret;
- x = menu->obj.dim.x;
- y = menu->obj.dim.y;
+ x = menu->obj.bbox.x0;
+ y = menu->obj.bbox.y0;
if (menu->title_id) {
int width;
- ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y);
+ ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.bbox.x0, y);
if (ret < 0)
return log_msg_ret("tit", ret);
@@ -286,6 +328,9 @@ int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
if (sel_id)
menu_point_to_item(menu, sel_id);
+ menu->obj.bbox.x1 = menu->obj.bbox.x0 + menu->obj.dims.x;
+ menu->obj.bbox.y1 = menu->obj.bbox.y0 + menu->obj.dims.y;
+ menu->obj.flags |= SCENEOF_SIZE_VALID;
return 0;
}
@@ -322,7 +367,7 @@ static struct scene_menitem *scene_menu_find_key(struct scene *scn,
txt = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
if (txt) {
- str = expo_get_str(scn->expo, txt->str_id);
+ str = expo_get_str(scn->expo, txt->gen.str_id);
if (str && *str == key)
return item;
}
@@ -397,8 +442,6 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
break;
}
- menu_point_to_item(menu, item->id);
-
return 0;
}
@@ -483,6 +526,33 @@ int scene_menu_set_pointer(struct scene *scn, uint id, uint pointer_id)
return 0;
}
+int scene_menu_select_item(struct scene *scn, uint id, uint cur_item_id)
+{
+ struct scene_obj_menu *menu;
+ int ret;
+
+ menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
+ if (!menu)
+ return log_msg_ret("menu", -ENOENT);
+
+ ret = menu_point_to_item(menu, cur_item_id);
+ if (ret)
+ return log_msg_ret("msi", ret);
+
+ return 0;
+}
+
+int scene_menu_get_cur_item(struct scene *scn, uint id)
+{
+ struct scene_obj_menu *menu;
+
+ menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
+ if (!menu)
+ return log_msg_ret("menu", -ENOENT);
+
+ return menu->cur_item_id;
+}
+
int scene_menu_display(struct scene_obj_menu *menu)
{
struct scene *scn = menu->obj.scene;
@@ -500,15 +570,16 @@ int scene_menu_display(struct scene_obj_menu *menu)
if (!txt)
return log_msg_ret("txt", -EINVAL);
- str = expo_get_str(exp, txt->str_id);
- printf("%s\n\n", str);
+ str = expo_get_str(exp, txt->gen.str_id);
+ printf("%s\n\n", str ? str : "");
}
if (list_empty(&menu->item_head))
return 0;
pointer = scene_obj_find(scn, menu->pointer_id, SCENEOBJT_TEXT);
- pstr = expo_get_str(scn->expo, pointer->str_id);
+ if (pointer)
+ pstr = expo_get_str(scn->expo, pointer->gen.str_id);
list_for_each_entry(item, &menu->item_head, sibling) {
struct scene_obj_txt *key = NULL, *label = NULL;
@@ -517,15 +588,15 @@ int scene_menu_display(struct scene_obj_menu *menu)
key = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
if (key)
- kstr = expo_get_str(exp, key->str_id);
+ kstr = expo_get_str(exp, key->gen.str_id);
label = scene_obj_find(scn, item->label_id, SCENEOBJT_TEXT);
if (label)
- lstr = expo_get_str(exp, label->str_id);
+ lstr = expo_get_str(exp, label->gen.str_id);
desc = scene_obj_find(scn, item->desc_id, SCENEOBJT_TEXT);
if (desc)
- dstr = expo_get_str(exp, desc->str_id);
+ dstr = expo_get_str(exp, desc->gen.str_id);
printf("%3s %3s %-10s %s\n",
pointer && menu->cur_item_id == item->id ? pstr : "",
diff --git a/boot/scene_textedit.c b/boot/scene_textedit.c
new file mode 100644
index 00000000000..8242eb39806
--- /dev/null
+++ b/boot/scene_textedit.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Implementation of a menu in a scene
+ *
+ * Copyright 2025 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY LOGC_EXPO
+
+#include <expo.h>
+#include <log.h>
+#include <linux/err.h>
+#include <linux/sizes.h>
+#include "scene_internal.h"
+
+enum {
+ INITIAL_SIZE = SZ_4K,
+};
+
+int scene_texted(struct scene *scn, const char *name, uint id, uint str_id,
+ struct scene_obj_txtedit **teditp)
+{
+ struct scene_obj_txtedit *ted;
+ char *buf;
+ int ret;
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXTEDIT,
+ sizeof(struct scene_obj_txtedit),
+ (struct scene_obj **)&ted);
+ if (ret < 0)
+ return log_msg_ret("obj", ret);
+
+ abuf_init(&ted->buf);
+ if (!abuf_realloc(&ted->buf, INITIAL_SIZE))
+ return log_msg_ret("buf", -ENOMEM);
+ buf = abuf_data(&ted->buf);
+ *buf = '\0';
+
+ ret = scene_txt_generic_init(scn->expo, &ted->gen, name, str_id, buf);
+ if (ret)
+ return log_msg_ret("teg", ret);
+ if (teditp)
+ *teditp = ted;
+
+ return ted->obj.id;
+}
+
+int scene_txted_set_font(struct scene *scn, uint id, const char *font_name,
+ uint font_size)
+{
+ struct scene_obj_txtedit *ted;
+
+ ted = scene_obj_find(scn, id, SCENEOBJT_TEXTEDIT);
+ if (!ted)
+ return log_msg_ret("find", -ENOENT);
+ ted->gen.font_name = font_name;
+ ted->gen.font_size = font_size;
+
+ return 0;
+}
diff --git a/boot/scene_textline.c b/boot/scene_textline.c
index 6adef7cc173..7bc35a997dc 100644
--- a/boot/scene_textline.c
+++ b/boot/scene_textline.c
@@ -31,8 +31,7 @@ int scene_textline(struct scene *scn, const char *name, uint id, uint max_chars,
(struct scene_obj **)&tline);
if (ret < 0)
return log_msg_ret("obj", -ENOMEM);
- abuf_init(&tline->buf);
- if (!abuf_realloc(&tline->buf, max_chars + 1))
+ if (!abuf_init_size(&tline->buf, max_chars + 1))
return log_msg_ret("buf", -ENOMEM);
buf = abuf_data(&tline->buf);
*buf = '\0';
@@ -62,7 +61,8 @@ void scene_textline_calc_bbox(struct scene_obj_textline *tline,
int scene_textline_calc_dims(struct scene_obj_textline *tline)
{
- struct scene *scn = tline->obj.scene;
+ struct scene_obj *obj = &tline->obj;
+ struct scene *scn = obj->scene;
struct vidconsole_bbox bbox;
struct scene_obj_txt *txt;
int ret;
@@ -71,17 +71,22 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline)
if (!txt)
return log_msg_ret("dim", -ENOENT);
- ret = vidconsole_nominal(scn->expo->cons, txt->font_name,
- txt->font_size, tline->max_chars, &bbox);
+ ret = vidconsole_nominal(scn->expo->cons, txt->gen.font_name,
+ txt->gen.font_size, tline->max_chars, &bbox);
if (ret)
return log_msg_ret("nom", ret);
if (bbox.valid) {
- tline->obj.dim.w = bbox.x1 - bbox.x0;
- tline->obj.dim.h = bbox.y1 - bbox.y0;
-
- scene_obj_set_size(scn, tline->edit_id, tline->obj.dim.w,
- tline->obj.dim.h);
+ obj->dims.x = bbox.x1 - bbox.x0;
+ obj->dims.y = bbox.y1 - bbox.y0;
+ if (!(obj->flags & SCENEOF_SIZE_VALID)) {
+ obj->bbox.x1 = obj->bbox.x0 + obj->dims.x;
+ obj->bbox.y1 = obj->bbox.y0 + obj->dims.y;
+ obj->flags |= SCENEOF_SIZE_VALID;
+ }
+ scene_obj_set_size(scn, tline->edit_id,
+ obj->bbox.x1 - obj->bbox.x0,
+ obj->bbox.y1 - obj->bbox.y0);
}
return 0;
@@ -95,16 +100,16 @@ int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr,
int x, y;
int ret;
- x = tline->obj.dim.x;
- y = tline->obj.dim.y;
+ x = tline->obj.bbox.x0;
+ y = tline->obj.bbox.y0;
if (tline->label_id) {
- ret = scene_obj_set_pos(scn, tline->label_id, tline->obj.dim.x,
- y);
+ ret = scene_obj_set_pos(scn, tline->label_id,
+ tline->obj.bbox.x0, y);
if (ret < 0)
return log_msg_ret("tit", ret);
ret = scene_obj_set_pos(scn, tline->edit_id,
- tline->obj.dim.x + 200, y);
+ tline->obj.bbox.x0 + 200, y);
if (ret < 0)
return log_msg_ret("tit", ret);
@@ -186,10 +191,10 @@ int scene_textline_render_deps(struct scene *scn,
if (!txt)
return log_msg_ret("cur", -ENOENT);
- if (txt->font_name || txt->font_size) {
+ if (txt->gen.font_name || txt->gen.font_size) {
ret = vidconsole_select_font(cons,
- txt->font_name,
- txt->font_size);
+ txt->gen.font_name,
+ txt->gen.font_size);
} else {
ret = vidconsole_select_font(cons, NULL, 0);
}
@@ -198,8 +203,8 @@ int scene_textline_render_deps(struct scene *scn,
if (ret)
return log_msg_ret("sav", ret);
- vidconsole_set_cursor_visible(cons, true, txt->obj.dim.x,
- txt->obj.dim.y, scn->cls.num);
+ vidconsole_set_cursor_visible(cons, true, txt->obj.bbox.x0,
+ txt->obj.bbox.y0, scn->cls.num);
}
return 0;
@@ -220,7 +225,7 @@ int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline)
if (!txt)
return log_msg_ret("cur", -ENOENT);
- vidconsole_set_cursor_pos(cons, txt->obj.dim.x, txt->obj.dim.y);
+ vidconsole_set_cursor_pos(cons, txt->obj.bbox.x0, txt->obj.bbox.y0);
vidconsole_entry_start(cons);
cli_cread_init(&scn->cls, abuf_data(&tline->buf), tline->max_chars);
scn->cls.insert = true;