[PATCH 00/24] bootctl: Expand bootctl to include a new UI
From: Simon Glass <sjg@chromium.org> The current bootctl UI is fairly basic, just supporting a keyboard menu with text. Now that expo supports a mouse, add a more interesting UI, with more graphical elements. Provide a way to switch between this and the simple UI. This series also includes some small test improvements, along with a patch to remove a blob from a bloblist. Simon Glass (24): test/py: Make test_bind_unbind_with_uclass() independent test/py: Mark a few more tests as slow bloblist: Add a name for the EFI log bloblist: Provide a way to remove a blob tpm: Correct address handling in tcg2_platform_get_log() scripts: build-efi: Use a locally built OVMF image boot: test: Add another Ubuntu image on mmc11 boot: Allow switching back to another layout test: Correct an incomplete sentence in prep_mmc_bootdev() sandbox: Enable Ubuntu fonts bootctl: Plumb in the feature bootctl: Create a common struct for the BOOTCTL_UI uclass bootctl: Avoid hanging on failure bootctl: Provide an option to slow the display refresh bootctl: Respect the autoboot option bootctl: Re-apply the theme when showing the UI bootctl: Bring in some additional images bootctl: Add an option to switch the layout bootctl: Provide a multi-themed UI bootctl: Disable autoboot bootctl: Add a test for the multi UI efi: x86: Provide settings for bootctl efi: x86: Enable required Kconfig options for bootctl efi: x86: Use only serial for input .gitignore | 2 + arch/sandbox/dts/test.dts | 9 + arch/x86/dts/efi-x86_app.dts | 14 + board/efi/efi-x86_app/efi-x86_app.env | 1 + boot/Kconfig | 4 +- boot/Makefile | 2 + boot/bootctl/Makefile | 1 + boot/bootctl/bootctl-uclass.c | 2 + boot/bootctl/bootctl.c | 3 +- boot/bootctl/logic.c | 3 +- boot/bootctl/multi_ui.c | 588 ++++++++++++++++++++++++++ boot/bootctl/simple_ui.c | 111 ++--- boot/bootctl/util.c | 15 + boot/bootflow_menu.c | 2 + cmd/Makefile | 1 + common/bloblist.c | 33 ++ configs/efi-x86_app64_defconfig | 11 +- configs/sandbox_defconfig | 2 + drivers/video/images/Makefile | 5 + drivers/video/images/canonical.bmp | Bin 0 -> 14258 bytes drivers/video/images/help.bmp | Bin 0 -> 1782 bytes drivers/video/images/multipass.bmp | Bin 0 -> 4378 bytes drivers/video/images/settings.bmp | Bin 0 -> 1782 bytes drivers/video/images/tick.bmp | Bin 0 -> 822 bytes include/bloblist.h | 12 + include/bootctl.dtsi | 11 +- include/bootctl/logic.h | 2 + include/bootctl/ui.h | 43 ++ include/tpm_tcg2.h | 4 +- lib/tpm_tcg2.c | 21 +- scripts/build-efi | 2 +- test/boot/bootctl/bootctl.c | 181 +++++++- test/boot/bootflow.c | 2 +- test/cmd/font.c | 5 + test/common/bloblist.c | 64 +++ test/dm/video.c | 7 +- test/py/tests/test_bind.py | 5 + test/py/tests/test_fit_auto_signed.py | 1 + test/py/tests/test_make_dep.py | 3 + test/py/tests/test_ut.py | 3 +- 40 files changed, 1084 insertions(+), 91 deletions(-) create mode 100644 boot/bootctl/multi_ui.c create mode 100644 drivers/video/images/canonical.bmp create mode 100644 drivers/video/images/help.bmp create mode 100644 drivers/video/images/multipass.bmp create mode 100644 drivers/video/images/settings.bmp create mode 100644 drivers/video/images/tick.bmp -- 2.43.0 base-commit: 05ed569280ad46563c77fafbc5f86fdf3f9d20d0 branch: proi
From: Simon Glass <sjg@chromium.org> Unbind the test node at the start of this test, so that it can be run independently from test_bind_unbind_with_node() Signed-off-by: Simon Glass <sjg@chromium.org> --- test/py/tests/test_bind.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/py/tests/test_bind.py b/test/py/tests/test_bind.py index 16c63ae9684..4982a00fab6 100644 --- a/test/py/tests/test_bind.py +++ b/test/py/tests/test_bind.py @@ -121,6 +121,10 @@ def get_next_line(tree, name): @pytest.mark.buildconfigspec('cmd_bind') @pytest.mark.singlethread def test_bind_unbind_with_uclass(ubman): + # Ensure /bind-test is unbound, since it may be bound from DT or the + # previous tests + ubman.run_command('unbind /bind-test') + #bind /bind-test response = ubman.run_command('bind /bind-test simple_bus') assert response == '' -- 2.43.0
From: Simon Glass <sjg@chromium.org> These are the top five slowest test as reported from 'make qcheck': 42.2s test_dep_esl 29.7s test_dep_hwids 17.3s test_dep_dtbo 6.4s test_bind_unbind_with_node 5.2s test_fit_auto_signed Mark them as slow so that they are skipped with 'make qcheck'. Signed-off-by: Simon Glass <sjg@chromium.org> --- test/py/tests/test_bind.py | 1 + test/py/tests/test_fit_auto_signed.py | 1 + test/py/tests/test_make_dep.py | 3 +++ 3 files changed, 5 insertions(+) diff --git a/test/py/tests/test_bind.py b/test/py/tests/test_bind.py index 4982a00fab6..b0a5b7b3e84 100644 --- a/test/py/tests/test_bind.py +++ b/test/py/tests/test_bind.py @@ -27,6 +27,7 @@ def in_tree(response, name, uclass, drv, depth, last_child): @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_bind') +@pytest.mark.slow def test_bind_unbind_with_node(ubman): tree = ubman.run_command('dm tree') diff --git a/test/py/tests/test_fit_auto_signed.py b/test/py/tests/test_fit_auto_signed.py index cdfd341c6f5..0e34e4b0704 100644 --- a/test/py/tests/test_fit_auto_signed.py +++ b/test/py/tests/test_fit_auto_signed.py @@ -120,6 +120,7 @@ class SignedFitHelper(object): @pytest.mark.buildconfigspec('fit_signature') @pytest.mark.requiredtool('fdtget') +@pytest.mark.slow def test_fit_auto_signed(ubman): """Test that mkimage generates auto-FIT with signatures/hashes as expected. diff --git a/test/py/tests/test_make_dep.py b/test/py/tests/test_make_dep.py index 734cbb547e4..d5cb5145bc4 100644 --- a/test/py/tests/test_make_dep.py +++ b/test/py/tests/test_make_dep.py @@ -411,6 +411,7 @@ def _check_template_change(env, prev_esl_mtime, prev_dtsi_mtime): @pytest.mark.boardspec('sandbox') +@pytest.mark.slow def test_dep_hwids(ubman): """Test that Makefile dependency tracking works without FORCE @@ -432,6 +433,7 @@ def test_dep_hwids(ubman): @pytest.mark.boardspec('sandbox') +@pytest.mark.slow def test_dep_dtbo(ubman): """Test that dtbo dependency tracking works without FORCE @@ -450,6 +452,7 @@ def test_dep_dtbo(ubman): @pytest.mark.boardspec('sandbox') +@pytest.mark.slow def test_dep_esl(ubman): """Test that ESL dependency tracking works without FORCE -- 2.43.0
From: Simon Glass <sjg@chromium.org> Add an entry for BLOBLISTT_EFI_LOG to the tag_name[] array, so that 'bloblist list' will show the tag as a string. Signed-off-by: Simon Glass <sjg@chromium.org> --- common/bloblist.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/bloblist.c b/common/bloblist.c index 790b0ea892d..d1d7ddb956a 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -63,6 +63,7 @@ static struct tag_name { { BLOBLISTT_U_BOOT_SPL_HANDOFF, "SPL hand-off" }, { BLOBLISTT_VBE, "VBE" }, { BLOBLISTT_U_BOOT_VIDEO, "SPL video handoff" }, + { BLOBLISTT_EFI_LOG, "EFI-call log" }, /* BLOBLISTT_VENDOR_AREA */ }; -- 2.43.0
From: Simon Glass <sjg@chromium.org> Add a function to remove a blob of a particular type. Signed-off-by: Simon Glass <sjg@chromium.org> Co-developed-by: Claude <noreply@anthropic.com> --- common/bloblist.c | 32 +++++++++++++++++++++ include/bloblist.h | 12 ++++++++ test/common/bloblist.c | 64 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) diff --git a/common/bloblist.c b/common/bloblist.c index d1d7ddb956a..e5fa67b0f71 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -356,6 +356,38 @@ int bloblist_resize(uint tag, int new_size) return 0; } +int bloblist_remove(uint tag) +{ + struct bloblist_hdr *hdr = gd->bloblist; + struct bloblist_rec *rec; + ulong rec_start; /* offset where record starts */ + ulong next_ofs; /* offset of the record after @rec */ + ulong removed_size; /* total size to remove, including alignment */ + + rec = bloblist_findrec(tag); + if (!rec) + return log_msg_ret("find", -ENOENT); + + /* Calculate where this record starts and where the next one begins */ + rec_start = (void *)rec - (void *)hdr; + next_ofs = bloblist_blob_end_ofs(hdr, rec); + + /* Calculate total size to remove (record + alignment) */ + removed_size = next_ofs - rec_start; + + /* Move all following blobs backward to fill the gap */ + if (next_ofs < hdr->used_size) { + memmove((void *)hdr + rec_start, + (void *)hdr + next_ofs, + hdr->used_size - next_ofs); + } + + /* Update the used size */ + hdr->used_size -= removed_size; + + return 0; +} + static u32 bloblist_calc_chksum(struct bloblist_hdr *hdr) { u8 chksum; diff --git a/include/bloblist.h b/include/bloblist.h index e55d71110c3..ff88f4c8d5e 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -350,6 +350,18 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp); */ int bloblist_resize(uint tag, int new_size); +/** + * bloblist_remove() - remove a blob from the bloblist + * + * This removes the blob with the given tag from the bloblist. Any blobs after + * this one are relocated backward to fill the gap. The space is reclaimed and + * used_size is reduced accordingly. + * + * @tag: Tag to remove (enum bloblist_tag_t) + * Return: 0 if OK, -ENOENT if the tag is not found + */ +int bloblist_remove(uint tag); + /** * bloblist_new() - Create a new, empty bloblist of a given size * diff --git a/test/common/bloblist.c b/test/common/bloblist.c index 797bde27025..ad87b104d9c 100644 --- a/test/common/bloblist.c +++ b/test/common/bloblist.c @@ -605,3 +605,67 @@ static int bloblist_test_blob_maxsize(struct unit_test_state *uts) return 0; } BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST); + +/* Test removing a blob */ +static int bloblist_test_remove(struct unit_test_state *uts) +{ + const uint small_size = 0x20; + struct bloblist_hdr *hdr; + void *blob1, *blob2, *blob3; + ulong used_before, used_after; + + clear_bloblist(); + ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); + hdr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); + + /* Create three blobs */ + blob1 = bloblist_add(TEST_TAG, small_size, 0); + ut_assertnonnull(blob1); + strcpy(blob1, test1_str); + + blob2 = bloblist_add(TEST_TAG2, small_size, 0); + ut_assertnonnull(blob2); + strcpy(blob2, test2_str); + + blob3 = bloblist_add(TEST_TAG_MISSING, small_size, 0); + ut_assertnonnull(blob3); + + used_before = hdr->used_size; + + /* Remove the middle blob */ + ut_assertok(bloblist_remove(TEST_TAG2)); + + /* Check that the blob is gone */ + ut_assertnull(bloblist_find(TEST_TAG2, 0)); + + /* Check that the first blob is still there and intact */ + ut_asserteq_ptr(blob1, bloblist_find(TEST_TAG, small_size)); + ut_asserteq_str(test1_str, blob1); + + /* Check that the third blob is still there */ + ut_assertnonnull(bloblist_find(TEST_TAG_MISSING, small_size)); + + /* Check that used_size was reduced */ + used_after = hdr->used_size; + ut_assert(used_after < used_before); + + /* Try to remove a non-existent blob */ + ut_asserteq(-ENOENT, bloblist_remove(TEST_TAG2)); + + /* Remove the first blob */ + ut_assertok(bloblist_remove(TEST_TAG)); + ut_assertnull(bloblist_find(TEST_TAG, 0)); + + /* The third blob should still be accessible */ + ut_assertnonnull(bloblist_find(TEST_TAG_MISSING, small_size)); + + /* Remove the last blob */ + ut_assertok(bloblist_remove(TEST_TAG_MISSING)); + ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0)); + + /* Check that we're back to just the header */ + ut_asserteq(sizeof(struct bloblist_hdr), hdr->used_size); + + return 0; +} +BLOBLIST_TEST(bloblist_test_remove, UFT_BLOBLIST); -- 2.43.0
From: Simon Glass <sjg@chromium.org> This function assumes that an address is the same as a pointer. Use map_sysmem() to fix this, which crashes on sandbox. Rename the parameter from addr to ptr, to avoid further confusion. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/tpm_tcg2.h | 4 ++-- lib/tpm_tcg2.c | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/tpm_tcg2.h b/include/tpm_tcg2.h index 189a93ee840..e305bc29a95 100644 --- a/include/tpm_tcg2.h +++ b/include/tpm_tcg2.h @@ -313,12 +313,12 @@ void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog, * Get the platform event log address and size. * * @dev TPM device - * @addr Address of the log + * @addr Pointer to the log * @size Size of the log * * Return: zero on success, negative errno otherwise */ -int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size); +int tcg2_platform_get_log(struct udevice *dev, void **ptrp, u32 *sizep); /** * Get the first TPM2 device found. diff --git a/lib/tpm_tcg2.c b/lib/tpm_tcg2.c index 364f7287438..bcd3423d923 100644 --- a/lib/tpm_tcg2.c +++ b/lib/tpm_tcg2.c @@ -671,7 +671,7 @@ void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog, unmap_physmem(elog->log, MAP_NOCACHE); } -__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) +__weak int tcg2_platform_get_log(struct udevice *dev, void **ptrp, u32 *sizep) { const __be32 *addr_prop = NULL; const __be32 *size_prop = NULL; @@ -680,13 +680,14 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) struct ofnode_phandle_args args; phys_addr_t a; fdt_size_t s; + void *ptr; + int size; - *addr = NULL; - *size = 0; + ptr = bloblist_get_blob(BLOBLISTT_TPM_EVLOG, &size); + if (ptr && size) { + ulong addr = map_to_sysmem(ptr); - *addr = bloblist_get_blob(BLOBLISTT_TPM_EVLOG, size); - if (*addr && *size) { - *addr = map_physmem((uintptr_t)(*addr), *size, MAP_NOCACHE); + *ptrp = map_physmem(addr, size, MAP_NOCACHE); return 0; } @@ -714,8 +715,8 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) u64 a = of_read_number(addr_prop, asize / sizeof(__be32)); u64 s = of_read_number(size_prop, ssize / sizeof(__be32)); - *addr = map_physmem(a, s, MAP_NOCACHE); - *size = (u32)s; + *ptrp = map_physmem(a, s, MAP_NOCACHE); + *sizep = (u32)s; return 0; } @@ -727,8 +728,8 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) if (a == FDT_ADDR_T_NONE) return -ENOMEM; - *addr = map_physmem(a, s, MAP_NOCACHE); - *size = (u32)s; + *ptrp = map_physmem(a, s, MAP_NOCACHE); + *sizep = (u32)s; return 0; } -- 2.43.0
From: Simon Glass <sjg@chromium.org> The standard OVMF image does not include mouse support. Use a locally built release build instead. Signed-off-by: Simon Glass <sjg@chromium.org> --- scripts/build-efi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-efi b/scripts/build-efi index 032b9f7b1ab..fffe699e80a 100755 --- a/scripts/build-efi +++ b/scripts/build-efi @@ -89,7 +89,7 @@ class BuildEfi: else: # x86 if self.helper.bitness == 64: qemu_arch = 'x86_64' - bios = 'OVMF_CODE_4M.fd' + bios = 'OVMF-release-x64.fd' else: qemu_arch = 'i386' bios = 'OVMF-pure-efi.i386.fd' -- 2.43.0
From: Simon Glass <sjg@chromium.org> Bring in a test image which has a different version of Ubuntu. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/sandbox/dts/test.dts | 9 +++++++++ test/py/tests/test_ut.py | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index da4a89baf30..86c01545462 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -47,6 +47,8 @@ mmc7 = "/mmc7"; mmc8 = "/mmc8"; mmc9 = "/mmc9"; + mmc10 = "/mmc10"; + mmc11 = "/mmc11"; pci0 = &pci0; pci1 = &pci1; pci2 = &pci2; @@ -1194,6 +1196,13 @@ filename = "mmc10.img"; }; + /* This is used for bootctl tests */ + mmc11 { + status = "disabled"; + compatible = "sandbox,mmc"; + filename = "mmc11.img"; + }; + pch { compatible = "sandbox,pch"; }; diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 0acc40ae6aa..b532bdced13 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -80,9 +80,10 @@ def test_ut_dm_init_bootstd(u_boot_config, u_boot_log): setup_cros_image(u_boot_config, u_boot_log) setup_android_image(u_boot_config, u_boot_log) setup_efi_image(u_boot_config) - setup_ubuntu_image(u_boot_config, u_boot_log, 3, 'flash') + setup_ubuntu_image(u_boot_config, u_boot_log, 3, 'flash', '25.04') setup_localboot_image(u_boot_config, u_boot_log) setup_vbe_image(u_boot_config, u_boot_log) + setup_ubuntu_image(u_boot_config, u_boot_log, 11, 'mmc') def test_ut(ubman, ut_subtest): """Execute a "ut" subtest. -- 2.43.0
From: Simon Glass <sjg@chromium.org> Implement the settings button to permit the user to switch to another UI layout, if available. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootflow_menu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c index 161c5a42401..26a2f559958 100644 --- a/boot/bootflow_menu.c +++ b/boot/bootflow_menu.c @@ -418,6 +418,8 @@ int bootflow_menu_poll(struct expo *exp, int *seqp) case EXPOACT_CLICK: if (act.select.id == OBJ_SETTINGS) return -ECOMM; /* layout change request */ + case EXPOACT_SETTINGS: + return -ECOMM; /* layout change request */ default: return -EAGAIN; } -- 2.43.0
From: Simon Glass <sjg@chromium.org> The comment for mmc_dev is missing the last part of the sentence. Add it. Signed-off-by: Simon Glass <sjg@chromium.org> --- test/boot/bootflow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 65e2b5b5c9d..e2de3af4f29 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -635,7 +635,7 @@ BOOTSTD_TEST(bootflow_cmd_boot, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); * * @uts: Unit test state * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid - * in the caller until + * in the caller until boot scanning is finished * @bind_cros: true to bind the ChromiumOS and Android bootmeths * @old_orderp: Returns the original bootdev order, which must be restored * Returns 0 on success, -ve on failure -- 2.43.0
From: Simon Glass <sjg@chromium.org> Bring the Ubuntu fonts into the build. Signed-off-by: Simon Glass <sjg@chromium.org> --- configs/sandbox_defconfig | 2 ++ test/cmd/font.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index ff2e9ac6e75..0d115368d1b 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -335,6 +335,8 @@ CONFIG_VIDEO_COPY=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y +CONFIG_CONSOLE_TRUETYPE_UBUNTU_LIGHT=y +CONFIG_CONSOLE_TRUETYPE_UBUNTU_BOLD=y CONFIG_I2C_EDID=y CONFIG_VIDEO_SANDBOX_SDL=y CONFIG_VIDEO_DSI_HOST_SANDBOX=y diff --git a/test/cmd/font.c b/test/cmd/font.c index ce694fef7e4..adfeebe920d 100644 --- a/test/cmd/font.c +++ b/test/cmd/font.c @@ -36,6 +36,11 @@ static int font_test_base(struct unit_test_state *uts) ut_assert_nextline("ankacoder_c75_r"); if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE)) ut_assert_nextline("cantoraone_regular"); + if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_UBUNTU_LIGHT)) + ut_assert_nextline("ubuntu_light"); + if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_UBUNTU_BOLD)) + ut_assert_nextline("ubuntu_bold"); + ut_assert_console_end(); ut_assertok(vidconsole_get_font_size(dev, &name, &size)); -- 2.43.0
From: Simon Glass <sjg@chromium.org> The code is present but is not currently enabled. Add Makefile rules so that it is built. Also add a gitignore for bootctl.ini since this file is created when 'bootctl run' is used. Update the Kconfig rule to disable this by default, except for sandbox the EFI app. Add a dependency on CMDLINE since the textline object calls cread_line_process_ch() which is otherwise not available. Signed-off-by: Simon Glass <sjg@chromium.org> --- .gitignore | 2 ++ boot/Kconfig | 4 ++-- boot/Makefile | 2 ++ cmd/Makefile | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6b95c85b9b8..986ab7ffda3 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,5 @@ __pycache__ # Clang's compilation database file /compile_commands.json + +bootctl.ini diff --git a/boot/Kconfig b/boot/Kconfig index b255245335b..cde4472ca57 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -507,8 +507,8 @@ config BOOT_DEFAULTS config BOOTCTL bool "Support for boot control" - depends on BOOTSTD - default y + depends on EXPO && CMDLINE + default y if SANDBOX || EFI_APP help This supports an experimental boot control, providing a way to discover and boot Operating Systems. diff --git a/boot/Makefile b/boot/Makefile index 3cb138ae022..cfa5a0a98e9 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -17,6 +17,8 @@ obj-y += image.o image-board.o bootm_final.o obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o +obj-$(CONFIG_$(PHASE_)BOOTCTL) += bootctl/ + obj-$(CONFIG_$(PHASE_)BOOTSTD) += bootdev-uclass.o obj-$(CONFIG_$(PHASE_)BOOTSTD) += bootflow.o obj-$(CONFIG_$(PHASE_)BOOTSTD) += bootmeth-uclass.o diff --git a/cmd/Makefile b/cmd/Makefile index 1d65703b625..b73725cfe41 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_CMD_AES) += aes.o obj-$(CONFIG_CMD_ADC) += adc.o obj-$(CONFIG_CMD_ARMFLASH) += armflash.o obj-$(CONFIG_BLK) += blk_common.o +obj-$(CONFIG_CMD_BOOTCTL) += bootctl.o obj-$(CONFIG_CMD_BOOTDEV) += bootdev.o obj-$(CONFIG_CMD_BOOTFLOW) += bootflow.o obj-$(CONFIG_CMD_BOOTMETH) += bootmeth.o -- 2.43.0
From: Simon Glass <sjg@chromium.org> All UI implementations will likely share a number of common elements, so move these into a per-device uclass struct. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootctl/bootctl-uclass.c | 2 + boot/bootctl/simple_ui.c | 93 +++++++++++++---------------------- include/bootctl/ui.h | 27 ++++++++++ 3 files changed, 63 insertions(+), 59 deletions(-) diff --git a/boot/bootctl/bootctl-uclass.c b/boot/bootctl/bootctl-uclass.c index f7280b83da3..756702b3e9a 100644 --- a/boot/bootctl/bootctl-uclass.c +++ b/boot/bootctl/bootctl-uclass.c @@ -10,6 +10,7 @@ #include <bootctl.h> #include <dm.h> +#include <bootctl/ui.h> UCLASS_DRIVER(bootctrl) = { .id = UCLASS_BOOTCTL, @@ -42,4 +43,5 @@ UCLASS_DRIVER(bootctrl_ui) = { .id = UCLASS_BOOTCTL_UI, .name = "bootctrl_ui", .per_device_plat_auto = sizeof(struct bootctl_uc_plat), + .per_device_auto = sizeof(struct bc_ui_priv), }; diff --git a/boot/bootctl/simple_ui.c b/boot/bootctl/simple_ui.c index b4b8541ac22..14c6de5bb1e 100644 --- a/boot/bootctl/simple_ui.c +++ b/boot/bootctl/simple_ui.c @@ -25,32 +25,9 @@ /* TODO: Define to 1 to use text mode (for terminals), 0 for graphics */ #define TEXT_MODE 0 -/** - * struct ui_priv - information about the display - * - * @expo: Expo containing the menu - * @scn: Current scene being shown - * @lpriv: Private data of logic device - * @console: vidconsole device in use - * @autoboot_template: template string to use for autoboot - * @autoboot_str: current string displayed for autoboot timeout - * @logo: logo in bitmap format, NULL to use default - * @logo_size: size of the logo in bytes - */ -struct ui_priv { - struct expo *expo; - struct scene *scn; /* consider dropping this */ - struct logic_priv *lpriv; - struct udevice *console; - struct abuf autoboot_template; - struct abuf *autoboot_str; - const void *logo; - int logo_size; -}; - static int simple_ui_probe(struct udevice *dev) { - struct ui_priv *priv = dev_get_priv(dev); + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); struct udevice *ldev; int ret; @@ -58,7 +35,7 @@ static int simple_ui_probe(struct udevice *dev) if (ret) return log_msg_ret("sup", ret); - priv->lpriv = dev_get_priv(ldev); + upriv->lpriv = dev_get_priv(ldev); return 0; } @@ -81,7 +58,7 @@ static int simple_ui_print(struct udevice *dev, const char *msg) static int simple_ui_show(struct udevice *dev) { - struct ui_priv *priv = dev_get_priv(dev); + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); struct bootstd_priv *std; struct scene *scn; struct abuf *buf; @@ -91,30 +68,30 @@ static int simple_ui_show(struct udevice *dev) ret = bootstd_get_priv(&std); if (ret) return log_msg_ret("sdb", ret); - ret = bootflow_menu_setup(std, TEXT_MODE, &priv->expo); + ret = bootflow_menu_setup(std, TEXT_MODE, &upriv->expo); if (ret) return log_msg_ret("sds", ret); - ret = expo_first_scene_id(priv->expo); + ret = expo_first_scene_id(upriv->expo); if (ret < 0) return log_msg_ret("ufs", ret); scene_id = ret; - scn = expo_lookup_scene_id(priv->expo, scene_id); + scn = expo_lookup_scene_id(upriv->expo, scene_id); scene_obj_set_hide(scn, OBJ_AUTOBOOT, false); - ret = expo_edit_str(priv->expo, STR_AUTOBOOT, - &priv->autoboot_template, - &priv->autoboot_str); + ret = expo_edit_str(upriv->expo, STR_AUTOBOOT, + &upriv->autoboot_template, + &upriv->autoboot_str); if (ret) return log_msg_ret("ses", ret); - ret = expo_edit_str(priv->expo, STR_MENU_TITLE, NULL, &buf); + ret = expo_edit_str(upriv->expo, STR_MENU_TITLE, NULL, &buf); if (ret) return log_msg_ret("set", ret); abuf_printf(buf, "Boot control"); - if (priv->logo) { + if (upriv->logo) { ret = scene_img_set_data(scn, OBJ_U_BOOT_LOGO, - priv->logo, priv->logo_size); + upriv->logo, upriv->logo_size); if (ret) return log_msg_ret("log", ret); ret = scene_obj_set_pos(scn, OBJ_U_BOOT_LOGO, 1135, 10); @@ -125,7 +102,7 @@ static int simple_ui_show(struct udevice *dev) log_debug("theme '%s'\n", ofnode_get_name(std->theme)); if (ofnode_valid(std->theme)) { - ret = expo_setup_theme(priv->expo, std->theme); + ret = expo_setup_theme(upriv->expo, std->theme); if (ret) return log_msg_ret("thm", ret); } @@ -135,22 +112,22 @@ static int simple_ui_show(struct udevice *dev) return log_msg_ret("usa", ret); scene_set_highlight_id(scn, OBJ_MENU); - priv->scn = scn; + upriv->scn = scn; - ret = device_find_first_child_by_uclass(priv->expo->display, - UCLASS_VIDEO_CONSOLE, - &priv->console); + ret = device_find_first_child_by_uclass(upriv->expo->display, + UCLASS_VIDEO_CONSOLE, + &upriv->console); if (ret) return log_msg_ret("suq", ret); - vidconsole_set_quiet(priv->console, true); + vidconsole_set_quiet(upriv->console, true); return 0; } static int simple_ui_add(struct udevice *dev, struct osinfo *info) { - struct ui_priv *priv = dev_get_priv(dev); - struct logic_priv *lpriv = priv->lpriv; + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct logic_priv *lpriv = upriv->lpriv; int seq = lpriv->osinfo.count; struct bootstd_priv *std; struct scene *scn; @@ -159,7 +136,7 @@ static int simple_ui_add(struct udevice *dev, struct osinfo *info) info = alist_add(&lpriv->osinfo, *info); if (!info) return -ENOMEM; - ret = bootflow_menu_add(priv->expo, &info->bflow, seq, &scn); + ret = bootflow_menu_add(upriv->expo, &info->bflow, seq, &scn); if (ret) return log_msg_ret("sda", ret); @@ -167,11 +144,11 @@ static int simple_ui_add(struct udevice *dev, struct osinfo *info) if (ret) return log_msg_ret("sup", ret); if (ofnode_valid(std->theme)) { - ret = expo_setup_theme(priv->expo, std->theme); + ret = expo_setup_theme(upriv->expo, std->theme); if (ret) return log_msg_ret("thm", ret); } - ret = expo_calc_dims(priv->expo); + ret = expo_calc_dims(upriv->expo); if (ret) return log_msg_ret("ecd", ret); @@ -187,19 +164,18 @@ static int simple_ui_add(struct udevice *dev, struct osinfo *info) static int simple_ui_render(struct udevice *dev) { - struct ui_priv *priv = dev_get_priv(dev); + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); int ret; - ret = abuf_printf(priv->autoboot_str, - priv->autoboot_template.data, - priv->lpriv->autoboot_remain_s); + ret = abuf_printf(upriv->autoboot_str, upriv->autoboot_template.data, + upriv->lpriv->autoboot_remain_s); if (ret < 0) return log_msg_ret("uip", ret); - ret = expo_arrange(priv->expo); + ret = expo_arrange(upriv->expo); if (ret) return log_msg_ret("sda", ret); - ret = expo_render(priv->expo); + ret = expo_render(upriv->expo); if (ret) return log_msg_ret("sdr", ret); @@ -208,18 +184,18 @@ static int simple_ui_render(struct udevice *dev) static int simple_ui_poll(struct udevice *dev, int *seqp, bool *selectedp) { - struct ui_priv *priv = dev_get_priv(dev); - struct logic_priv *lpriv = priv->lpriv; + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct logic_priv *lpriv = upriv->lpriv; int seq, ret; bool ok = true; *seqp = -1; *selectedp = false; - ret = bootflow_menu_poll(priv->expo, &seq); + ret = bootflow_menu_poll(upriv->expo, &seq); ok = !ret; if (ret == -ERESTART || ret == -EREMCHG) { lpriv->autoboot_active = false; - scene_obj_set_hide(priv->scn, OBJ_AUTOBOOT, true); + scene_obj_set_hide(upriv->scn, OBJ_AUTOBOOT, true); ok = true; } else if (ret == -EAGAIN) { ok = true; @@ -241,9 +217,9 @@ static int simple_ui_poll(struct udevice *dev, int *seqp, bool *selectedp) static int simple_ui_of_to_plat(struct udevice *dev) { - struct ui_priv *priv = dev_get_priv(dev); + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); - priv->logo = dev_read_prop(dev, "logo", &priv->logo_size); + upriv->logo = dev_read_prop(dev, "logo", &upriv->logo_size); return 0; } @@ -270,5 +246,4 @@ U_BOOT_DRIVER(simple_ui) = { .bind = simple_ui_bind, .probe = simple_ui_probe, .ops = &ops, - .priv_auto = sizeof(struct ui_priv), }; diff --git a/include/bootctl/ui.h b/include/bootctl/ui.h index 8333ff199dd..beb11178c52 100644 --- a/include/bootctl/ui.h +++ b/include/bootctl/ui.h @@ -10,11 +10,38 @@ #define __bootctl_display_h #include <stdbool.h> +#include <abuf.h> +struct expo; +struct logic_priv; struct osinfo; struct oslist_iter; +struct scene; struct udevice; +/** + * struct bc_ui_priv - Common uclass private data for UI devices + * + * @expo: Expo containing the menu + * @scn: Current scene being shown + * @lpriv: Private data of logic device + * @console: vidconsole device in use + * @autoboot_template: template string to use for autoboot + * @autoboot_str: current string displayed for autoboot timeout + * @logo: logo in bitmap format, NULL to use default + * @logo_size: size of the logo in bytes + */ +struct bc_ui_priv { + struct expo *expo; + struct scene *scn; + struct logic_priv *lpriv; + struct udevice *console; + struct abuf autoboot_template; + struct abuf *autoboot_str; + const void *logo; + int logo_size; +}; + /** * struct bc_ui_ops - Operations for displays */ -- 2.43.0
From: Simon Glass <sjg@chromium.org> For now just drop to the cmdline so that the state can be examined. This will aid debugging. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootctl/bootctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/bootctl/bootctl.c b/boot/bootctl/bootctl.c index 9fa943222db..7155ff0a8f0 100644 --- a/boot/bootctl/bootctl.c +++ b/boot/bootctl/bootctl.c @@ -58,7 +58,8 @@ int bootctl_run(void) ret = bc_logic_poll(logic); if (ret) { printf("logic err %dE\n", ret); - hang(); + /* could hang here */ + return ret; } } while (ret != -ESHUTDOWN); -- 2.43.0
From: Simon Glass <sjg@chromium.org> When a mouse pointer is not used, there is typically no need to refresh the display unless something changes. Add an option to allow slow refresh. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootctl/logic.c | 3 ++- include/bootctl/logic.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/boot/bootctl/logic.c b/boot/bootctl/logic.c index c0b7b8ae3d5..e2ec2c679ec 100644 --- a/boot/bootctl/logic.c +++ b/boot/bootctl/logic.c @@ -219,7 +219,7 @@ static int logic_poll(struct udevice *dev) priv->refresh = true; } - if (priv->refresh) { + if (!priv->opt_slow_refresh || priv->refresh) { ret = bc_ui_render(priv->ui); if (ret) return log_msg_ret("bdr", ret); @@ -286,6 +286,7 @@ static int logic_of_to_plat(struct udevice *dev) priv->opt_labels = ofnode_read_string(node, "labels"); priv->opt_autoboot = ofnode_read_bool(node, "autoboot"); priv->opt_measure = ofnode_read_bool(node, "measure"); + priv->opt_slow_refresh = ofnode_read_bool(node, "slow-refresh"); return 0; } diff --git a/include/bootctl/logic.h b/include/bootctl/logic.h index a0c2ab9f496..1aefac29128 100644 --- a/include/bootctl/logic.h +++ b/include/bootctl/logic.h @@ -26,6 +26,7 @@ struct udevice; * be used to boot * @opt_autoboot: true to autoboot the default OS after a timeout * @opt_measure: true to measure loaded images, etc. + * @opt_slow_refresh: refresh the UI only when needed * * @state_loaded: true if the state information has been loaded * @scanning: true if scanning for new OSes @@ -55,6 +56,7 @@ struct logic_priv { const char *opt_labels; bool opt_autoboot; bool opt_measure; + bool opt_slow_refresh; bool state_loaded; bool state_saved; -- 2.43.0
From: Simon Glass <sjg@chromium.org> When autoboot is disabled, hide the prompt. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootctl/simple_ui.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/bootctl/simple_ui.c b/boot/bootctl/simple_ui.c index 14c6de5bb1e..3ef00651c05 100644 --- a/boot/bootctl/simple_ui.c +++ b/boot/bootctl/simple_ui.c @@ -59,6 +59,7 @@ static int simple_ui_print(struct udevice *dev, const char *msg) static int simple_ui_show(struct udevice *dev) { struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct logic_priv *lpriv = upriv->lpriv; struct bootstd_priv *std; struct scene *scn; struct abuf *buf; @@ -78,7 +79,7 @@ static int simple_ui_show(struct udevice *dev) scene_id = ret; scn = expo_lookup_scene_id(upriv->expo, scene_id); - scene_obj_set_hide(scn, OBJ_AUTOBOOT, false); + scene_obj_set_hide(scn, OBJ_AUTOBOOT, !lpriv->opt_autoboot); ret = expo_edit_str(upriv->expo, STR_AUTOBOOT, &upriv->autoboot_template, &upriv->autoboot_str); -- 2.43.0
From: Simon Glass <sjg@chromium.org> If a different UI is used then the theme may have changed, so re-apply the theme when showing the UI. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootctl/simple_ui.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/boot/bootctl/simple_ui.c b/boot/bootctl/simple_ui.c index 3ef00651c05..7fb59c8b8c3 100644 --- a/boot/bootctl/simple_ui.c +++ b/boot/bootctl/simple_ui.c @@ -60,6 +60,7 @@ static int simple_ui_show(struct udevice *dev) { struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); struct logic_priv *lpriv = upriv->lpriv; + struct expo_theme *theme; struct bootstd_priv *std; struct scene *scn; struct abuf *buf; @@ -107,6 +108,12 @@ static int simple_ui_show(struct udevice *dev) if (ret) return log_msg_ret("thm", ret); } + theme = &upriv->expo->theme; + theme->white_on_black = true; + + ret = expo_apply_theme(upriv->expo, true); + if (ret) + return log_msg_ret("asn", ret); ret = scene_arrange(scn); if (ret) @@ -144,11 +151,11 @@ static int simple_ui_add(struct udevice *dev, struct osinfo *info) ret = bootstd_get_priv(&std); if (ret) return log_msg_ret("sup", ret); - if (ofnode_valid(std->theme)) { - ret = expo_setup_theme(upriv->expo, std->theme); - if (ret) - return log_msg_ret("thm", ret); - } + + ret = expo_apply_theme(upriv->expo, true); + if (ret) + return log_msg_ret("asn", ret); + ret = expo_calc_dims(upriv->expo); if (ret) return log_msg_ret("ecd", ret); -- 2.43.0
From: Simon Glass <sjg@chromium.org> Provide some sample images for use with the 'multi' theme. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/video/images/Makefile | 5 +++++ drivers/video/images/canonical.bmp | Bin 0 -> 14258 bytes drivers/video/images/help.bmp | Bin 0 -> 1782 bytes drivers/video/images/multipass.bmp | Bin 0 -> 4378 bytes drivers/video/images/settings.bmp | Bin 0 -> 1782 bytes drivers/video/images/tick.bmp | Bin 0 -> 822 bytes test/dm/video.c | 7 ++++++- 7 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 drivers/video/images/canonical.bmp create mode 100644 drivers/video/images/help.bmp create mode 100644 drivers/video/images/multipass.bmp create mode 100644 drivers/video/images/settings.bmp create mode 100644 drivers/video/images/tick.bmp diff --git a/drivers/video/images/Makefile b/drivers/video/images/Makefile index 9019b36c918..8e719691880 100644 --- a/drivers/video/images/Makefile +++ b/drivers/video/images/Makefile @@ -10,3 +10,8 @@ endif ifdef CONFIG_$(PHASE_)GENERATE_ACPI_TABLE obj-y += bgrt.o endif + +obj-$(CONFIG_BOOTCTL) += canonical.o +obj-$(CONFIG_BOOTCTL) += tick.o +obj-$(CONFIG_BOOTCTL) += multipass.o settings.o +obj-$(CONFIG_BOOTCTL) += help.o diff --git a/drivers/video/images/canonical.bmp b/drivers/video/images/canonical.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0b40d9f8e5bcab5d0465e71029e37d48ae368fba GIT binary patch literal 14258 zcmdU$`I8ex6vxLO{2%<$TfEN#JW=s13oT1T5fMRA5fxAryiiaS6e&Sayto8J<q!n~ zl}kWH1O((#5Kt60n?17GWV6|9@IwYVou2NQo@}z{7D>H%>3Q#c`+P@pb*C@dIk~^K ze7E6q9iNVTj&Y9T+i{-b_ld{4pB#g)ga3iQ=Ip_x>lz17sJpg*)j2&PZSIP6cqIDJ z>$S6%H6&8mum+YB6PErJ$t>T{_`#QnVUyyR{O}vKU#x0SY+SP?ebbXw$9JyK{%hO2 za^{kx@{0ds88B7WHZS--HDGM)+#V6d%yzviWAz37K5;?fq&xIz<aZx`E7q7Uc+m$| z=`bZzSvs`SAY+eX<D3-*gY?Og2H9|bnlaAWp(+KYit6T<Cda*_qS(kFrJM3rZQ9jz zvc(9=LZ&XVnuIOG)X<oHYgYXkcdK(uHbl@Prp4t6(`{&t_{owuzh`A#BHt^rG?{Jz zrp0Sg7e82OX%5X+ZE6&nx9)DTe^G8Z<*VSKDhg97oqhiOI$2d9eZuV(46491=Ck_1 zSF{bf4XY7COhkB0yZ+AHIM8n+(AvVZkxk(2(KZWYUeK#Rjx1BqAu(<IJ$>H2A?6!4 zvUhZTu6oprdZ82I)@P~%&DS<yyaPA&FqnSal0LJ$)pme6;F$1vV$1F(?FP)RT9X5r zC*EGsl#zQ!LtA57wXqSGB~T}O;P5H&o%;gxJ~BEMC`#La13`nLkY$Gn8*#(5N(A%N zu92Y=<I&pYLIwIK+z0VuD5B4(TD?SxYk{e@K6~Y(QGd<XKVJ3gA5D_n0CHa>!z}Wb zsr_}{%Dg8MPi7TQ%hei$iPdoTuz<ty)sNzVbKHxu|Jcye@2W?mvZ7CyHuN78^GXiF zG;MKG+g~md_mc)*sWzN{qM1-zDC4?peg4!&Mb{S(b@u1d$hmrbG3~EvKKmZyGQwN? zc5TYWd{dk6H#eSgr%}Grm*eLoWI1fYZUYuNcFI5bV(LB8crwy!^3;|^hN9PQOJ8_j zz=3yCmx_1h764)f-aI&e8Vq{7PF8Bhw0_6oj!^o`eZ+N@#k7PzP~AM}ojOw#g{zAP zugD)cEiPLH=pB3WZOoYN9d6tj?s~B%Q!v_!%3>ZPHO(`=Nj@<ycF)T-cMPfS_hyXA z_S;{1ONG$6-!<S($e5sey_(<S4Vc)Nz3;hVSYhZF8d{kkjAT?4Ks;itIOq+SHvE?U z>c<q59rt0;n$)=2^$)&Q>pDgs&M%nSt&9nO%L~Zm5SO~f7%*uqB|0b3AfFK0W@TmK zz+Toz?*MQzxZz9~Ol39JUN~W)X{hF}K6JMH4>6JPGvz*>9Dm5IFksrVKf^S`)1168 z$$Hu!J!+eRcKq1;wL?WR5NECs6Fc<GZ<E&zP{UYu70$SYKcuw5kXCJ3nWQ$fm|$+( z(<EWqb09b<zw?C}%V?skn8>M}(M|7E;n*I*#DPT0zyx0AU)m>1q)=9qZG@Ymh2c}< zIZT|P?ZafX$gvcWnzymkz75f|+|z=_p~zt>B9s~RamoBWdmM60Q(l_r)N%0siU>JR z?-r?w9nH;<SW1kIOt3T@haQ)C_H@`1irmXBr#J1?XL8T#9&wyoq(H<T5G`%e9WA%r zB!MiO)><M}$GIpdB-6eMlg=<HYz6-2U3yHpaUzFhvf7_dd9oF3H>n`**P4eb;W%Ug zwLb<jZ+rG=juWXBt%c;49H+~Wd|<C_Wnxm@G<9Mt@J*Ew!eqxGePOcNpa13ReEP5z zKqx9ql@W?aj`MeAridj)%_Px~uO}%A%l(Ke&AQQcIW_*AAMx^Jy`Q0d$z@JjP-LpI zBye%QO}3Hl%3&hpmD6RW=7Qh-rJAD~!N2*b-cP_;$FLkG`i`jYntp27BtXan+nr6J zxFqAD6~e^3qOU$BfwRslM=(KRDR&TL^A(yT6e}>WOs6%ZgiLPnD29p0k8;U-36rb# z=k4jfqYtOOL|a0uf#YI3{?ud;OK7a6C{vA*Os*TRdN8?y84Plut2Z}t8Hik9$+NDO z=4+eHUD2Suk<s&&!zFnGCatjl4wG*72C-b$axDyxsk*Lt$-06%PzkXTK9i<m)!sLv z76%8{|F!9H(!pFYQ~t<owSORgL=k$6{7)E6M2~17!|W|@DGG~t<UDzMZo*VG?$|F1 zRz>W(9cfVwkqbw@m>A9JUneQcP;R*V;ezdxtRX$6C@K1pqL|GANu^W141>C{x%)8O zwvY$X7t_j(#$A&wk;_J;&x*z&UgTPtcX5a<S0PBD$mVlP2s3{9JuRd`_+sLB>OhKA z`SFs6qAeUPcGR$UT9ow8?tj#N4Z=jR-c(0$!BI^R8;;yrmNZEXxsz;YO2Gc}BM1|w zu@wCsceaetGwbF1hL(V6X7Y0U!9Dw4K>=4$XMu?~W-r$Vm9l0+`4vY_2t|qM(Ud2V z#cFACDDtXO<lAB5C3lC>YLJ<Dk(3q{C8kI2g39lPqJ7q}H74xhzM7@l8=k15!pu!S z6B?IqFVL$Or_Cfh3?^i}J1=3XU3=BS>CiWdM@$ixi>5zqP2)p~(;jJD>e0Ss!}OUA zAu(YHCpL*?8@1Xta?PGNTieElsl8_4j$C+5ytjRC)76g^xD_^5xNV4KT+Mu&a&&>x z@Xvh0xS}v&4mEgg>lINvkS`t+XNS5*C9o2^ijMIT#bR<L;gk@{3spA6{UZv@DXs#6 zr|yL!I4#437}h)<v(JAbQGntF@E<ya{`zEA4jGij+DHFELUM~Sxz>S<1DCrl!ui*l z<1&>y%w+TJHywfw?cGYzNu|RiM3NC8JR!krsv!f5pSX}HUV$J<V6(6~Jym6MtD!{W zBpc|`tbevRc7&%V)NzlDL>pGS<H7xBZ|!RDfecH{G`gpCjl427&c@_b<mHqNlUJ1u dhw2{(F{=}gj_MdojSHgh%}XdZDg8w`&cB6mH7Ni9 literal 0 HcmV?d00001 diff --git a/drivers/video/images/help.bmp b/drivers/video/images/help.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3b010e3310ff65a0d48a2d4d24385b0ce75ee1b9 GIT binary patch literal 1782 zcmb7_drVtp7{+TN9TgUuf^5oVlyav9);dsNg&m+5$8|I5MwoWaWRi(78ACK~!3c!{ zV{{auv~=7CrBFn+#D9!&8Z~2M*{q}Y_7r-7OlKe&)(z0Nr={y~nfm2DCtuogetDkf zea|^a$r>JqtxPy4!Li$WJcsRYxNp7xV;B9)DIfsHW)P1dVf?~ysAEVtCzA+2{`Zwm zCe)NfD$Zu#ke2C{RkkZ9Y**hgsNTGJsY20^TT>pDK@NU4ZO0DW@q%#GIfiAl*fCM! zP;wpPY$&Ia<DB3wsfw4UD^O+GbmObX*}LK5r>>Vt&(|G_nCs5Bk8y0Hg;4gfLc5{} z%AsIkG`4es<DBF!e^GWv&aOX7jvx`Xp#WZ25vh?Pwh`9iFtRv;*e*jA0L?MZaSMBr zwlr0&AK`v{l)Oz9KR@)QX#e6+;lkj7g`oqBLx_iFA3wOhc5i*{H?X-S%&QG--jT7u zpidGt8n3LQE({i0<$2ai`3nR2UfM8XSCni%d;sN`EO*-+^VwuMl<Xx{=~Tl$dYm`* z>Y^~c6hY;AsGNzR{Aq||;;=*YhRy91Y!*Bbnv!i9J6Ka10g_-O`cEaGa>OFbMf>-= z%SQuYm^PoyEt<Cl5SnwMc<2lbAgr{YZyFh>jA`l1u}E{hG&$2pTe&^(>-SCI^f3*D zT`sVD8amGTp)>b&29cMw^HxW;MUrcgWMe1~%_ofc0R8R{+x5qxZM9&_W|3N2RGAl6 zl@p?Fqw3q^_2=UZ=i?0>@rDZt#?AzzDA6cNGF?n^&Yb*fbHg#sH+QF6K2NpuP%XVw zR6;`~Y1Y0pt29H`m&r$7ta>d(-I}UvrRduz`t~?C4NzVhpb`Of|GId?wPI6Ln7dQV zfWl~KFQ8~>U%FnhkB@}%vVvznO9GCrHC6{Ge;NpLYje|9)C!m)m<qEv1!!JjJs>Ro zwrFo9Gn7Lkd|e+49Bm6(Cxi_~Yj<n&w`mfmZ~VEsdUw*)m246x`)I(qCZKWY#2`FQ zb|O;SnxJit(YC~Bg<cvajN%`fYxx(~vf2|G(9A#sVZHQ$_b7Pmg>*8X__H8UBOq%8 zdoUW=O>2!c_2d}4=$_CP6}-)jN2_<IJT@UTcZpMVV)`jgnCH=;zJwpGj?}coYnq|~ zr4ht<X!mEOn~z+s<$2eVdUIp_;qO+oA8~hcD>QR=y7F`!gYts!5qm3p=Z|M88bR!Q zW3;9TP?)f0vUT|I(pUBOt_dAiJ}`8`ctB`aLoXzlx>9FbsQf&V4+5LOK-_5-Y3|cF z3>BsEr$K1{Xo0aaMcq!VFW*Jj{szMBAqLd4Nk28DXoSi0jWL)oKW!~oXwcBMc;m&4 z8^XP3O2gq6e=)v&AP&dR37PqjZjhCkdJug_hE|B>-wd}W8$=AVjAb4?boE^3+j%6g z@a&Zlg@3;&eDb60ISJ38c-Qu2t!<{(I9`2ATB-VkS;N^yi~1km9T*8NmB4!?_()dJ Sk*r`|W-yCN@XX0mW&91`SI$EK literal 0 HcmV?d00001 diff --git a/drivers/video/images/multipass.bmp b/drivers/video/images/multipass.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3816907bf20ab6ab9e777cb97a9f82cf10b7f361 GIT binary patch literal 4378 zcmeH{%}*0S7{<5%0p5rQVge+79K6*EoKO=lDketMh7&1JBvSRF#*c=CL=){nZ>>tW z8W95F;{fF|A;whCc=ponZo9jsEf!jQ=xiqM?yM$Flz5oU%;cSCpZC{y-%h6U($OPI z?eSwhj@g8H8q=pVVpWtM4T_TVu~`$a9J`kOM?<p3#vW=<TDsGBUz->R#8O11^+x92 z8#ChN7wVo|EA7{wsr8ab5|!x<+y80R?HAa(Sz+v4zCuYSgPG`i>)AW&L@+~j*q9%Q zR7WhZKQ7yKOsqKSSW5k5jKwcIlrgz#`#&TdelK=&clvhB7>bz)D5FrSGByIL!v-@_ zny)+jUhF`>`Xpgtob6XBgZ~dGl<I8*+T-|vABj}=VqbocW%YGE%u+Av8+>JiUmC9O zx%$ZVBa!;+VYi31(eXS60?POsY<vd$o-5A!BpYp!J>kdge?KP|@9XRw-;CyX(FlSg zIi}xo>ew<JiPVo+xCc-5WOnxs-0|rG^^VUM8Dng=NcF@_0XkA}2~*vR4Q=7`4(#RK zDsCWuNDcI<BV&2?gA9X<{7gv2c>30Y4dUFU<KksMBGe7JBdnR*_Kk`>{$#BR2H*0) z*skI>WIVchvGM-=u>S3PnP($NZIvNji0EIp96GkpDU!#(VYBz0ceLK;M(BlsfM*~$ sH>^R#E0<0^i2ulTdF$Ouw%9S*6WJ571EM0&iR_8k0a20X<gk143;KPK<p2Nx literal 0 HcmV?d00001 diff --git a/drivers/video/images/settings.bmp b/drivers/video/images/settings.bmp new file mode 100644 index 0000000000000000000000000000000000000000..528488230f602264cf4a61472c0c1b81a0ad3224 GIT binary patch literal 1782 zcma)+$xB;N6vop<91yxLx^UZtqD1H)&_x^|5wTH85UNH<5NAwuW6%&x7OsS>BAA^- z5u;Y)kU@huD-LmvacZ*cuIv8#t_FFvwg=whoO{3X-80?$S@SbPA;~BHANf8!eeWbq zp@^^_eJ?%<_{LAERF;;O*4Nj6l?0`%tc=AsTx45CMMbTxtv;V`e}6w7kAIg0<>268 za&of0y}h`&Smq)#Gcz+A8XBgirto@ve0+F#xWB*Wk6^-=OePbFgx~K623Y1U%-q~u zi^a0LyNmDL-QCjClGEvIZf^b}35v_*3I>CM@bK`kudgpJFHc4Vc~4JIEEc=Hz1`m4 z?&|8&Jd4q2Y-(zHwlv+{-6TkCmzS4N$)ci`J3BkXyu7?zS68RiYWw^9sV(l`BtgMs zku3n>a2P5GNiZE!K|#U9!~`Tn0tT1r>S}bdpxR`LpkT7d764#$0V;~AQmF)$$z(b^ zJG;KVCLN9gNlBv7=-%Gm#>NI!otc^0+}y-mTU%ob05HJRpN_P&w7|nicsw4=`T2Pc zB61D|k5?cN7#<#G5#cPFE~o$iV{v6=g^;{nFC=QUIur_BU0pdG4z?%)@q>4}-Bndp zv$L}_k#Qmbc3ET#fG8auBqSoQsHmu|ttEYm-`Lm)5}_1ZTU$Dv4qr0D5n&Otrly81 zbb(|Tn2@8RBfVa4Fc?lwPA)Dk$eI?@9B4VBva*seB#x)w$jHdRzyK)&0LCzI7IQ)j zv|I3;pP#3BaQhz~4#g$SLtab{JhHs#%gekNj6d^&ifLiC$%|V|-QXD<93<;k>)h7X z1_`^eIu8vE!9(!n<>fg!IisVa@K92aHk*yMvPE_a3k!eiJ21ci$ZKqDEF<Ihi$&R~ z`RVCtM@I+eO7~JehYTdlVh%;hJRnRR4Kka}VxGAd<KyFu^y=y=o#h}3NL1uYS#YO8 zD3~m=1%RqD;Wsxote2FO2p;~Fg%b&BZf*`Lq9SrJY^=~_d@;p6g@jS(9?>8=o+d%b z%F62O?Bwb}6^TSBERI5G3i51e$bEf%o%ugLKJM-9&Cbq#$%CGspU)K_a%v9S^z^jd zZf6)s1Yznhxh52ZvXHFRYQ;rHB21#fkuEUpG=f9nq;80C7tieC;vz7>uacw}dBzEz o>yK|LmHHtG3iHnqJQsz9g=z3V6-I)mfRgfLAt;z)PG0r>1@dtlU;qFB literal 0 HcmV?d00001 diff --git a/drivers/video/images/tick.bmp b/drivers/video/images/tick.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7529183f049188d12d01dd5907369f0e7c657d42 GIT binary patch literal 822 zcmah{OR~Zs5XABVZ|M;{fg9gKAwqbTo+)Q=XO#+ArE72K>tPZgAInsrhM_w%-4l6O z%|(1x*q2y8?V5>2%nRJV+QkVW-u<UKSGB9OrxyW^{rh}6JU7Ny#;egQag}i~GJb2q z7@0HnrV_>8YzfvAC5V`+XqUgEowO%AYKZ`Vp~S|a?G_J#TvXq6N|piSCyh)`O&+i7 z63KBLWJ>PtJAko+*fb4d^0q78;dAFy$hCAx7H=AjxtP+5Iw<|YMpR)6xz|;J!2RPl z9S1?}CCm9EPiT}pZd0fjP)zg?d(3}vug47vjd3~Bh5w;zav~s&+XUu-W;E3pgqL3) Rupl3fk#G2=gTnL&fPWQ&oDu*4 literal 0 HcmV?d00001 diff --git a/test/dm/video.c b/test/dm/video.c index 616aee3f84d..a2c654831b9 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -1303,10 +1303,15 @@ static int dm_test_video_images(struct unit_test_state *uts) ut_assert_nextline("Name Size"); ut_assert_nextline("-------------------- ----------"); ut_assert_nextline("bgrt 43926"); + ut_assert_nextline("canonical 14258"); + ut_assert_nextline("help 1782"); + ut_assert_nextline("multipass 4378"); ut_assert_nextline("riscos_arrow 3798"); + ut_assert_nextline("settings 1782"); + ut_assert_nextline("tick 822"); ut_assert_nextline("u_boot 6932"); ut_assert_skip_to_line(""); - ut_assert_nextline("Total images: 3"); + ut_assert_nextline("Total images: 8"); ut_assert_console_end(); return 0; -- 2.43.0
From: Simon Glass <sjg@chromium.org> Provide an operation to switch to a different layout, for use with the upcoming 'multi' UI. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootctl/util.c | 15 +++++++++++++++ include/bootctl/ui.h | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/boot/bootctl/util.c b/boot/bootctl/util.c index ec8de21815d..48912c67f21 100644 --- a/boot/bootctl/util.c +++ b/boot/bootctl/util.c @@ -95,6 +95,21 @@ int bc_ui_poll(struct udevice *disp, int *seqp, bool *selectedp) return ret; } +int bc_ui_switch_layout(struct udevice *dev) +{ + struct bc_ui_ops *ops = bc_ui_get_ops(dev); + int ret; + + if (!ops->switch_layout) + return -ENOSYS; + + ret = ops->switch_layout(dev); + if (ret) + return log_msg_ret("bsl", ret); + + return 0; +} + void bc_oslist_setup_iter(struct oslist_iter *iter) { memset(iter, '\0', sizeof(struct oslist_iter)); diff --git a/include/bootctl/ui.h b/include/bootctl/ui.h index beb11178c52..4f8e08a00c2 100644 --- a/include/bootctl/ui.h +++ b/include/bootctl/ui.h @@ -91,6 +91,14 @@ struct bc_ui_ops { * -ve on error */ int (*poll)(struct udevice *dev, int *seqp, bool *selectedp); + + /** + * switch_layout() - Switch between different UI layout modes + * + * @dev: Display device + * Return 0 if OK, -ve on error + */ + int (*switch_layout)(struct udevice *dev); }; #define bc_ui_get_ops(dev) ((struct bc_ui_ops *)(dev)->driver->ops) @@ -132,4 +140,12 @@ int bc_ui_render(struct udevice *dev); */ int bc_ui_poll(struct udevice *dev, int *seqp, bool *selectedp); +/** + * bc_ui_switch_layout() - Switch between different UI layout modes + * + * @dev: Display device + * Return 0 if OK, -ve on error + */ +int bc_ui_switch_layout(struct udevice *dev); + #endif -- 2.43.0
From: Simon Glass <sjg@chromium.org> Add a new 'multi' UI which can display in a simple format (like GRUB) as well as a more modern format with a mouse. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootctl/Makefile | 1 + boot/bootctl/multi_ui.c | 588 ++++++++++++++++++++++++++++++++++++++++ include/bootctl.dtsi | 9 +- 3 files changed, 597 insertions(+), 1 deletion(-) create mode 100644 boot/bootctl/multi_ui.c diff --git a/boot/bootctl/Makefile b/boot/bootctl/Makefile index 4ed842fa752..0288fc038ad 100644 --- a/boot/bootctl/Makefile +++ b/boot/bootctl/Makefile @@ -11,4 +11,5 @@ obj-y += logic.o obj-y += simple_meas.o obj-y += simple_state.o obj-y += simple_ui.o +obj-y += multi_ui.o obj-y += util.o diff --git a/boot/bootctl/multi_ui.c b/boot/bootctl/multi_ui.c new file mode 100644 index 00000000000..adf48808c0f --- /dev/null +++ b/boot/bootctl/multi_ui.c @@ -0,0 +1,588 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Provides a 'multiboot' menu on a graphical display + * + * This is based on Heinrich's design shared in late August. + * + * Copyright 2025 Canonical Ltd + * Written by Simon Glass <simon.glass@canonical.com> + */ + +#define LOG_CATEGORY UCLASS_BOOTCTL + +#include <alist.h> +#include <bootctl.h> +#include <bootstd.h> +#include <dm.h> +#include <expo.h> +#include <video.h> +#include <video_console.h> +#include <bootctl/logic.h> +#include <bootctl/oslist.h> +#include <bootctl/ui.h> +#include <bootctl/util.h> +#include "../bootflow_internal.h" +#include "../scene_internal.h" + +enum { + /* Bar on the left */ + BAR_X = 0, + BAR_Y = 0, + BAR_W = 70, + BAR_H = 800, + + HELP_Y = 675, + SETTINGS_Y = 720, + + MAIN_X = 150, + MAIN_Y = 150, + + IMAGES_Y = 225, + BOX_W = 300, + BOX_H = 300, + BOX_MARGIN = 10, + + // gap between boxes + GAP_X = 20, + GAP_Y = 20, +}; + +/** + * struct multiboot_ui_priv - Driver-specific private data for multiboot UI + * + * @use_bootflow_props: true to use bootflow_menu_set_props(), false for multiboot_ui_set_props() + */ +struct multiboot_ui_priv { + bool use_bootflow_props; +}; + +static int multiboot_ui_probe(struct udevice *dev) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct udevice *ldev; + int ret; + + ret = uclass_first_device_err(UCLASS_BOOTCTL, &ldev); + if (ret) + return log_msg_ret("sup", ret); + + upriv->lpriv = dev_get_priv(ldev); + + return 0; +} + +static int multiboot_ui_bind(struct udevice *dev) +{ + struct bootctl_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->desc = "Graphical or textual display for user"; + + return 0; +} + +int setup_version(struct expo *exp, int i, const struct bootflow *bflow, + const char **versp) +{ + const char *vers = NULL; + struct abuf *buf; + char *str; + int ret; + + ret = expo_edit_str(exp, STR_DESC + i, NULL, &buf); + if (ret) + return ret; + abuf_printf(buf, bflow->os_name ? bflow->os_name : bflow->name); + + str = buf->data; + if (!strncmp("Ubuntu", str, 6) && strlen(str) > 20) { + /* get the space string after the 24.04[.1] */ + char *p = strchr(str + 8, ' '); + + /* get the space after that */ + char *q = p ? strchr(p + 1, ' ') : NULL; + + vers = str + 7; + if (q) + *q = '\0'; + else + *p = '\0'; + } + + if (versp) + *versp = vers; + + return 0; +} + +static int multiboot_set_item_props(struct scene *scn, int i, + const struct bootflow *bflow) +{ + struct expo *exp = scn->expo; + struct abuf *buf; + int x, y, ret = 0; + + x = MAIN_X + i * (BOX_W + GAP_X); + y = IMAGES_Y; + + ret = setup_version(exp, i, bflow, NULL); + + scene_obj_set_bbox(scn, ITEM_BOX + i, x, IMAGES_Y, + x + BOX_W, IMAGES_Y + BOX_H); + scene_obj_set_hide(scn, ITEM_BOX + i, false); + + scene_obj_set_pos(scn, ITEM_DESC + i, x + BOX_MARGIN, + IMAGES_Y + 80); + scene_obj_set_pos(scn, ITEM_LABEL + i, x + BOX_MARGIN, + IMAGES_Y + 80 + 20); + scene_obj_set_pos(scn, ITEM_VERSION_NAME + i, x + BOX_MARGIN, + IMAGES_Y + 80 + 70); + scene_obj_set_pos(scn, ITEM_PREVIEW + i, x + BOX_MARGIN, + IMAGES_Y + 5); + scene_obj_set_pos(scn, ITEM_VERIFIED + i, + x + BOX_MARGIN + 40 + 32, IMAGES_Y + 80 + 21); + + ret |= scene_obj_set_hide(scn, ITEM_PREVIEW + i, false); + ret |= scene_obj_set_hide(scn, ITEM_BOX + i, false); + ret |= scene_obj_set_hide(scn, ITEM_VERSION_NAME + i, false); + ret |= scene_obj_set_hide(scn, ITEM_VERIFIED + i, false); + + /* Hide key in multiboot mode (not used with mouse) */ + ret |= scene_obj_set_hide(scn, ITEM_KEY + i, true); + if (ret) + return log_msg_ret("msp", ret); + + /* Set font sizes for multiboot UI */ + ret = scene_txt_set_font(scn, ITEM_LABEL + i, "ubuntu_light", 18); + ret |= scene_txt_set_font(scn, ITEM_DESC + i, "ubuntu_bold", 20); + ret |= scene_txt_set_font(scn, ITEM_VERSION_NAME + i, NULL, 18); + if (ret) + return log_msg_ret("msq", ret); + + ret = expo_edit_str(exp, STR_LABEL + i, NULL, &buf); + if (!ret) + abuf_printf(buf, "Canonical"); + + return 0; +} + +static int multiboot_ui_set_props(struct udevice *dev, struct scene *scn, + struct bootstd_priv *std) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct logic_priv *lpriv = upriv->lpriv; + struct expo *exp = scn->expo; + struct expo_theme *theme = &exp->theme; + struct abuf *buf; + int i, ret = 0; + + /* Set multiboot-specific strings */ + ret = expo_edit_str(exp, STR_PROMPT1B, NULL, &buf); + if (!ret) + abuf_printf(buf, "Select image to boot"); + + ret = expo_edit_str(exp, STR_PROMPT2, NULL, &buf); + if (!ret) + abuf_printf(buf, "Images"); + + /* Show multiboot-specific objects */ + scene_obj_set_hide(scn, OBJ_BOX, false); + scene_obj_set_hide(scn, OBJ_OTHER_LOGO, false); + scene_obj_set_hide(scn, OBJ_SETTINGS, false); + scene_obj_set_hide(scn, OBJ_HELP, false); + scene_obj_set_hide(scn, OBJ_POINTER, true); + scene_menu_set_pointer(scn, OBJ_MENU, 0); + + /* Enable mouse for multiboot UI */ + expo_set_mouse_enable(exp, true); + + /* Use manual positioning for menu */ + scene_obj_set_manual(scn, OBJ_MENU, true); + + ret = expo_edit_str(upriv->expo, STR_MENU_TITLE, NULL, &buf); + if (ret) + return log_msg_ret("set", ret); + abuf_printf(buf, "Welcome to Multiboot"); + + scene_obj_set_halign(scn, OBJ_MENU_TITLE, SCENEOA_LEFT); + scene_obj_set_pos(scn, OBJ_MENU_TITLE, MAIN_X, 50); + + scene_obj_set_pos(scn, OBJ_PROMPT1B, MAIN_X, 120); + scene_obj_set_halign(scn, OBJ_PROMPT1B, SCENEOA_LEFT); + + scene_obj_set_pos(scn, OBJ_PROMPT2, MAIN_X, 180); + scene_obj_set_halign(scn, OBJ_PROMPT2, SCENEOA_LEFT); + + scene_obj_set_hide(scn, OBJ_AUTOBOOT, !lpriv->opt_autoboot); + + if (upriv->logo) { + ret = scene_obj_set_pos(scn, OBJ_U_BOOT_LOGO, 1045, 10); + if (ret) + return log_msg_ret("lop", ret); + } + + scene_obj_set_bbox(scn, OBJ_BOX, BAR_X, BAR_Y, BAR_X + BAR_W, + BAR_Y + BAR_H); + scene_box_set_fill(scn, OBJ_BOX, true); + + scene_obj_set_bbox(scn, OBJ_OTHER_LOGO, BAR_X, BAR_Y, BAR_X + BAR_W, + BAR_Y + 50); + scene_obj_set_halign(scn, OBJ_OTHER_LOGO, SCENEOA_CENTRE); + + scene_obj_set_bbox(scn, OBJ_SETTINGS, BAR_X, SETTINGS_Y, BAR_X + BAR_W, + SETTINGS_Y + 24); + scene_obj_set_halign(scn, OBJ_SETTINGS, SCENEOA_CENTRE); + + scene_obj_set_bbox(scn, OBJ_HELP, BAR_X, HELP_Y, BAR_X + BAR_W, + HELP_Y + 24); + scene_obj_set_halign(scn, OBJ_HELP, SCENEOA_CENTRE); + + if (ofnode_valid(std->theme)) { + ret = expo_setup_theme(upriv->expo, std->theme); + if (ret) + return log_msg_ret("thm", ret); + } + + theme->white_on_black = false; + + ret = expo_apply_theme(exp, true); + if (ret) + return log_msg_ret("asn", ret); + + scene_obj_set_manual(scn, OBJ_MENU, true); + + for (i = 0; i < std->bootflows.count; i++) { + const struct bootflow *bflow; + + bflow = alist_get(&std->bootflows, i, struct bootflow); + if (!bflow) + return log_msg_ret("mbb", -ENOENT); + + multiboot_set_item_props(scn, i, bflow); + } + + expo_set_mouse_enable(exp, true); + + scene_txt_set_font(scn, OBJ_MENU_TITLE, NULL, 60); + scene_txt_set_font(scn, OBJ_PROMPT1B, NULL, 30); + scene_txt_set_font(scn, OBJ_PROMPT2, "ubuntu_bold", 30); + + scene_menu_select_item(scn, OBJ_MENU, 0); + scene_set_highlight_id(scn, 0); + exp->show_highlight = false; + + return 0; +} + +static int multiboot_ui_print(struct udevice *dev, const char *msg) +{ + printf("%s", msg); + + return 0; +} + +static int multiboot_ui_show(struct udevice *dev) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct multiboot_ui_priv *priv = dev_get_priv(dev); + struct bootstd_priv *std; + struct scene *scn; + struct abuf *buf; + uint scene_id; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return log_msg_ret("sdb", ret); + ret = bootflow_menu_setup(std, 0, &upriv->expo); + if (ret) + return log_msg_ret("sds", ret); + + expo_set_mouse_enable(upriv->expo, true); + + ret = expo_first_scene_id(upriv->expo); + if (ret < 0) + return log_msg_ret("ufs", ret); + scene_id = ret; + scn = expo_lookup_scene_id(upriv->expo, scene_id); + + ret = expo_edit_str(upriv->expo, STR_PROMPT1B, NULL, &buf); + if (!ret) + abuf_printf(buf, "Select image to boot"); + + ret = expo_edit_str(upriv->expo, STR_PROMPT2, NULL, &buf); + if (!ret) + abuf_printf(buf, "Images"); + + ret = expo_edit_str(upriv->expo, STR_AUTOBOOT, + &upriv->autoboot_template, + &upriv->autoboot_str); + if (ret) + return log_msg_ret("ses", ret); + + if (upriv->logo) { + ret = scene_img_set_data(scn, OBJ_U_BOOT_LOGO, upriv->logo, + upriv->logo_size); + if (ret) + return log_msg_ret("log", ret); + } + + ret |= scene_img(scn, "multipass", OBJ_OTHER_LOGO, + video_image_getptr(multipass), NULL); + + ret |= scene_img(scn, "settings", OBJ_SETTINGS, + video_image_getptr(settings), NULL); + + ret |= scene_img(scn, "help", OBJ_HELP, + video_image_getptr(help), NULL); + + log_debug("theme '%s'\n", ofnode_get_name(std->theme)); + + if (priv->use_bootflow_props) { + void *logo = upriv->logo ? (void *)upriv->logo : + video_get_u_boot_logo(NULL); + + ret = bootflow_menu_set_props(upriv->expo, scn, logo, + "Boot Control"); + if (ret) + return log_msg_ret("bfprops", ret); + } else { + ret = multiboot_ui_set_props(dev, scn, std); + if (ret) + return log_msg_ret("props", ret); + } + + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("usa", ret); + + upriv->scn = scn; + + ret = device_find_first_child_by_uclass(upriv->expo->display, + UCLASS_VIDEO_CONSOLE, + &upriv->console); + if (ret) + return log_msg_ret("suq", ret); + vidconsole_set_quiet(upriv->console, true); + expo_enter_mode(upriv->expo); + + return 0; +} + +static int multiboot_ui_add(struct udevice *dev, struct osinfo *info) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct logic_priv *lpriv = upriv->lpriv; + struct bootstd_priv *std; + const char *vers = NULL; + struct scene *scn; + struct abuf *buf; + int seq, ret; + + info = alist_add(&lpriv->osinfo, *info); + if (!info) + return log_msg_ret("mua", -ENOMEM); + seq = bootstd_add_bootflow(&info->bflow); + if (seq + 1 != lpriv->osinfo.count) + return log_msg_ret("mdb", seq); + ret = bootflow_menu_add(upriv->expo, &info->bflow, seq, &scn); + if (ret) + return log_msg_ret("mda", ret); + + ret = setup_version(upriv->expo, seq, &info->bflow, &vers); + + if (vers) { + void *logo; + + ret = expo_edit_str(upriv->expo, STR_LABEL + seq, NULL, &buf); + if (!ret) + abuf_printf(buf, "Canonical"); + + scene_obj_set_hide(scn, ITEM_VERSION_NAME + seq, false); + scene_txt_set_font(scn, ITEM_DESC + seq, "ubuntu_bold", + 20); + ret = expo_edit_str(upriv->expo, STR_VERSION_NAME + seq, NULL, + &buf); + if (!ret) { + if (!strncmp("24.04", vers, 5)) + abuf_printf(buf, "Noble Numbat"); + else if (!strncmp("25.04", vers, 5)) + abuf_printf(buf, "Plucky Puffin"); + else if (!strncmp("22.04", vers, 5)) + abuf_printf(buf, "Jammy Jellyfish"); + } + + logo = video_image_getptr(canonical); + ret |= scene_img(scn, "preview", ITEM_PREVIEW + seq, logo, + NULL); + + logo = video_image_getptr(tick); + ret |= scene_img(scn, "verified", ITEM_VERIFIED + seq, logo, + NULL); + } + + ret = bootstd_get_priv(&std); + if (ret) + return log_msg_ret("sup", ret); + + multiboot_set_item_props(scn, seq, &info->bflow); + + ret = expo_calc_dims(upriv->expo); + if (ret) + return log_msg_ret("ecd", ret); + + if (lpriv->default_os && + !strcmp(lpriv->default_os, info->bflow.os_name)) + scene_menu_select_item(scn, OBJ_MENU, ITEM + seq); + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("sua", ret); + + return 0; +} + +static int multiboot_ui_render(struct udevice *dev) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + int ret; + + ret = abuf_printf(upriv->autoboot_str, + upriv->autoboot_template.data, + upriv->lpriv->autoboot_remain_s); + if (ret < 0) + return log_msg_ret("uip", ret); + + ret = expo_arrange(upriv->expo); + if (ret) + return log_msg_ret("sda", ret); + ret = expo_render(upriv->expo); + if (ret) + return log_msg_ret("sdr", ret); + + return 0; +} + +static int multiboot_ui_switch_layout(struct udevice *dev) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct multiboot_ui_priv *priv = dev_get_priv(dev); + struct bootstd_priv *std; + struct scene *scn; + int ret; + + /* Toggle the layout mode */ + priv->use_bootflow_props = !priv->use_bootflow_props; + + /* Get the current scene */ + scn = expo_lookup_scene_id(upriv->expo, upriv->expo->scene_id); + if (!scn) + return log_msg_ret("scn", -ENOENT); + + ret = bootstd_get_priv(&std); + if (ret) + return log_msg_ret("std", ret); + + /* Re-apply properties with the new layout */ + if (priv->use_bootflow_props) { + /* Apply simple_ui style using bootflow_menu_set_props() */ + void *logo = upriv->logo ? (void *)upriv->logo : + video_get_u_boot_logo(NULL); + + ret = bootflow_menu_set_props(upriv->expo, scn, logo, + "Boot control"); + if (ret) + return log_msg_ret("bfprops", ret); + } else { + /* Apply multiboot style using multiboot_ui_set_props() */ + ret = multiboot_ui_set_props(dev, scn, std); + if (ret) + return log_msg_ret("props", ret); + } + + /* Calculate dimensions then re-arrange */ + ret = expo_calc_dims(upriv->expo); + if (ret) + return log_msg_ret("ecd", ret); + + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); + + return 0; +} + +static int multiboot_ui_poll(struct udevice *dev, int *seqp, bool *selectedp) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + struct logic_priv *lpriv = upriv->lpriv; + int seq, ret; + bool ok = true; + + *seqp = -1; + *selectedp = false; + ret = bootflow_menu_poll(upriv->expo, &seq); + + ok = !ret; + if (ret == -ERESTART || ret == -EREMCHG) { + lpriv->autoboot_active = false; + scene_obj_set_hide(upriv->scn, OBJ_AUTOBOOT, true); + ok = true; + } else if (ret == -ECOMM) { + /* Layout change requested */ + ret = multiboot_ui_switch_layout(dev); + if (ret) + return log_msg_ret("swl", ret); + ret = -ECOMM; /* Restore the original return code */ + ok = true; + } else if (ret == -EAGAIN || ret == -ENOTTY) { + ok = true; + } + + *seqp = seq; + if (ret) { + if (!ok) + return log_msg_ret("sdp", ret); + if (ret == -EAGAIN || ret == -ERESTART || ret == -ECOMM || + ret == -ENOTTY) + return 0; + return 1; + } + + *selectedp = true; + + return 0; +} + +static int multiboot_ui_of_to_plat(struct udevice *dev) +{ + struct bc_ui_priv *upriv = dev_get_uclass_priv(dev); + + upriv->logo = dev_read_prop(dev, "logo", &upriv->logo_size); + + return 0; +} + +static struct bc_ui_ops ops = { + .print = multiboot_ui_print, + .show = multiboot_ui_show, + .add = multiboot_ui_add, + .render = multiboot_ui_render, + .poll = multiboot_ui_poll, + .switch_layout = multiboot_ui_switch_layout, +}; + +static const struct udevice_id multiboot_ui_ids[] = { + { .compatible = "bootctl,multiboot-ui" }, + { .compatible = "bootctl,ui" }, + { } +}; + +U_BOOT_DRIVER(multiboot_ui) = { + .name = "multiboot_ui", + .id = UCLASS_BOOTCTL_UI, + .of_match = multiboot_ui_ids, + .of_to_plat = multiboot_ui_of_to_plat, + .bind = multiboot_ui_bind, + .probe = multiboot_ui_probe, + .ops = &ops, + .priv_auto = sizeof(struct multiboot_ui_priv), +}; diff --git a/include/bootctl.dtsi b/include/bootctl.dtsi index 2d3a83c4576..d7c191770a7 100644 --- a/include/bootctl.dtsi +++ b/include/bootctl.dtsi @@ -115,10 +115,17 @@ #endif }; - ui { + ui-multi { compatible = "bootctl,multiboot-ui", "bootctl,simple-ui", "bootctl,ui"; graphical = "if-available"; textual = "if-available"; }; + + ui-simple { + compatible = "bootctl,simple-ui", "bootctl,ui"; + graphical = "if-available"; + textual = "if-available"; + }; + }; -- 2.43.0
From: Simon Glass <sjg@chromium.org> Disable the autoboot feature to make the two UIs more similar. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/bootctl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bootctl.dtsi b/include/bootctl.dtsi index d7c191770a7..05032a924e1 100644 --- a/include/bootctl.dtsi +++ b/include/bootctl.dtsi @@ -24,7 +24,7 @@ track-success; /* auto-boot the default OS after a timeout */ - autoboot; + // autoboot; /* measure loaded images, etc. */ #if !defined(CONFIG_QEMU) && !defined(CONFIG_EFI_APP) -- 2.43.0
From: Simon Glass <sjg@chromium.org> Add a test which switches between the simple and the mouse-based UI. For now the tests are not enabled, due to an integration problem which causes bootflow_efi() to detect and invalid free() Signed-off-by: Simon Glass <sjg@chromium.org> --- test/boot/bootctl/bootctl.c | 181 +++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 4 deletions(-) diff --git a/test/boot/bootctl/bootctl.c b/test/boot/bootctl/bootctl.c index e6bdf6820a0..ab9aa28a668 100644 --- a/test/boot/bootctl/bootctl.c +++ b/test/boot/bootctl/bootctl.c @@ -11,14 +11,21 @@ #include <stdbool.h> #include <bootctl.h> +#include <bootflow.h> #include <bootmeth.h> +#include <bootstd.h> #include <dm.h> +#include <expo.h> #include <os.h> #include <test/ut.h> +#include <test/video.h> #include "bootctl_common.h" +#include <bootctl/logic.h> #include <bootctl/measure.h> #include <bootctl/oslist.h> #include <bootctl/state.h> +#include <bootctl/ui.h> +#include <dm/lists.h> #include "../bootstd_common.h" /* test that expected devices are available and can be probed */ @@ -27,10 +34,10 @@ static int bootctl_base(struct unit_test_state *uts) struct udevice *dev; ut_assertok(bootctl_get_dev(UCLASS_BOOTCTL_UI, &dev)); - ut_asserteq_str("ui", dev->name); + ut_asserteq_str("ui-multi", dev->name); ut_assertok(bootctl_get_dev(UCLASS_BOOTCTL_OSLIST, &dev)); - ut_asserteq_str("oslist", dev->name); + ut_asserteq_str("oslist-extlinux", dev->name); ut_assertok(bootctl_get_dev(UCLASS_BOOTCTL_STATE, &dev)); ut_asserteq_str("state", dev->name); @@ -48,7 +55,7 @@ static int bootctl_oslist(struct unit_test_state *uts) struct udevice *dev; ut_assertok(bootctl_get_dev(UCLASS_BOOTCTL_OSLIST, &dev)); - ut_asserteq_str("oslist", dev->name); + ut_asserteq_str("oslist-extlinux", dev->name); /* initially we should only see Fedora */ bc_oslist_setup_iter(&iter); @@ -74,7 +81,7 @@ static int bootctl_oslist_usb(struct unit_test_state *uts) bootstd_reset_usb(); ut_assertok(bootctl_get_dev(UCLASS_BOOTCTL_OSLIST, &dev)); - ut_asserteq_str("oslist", dev->name); + ut_asserteq_str("oslist-extlinux", dev->name); /* include usb in the bootdev order */ ut_assertok(bootdev_set_order("mmc usb")); @@ -325,3 +332,169 @@ static int bootctl_simple_measure(struct unit_test_state *uts) return 0; } BOOTCTL_TEST(bootctl_simple_measure, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); + +static int check_multiboot_ui(struct unit_test_state *uts, + struct bootstd_priv *std) +{ + struct udevice *oslist_dev, *ui_dev, *vid_dev; + struct membuf buf1, buf2, buf3, buf4; + char *data1, *data2, *data3, *data4; + struct bc_ui_priv *uc_priv; + struct udevice *logic_dev; + struct logic_priv *lpriv; + struct oslist_iter iter; + struct osinfo info[2]; + int len; + + test_set_skip_delays(true); + bootstd_reset_usb(); + + /* get the oslist device and find two OSes */ + ut_assertok(bootctl_get_dev(UCLASS_BOOTCTL_OSLIST, &oslist_dev)); + ut_asserteq_str("oslist-extlinux", oslist_dev->name); + + bc_oslist_setup_iter(&iter); + ut_assertok(bc_oslist_next(oslist_dev, &iter, &info[0])); + ut_asserteq_str("mmc11.bootdev.part_1", info[0].bflow.name); + + ut_assertok(bc_oslist_next(oslist_dev, &iter, &info[1])); + ut_asserteq_str("hub1.p4.usb_mass_storage.lun0.bootdev.part_1", + info[1].bflow.name); + + test_set_skip_delays(false); + + /* first use simple_ui as baseline */ + ut_assertok(uclass_get_device_by_name(UCLASS_BOOTCTL_UI, "ui-simple", + &ui_dev)); + ut_assertok(bc_ui_show(ui_dev)); + ut_assertok(bc_ui_add(ui_dev, &info[0])); + ut_assertok(bc_ui_add(ui_dev, &info[1])); + ut_assertok(bc_ui_render(ui_dev)); + ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &vid_dev)); + ut_asserteq(22656, video_compress_fb(uts, vid_dev, false)); + + /* dump the simple_ui expo - buf1 is golden for simple_ui */ + uc_priv = dev_get_uclass_priv(ui_dev); + ut_assertok(membuf_new(&buf1, 4096)); + expo_dump(uc_priv->expo, &buf1); + len = membuf_getraw(&buf1, -1, false, &data1); + ut_assert(len > 0); + if (_DEBUG) + ut_assertok(os_write_file("simple_ui.txt", data1, len)); + + /* clear out osinfo and bootflows before using ui2 */ + ut_assertok(bootctl_get_dev(UCLASS_BOOTCTL, &logic_dev)); + lpriv = dev_get_priv(logic_dev); + alist_empty(&lpriv->osinfo); + + alist_empty(&std->bootflows); + + /* now use multiboot_ui - this is the initial multiboot state */ + ut_assertok(uclass_get_device_by_name(UCLASS_BOOTCTL_UI, "ui-multi", + &ui_dev)); + ut_assertok(bc_ui_show(ui_dev)); + ut_assertok(bc_ui_add(ui_dev, &info[0])); + ut_assertok(bc_ui_add(ui_dev, &info[1])); + ut_assertok(bc_ui_render(ui_dev)); + ut_asserteq(16645, video_compress_fb(uts, vid_dev, false)); + + /* dump after render - buf2 is golden for multiboot_ui */ + uc_priv = dev_get_uclass_priv(ui_dev); + ut_assertok(membuf_new(&buf2, 4096)); + expo_dump(uc_priv->expo, &buf2); + len = membuf_getraw(&buf2, -1, false, &data2); + ut_assert(len > 0); + if (_DEBUG) + ut_assertok(os_write_file("multiboot_ui.txt", data2, len)); + + /* switch to simple_ui layout and check against buf1 */ + ut_assertok(bc_ui_switch_layout(ui_dev)); + ut_assertok(bc_ui_render(ui_dev)); + ut_asserteq(22656, video_compress_fb(uts, vid_dev, false)); + + /* dump after switch to simple_ui - buf3 should match buf1 */ + ut_assertok(membuf_new(&buf3, 4096)); + expo_dump(uc_priv->expo, &buf3); + len = membuf_getraw(&buf3, -1, false, &data3); + ut_assert(len > 0); + if (_DEBUG) + ut_assertok(os_write_file("multiboot_ui_switched.txt", data3, + len)); + + /* compare buf3 against buf1 (simple_ui golden) */ + if (strcmp(data1, data3)) { + printf("Expo dumps differ after switch to simple_ui!\n"); + if (_DEBUG) { + puts("simple_ui:\n"); + puts(data1); + puts("multiboot_ui_switched:\n"); + puts(data3); + } + } + + /* switch back to multiboot UI style and check against buf2 */ + ut_assertok(bc_ui_switch_layout(ui_dev)); + ut_assertok(bc_ui_render(ui_dev)); + ut_asserteq(16645, video_compress_fb(uts, vid_dev, false)); + + /* dump after switch back to multiboot - buf4 should match buf2 */ + ut_assertok(membuf_new(&buf4, 4096)); + expo_dump(uc_priv->expo, &buf4); + len = membuf_getraw(&buf4, -1, false, &data4); + ut_assert(len > 0); + if (_DEBUG) + ut_assertok(os_write_file("multiboot_ui_switched_back.txt", + data4, len)); + + /* compare buf4 against buf2 (multiboot_ui golden) */ + if (strcmp(data2, data4)) { + printf("Expo dumps differ after switch back to multiboot!\n"); + if (_DEBUG) { + puts("multiboot_ui:\n"); + puts(data2); + puts("multiboot_ui_switched_back:\n"); + puts(data4); + } + } + + membuf_dispose(&buf1); + membuf_dispose(&buf2); + membuf_dispose(&buf3); + membuf_dispose(&buf4); + + return 0; +} + +/* test creating multiboot_ui with two OSes */ +static int bootctl_multiboot_ui(struct unit_test_state *uts) +{ + static const char *order[3]; + struct bootstd_priv *std; + const char **old_order; + struct udevice *dev; + ofnode root, node; + int ret; + + order[0] = "mmc11"; + order[1] = "usb3"; + order[2] = NULL; + + /* Enable the requested mmc node since we need a second bootflow */ + root = oftree_root(oftree_default()); + node = ofnode_find_subnode(root, "mmc11"); + ut_assert(ofnode_valid(node)); + ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false)); + + /* Change the order to include the device */ + ut_assertok(bootstd_get_priv(&std)); + old_order = std->bootdev_order; + std->bootdev_order = order; + + ret = check_multiboot_ui(uts, std); + + std->bootdev_order = old_order; + ut_assertok(ret); + + return 0; +} +BOOTCTL_TEST(bootctl_multiboot_ui, UTF_DM | UTF_SCAN_FDT); -- 2.43.0
From: Simon Glass <sjg@chromium.org> Provide some basic settings so that bootctl can be used with the EFI app on x86. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/x86/dts/efi-x86_app.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/dts/efi-x86_app.dts b/arch/x86/dts/efi-x86_app.dts index 1daba34d5f0..6acb0dbae51 100644 --- a/arch/x86/dts/efi-x86_app.dts +++ b/arch/x86/dts/efi-x86_app.dts @@ -34,4 +34,18 @@ compatible = "efi,mouse"; }; + boot_ctl: bootctl { + }; + + bootstd { + compatible = "u-boot,boot-std"; + theme { + font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; + }; + }; + }; + +#include "bootctl.dtsi" -- 2.43.0
From: Simon Glass <sjg@chromium.org> Adjust the configuration to support truetype fonts, more bitmap formats, VIDEO_COPY (for smoother display) and bloblist for ACPI tables. Disable the pager since it can be confusing when using bootctl. Signed-off-by: Simon Glass <sjg@chromium.org> --- configs/efi-x86_app64_defconfig | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configs/efi-x86_app64_defconfig b/configs/efi-x86_app64_defconfig index ea9a2068565..63a53361688 100644 --- a/configs/efi-x86_app64_defconfig +++ b/configs/efi-x86_app64_defconfig @@ -1,4 +1,5 @@ CONFIG_X86=y +CONFIG_SYS_MALLOC_F_LEN=0x1000 CONFIG_NR_DRAM_BANKS=8 CONFIG_ENV_SIZE=0x1000 CONFIG_DEFAULT_DEVICE_TREE="efi-x86_app" @@ -16,11 +17,13 @@ CONFIG_BOOTSTD_FULL=y CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" -CONFIG_BOOTCOMMAND="bootflow scan -lbp" +CONFIG_BOOTCOMMAND="bootctl run" CONFIG_SYS_PBSIZE=532 CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_CONSOLE_PAGER is not set CONFIG_LOG=y CONFIG_BOARD_EARLY_INIT_R=y +CONFIG_BLOBLIST=y CONFIG_CMD_LSBLK=y CONFIG_CMD_CAT=y CONFIG_CMD_TIME=y @@ -36,7 +39,13 @@ CONFIG_SYSCON=y # CONFIG_SCSI is not set # CONFIG_TPM_V1 is not set CONFIG_TPM2_EFI=y +CONFIG_VIDEO_COPY=y +CONFIG_CONSOLE_TRUETYPE=y +CONFIG_CONSOLE_TRUETYPE_UBUNTU_LIGHT=y +CONFIG_CONSOLE_TRUETYPE_UBUNTU_BOLD=y CONFIG_CONSOLE_SCROLL_LINES=5 +CONFIG_BMP_16BPP=y +CONFIG_BMP_24BPP=y CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y # CONFIG_GZIP is not set -- 2.43.0
From: Simon Glass <sjg@chromium.org> We don't need to enable USB or i8042 for the app. Enable only serial for now. Signed-off-by: Simon Glass <sjg@chromium.org> --- board/efi/efi-x86_app/efi-x86_app.env | 1 + 1 file changed, 1 insertion(+) diff --git a/board/efi/efi-x86_app/efi-x86_app.env b/board/efi/efi-x86_app/efi-x86_app.env index 106836af1ff..d6eea472070 100644 --- a/board/efi/efi-x86_app/efi-x86_app.env +++ b/board/efi/efi-x86_app/efi-x86_app.env @@ -4,3 +4,4 @@ */ #include <env/x86.env> +stdin=serial -- 2.43.0
participants (1)
-
Simon Glass