Example AI transcript for adding a small feature
Hi, I thought I would post this, just as an example of using Claude to make a change in U-Boot. Once it got started I typed 'iomux_doenv() might be a good place to filter it out' but then I saw that it had decided on using an environment event, which seems better to me, so I didn't enter that prompt. I did enter 'Try adding malloc_dump() at the start of main_loop() to produce a lot of output' to give it a hint for timing comparisons.
Another thing, I notice that running sandbox is much faster (if there is a lot of output) when stdout contains just 'serial' instead of also 'vidconsole'. This is because it outputs truetype fonts to its internal framebuffer. Can you add a command-line option to sandbox to drop vidconsole from stdout ?
● Let me explore how sandbox handles command-line options and stdout configuration: ● Bash(grep -n "add_args\|SANDBOX_CMDLINE" arch/sandbox/cpu/os.c | head -30) ⎿ 898: * add_args() - Allocate a new argv with the given args 904: * @add_args: Arguments to add, each a string 905: * @count: Number of arguments in @add_args … +4 lines (ctrl+o to expand) ● Bash(grep -n "struct sandbox_cmdline_option\|SANDBOX_STATE_FLAG" include/sandbox_state.h | head -20) ⎿ grep: include/sandbox_state.h: No such file or directory ● Bash(find include arch/sandbox -name "*.h" | xargs grep -l "sandbox_state" | head -5) ⎿ include/efi.h include/os.h include/spi.h … +2 lines (ctrl+o to expand) ● Bash(grep -n "struct sandbox_state\|cmdline_option" include/os.h | head -30) ⎿ 19:struct sandbox_state; 263:int os_parse_args(struct sandbox_state *state, int argc, char *argv[]); ● Bash(find . -name "*.h" | xargs grep -l "struct sandbox_state {" 2>/dev/null) ⎿ Error: Exit code 123 ./arch/sandbox/include/asm/state.h ● Read(arch/sandbox/include/asm/state.h) ⎿ Read 416 lines ● Bash(grep -n "os_parse_args\|sandbox_cmdline_option\|CMDLINE" arch/sandbox/cpu/start.c | head -40) ⎿ 37: const struct sandbox_cmdline_option *opt1 = p1; 38: const struct sandbox_cmdline_option *opt2 = p2; 42: opt1 = *(struct sandbox_cmdline_option **)p1; … +54 lines (ctrl+o to expand) ● Read(arch/sandbox/cpu/start.c) ⎿ Read 779 lines ● Now let me find how stdout is configured: ● Bash(grep -rn "stdout" arch/sandbox/dts/sandbox.dts 2>/dev/null | head -10) ⎿ (No content) ● Bash(grep -rn "stdout\|vidconsole" arch/sandbox/dts/*.dts | head -20) ⎿ arch/sandbox/dts/test.dts:1687: stdout-path = "serial0:115200n8"; ● Bash(grep -rn "vidconsole\|stdio_add\|stdout" common/board_r.c common/stdio_console.c common/console.c 2>/dev/null | head -30) ⎿ common/board_r.c:707: INITCALL(stdio_add_devices); common/console.c:104: * if overwrite_console returns 1, the stdin, stderr and stdout … +38 lines (ctrl+o to expand) ● Bash(grep -rn "vidconsole" drivers/video/vidconsole-uclass.c | head -20) ⎿ 20:#include "vidconsole_internal.h" 24:int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, int ch) … +20 lines (ctrl+o to expand) ● Bash(grep -rn "stdio_register\|DEV_FLAGS_OUTPUT" drivers/video/vidconsole-uclass.c) ⎿ 860: sdev->flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_DM; 865: return stdio_register(sdev); ● Read(common/console.c) ⎿ Read 100 lines ● Bash(grep -rn "stdout.*vidconsole\|vidconsole.*stdout" . --include="*.c" --include="*.h" 2>/dev/null | head -10) ⎿ ./lib/efi_loader/efi_console.c:218: if (!stdout_name || strncmp(st dout_name, "vidconsole", 10)) ./lib/efi_loader/efi_console.c:220: stdout_dev = stdio_get_by_name … +19 lines (ctrl+o to expand) ● Bash(grep -rn "stdout=serial" include/configs/sandbox.h) ⎿ No matches found ● Read(include/configs/sandbox.h) ⎿ Read 25 lines ● Bash(grep -rn "stdout.*serial.*vidconsole" . --include="*.env" --include="Kconfig" 2>/dev/null | head -10) ⎿ ./board/emulation/qemu-sbsa/qemu-sbsa.env:6:stdout=serial,vidconso le ./board/emulation/qemu-arm/qemu-arm.env:6:stdout=serial,vidconsole … +12 lines (ctrl+o to expand) ● Read(board/sandbox/sandbox.env) ⎿ Read 27 lines ● Bash(grep -rn "env_set.*state\|state.*env_set" arch/sandbox --include="*.c" | head -10) ⎿ (No content) ● Bash(grep -rn "EVT_" arch/sandbox/cpu/*.c board/sandbox/*.c | head -20) ⎿ arch/sandbox/cpu/start.c:127:EVENT_SPY_SIMPLE(EVT_MISC_INIT_F, san dbox_early_getopt_check); arch/sandbox/cpu/start.c:630:EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init); ● Bash(grep -rn "console_init_r\|EVT_" common/board_r.c | head -30) ⎿ 560: event_notify_null(EVT_MAIN_LOOP); 699: INITCALL_EVT(EVT_SETTINGS_R); 712: INITCALL(console_init_r); /* fully init console as a device */ 751: INITCALL_EVT(EVT_LAST_STAGE_INIT); ● Bash(grep -rn "INITCALL\|console_init" common/board_r.c | head -40) ⎿ 581: INITCALL(initr_trace); 582: INITCALL(initr_reloc); 583: INITCALL(event_init); … +38 lines (ctrl+o to expand) ● Bash(grep -rn "INITCALL\|console_init" common/board_r.c | tail -30) ⎿ 676: INITCALL(efi_init_early); 679: INITCALL(initr_nand); 682: INITCALL(initr_onenand); … +27 lines (ctrl+o to expand) ● Now I understand the flow. I need to: 1. Add a flag to sandbox_state 2. Add a command-line option 3. Hook EVT_SETTINGS_R to modify stdout before console init ● Update(arch/sandbox/include/asm/state.h) ⎿ Added 1 line 177 bool soft_fail; /* Continue on failure */ 178 bool pager_bypass; /* Enable pager-bypass mode */ 179 bool no_term_present; /* Assume no terminal present */ 180 + bool no_vidconsole; /* Drop vidconsole from stdout */ 181 int video_test; /* ms to wait before next assert */ 182 const char *video_frames_dir; /* Directory to write video frames */ 183 int video_frame_count; /* Number of frames written */ ● Update(arch/sandbox/cpu/start.c) ⎿ Added 8 lines 476 SANDBOX_CMDLINE_OPT_SHORT(no_term_present, 'A', 0, 477 "Assume no terminal present (for pager testing)"); 478 479 +static int sandbox_cmdline_cb_no_vidconsole(struct +sandbox_state *state, 480 + const char *arg) 481 +{ 482 + state->no_vidconsole = true; 483 + return 0; 484 +} 485 +SANDBOX_CMDLINE_OPT(no_vidconsole, 0, "Drop vidconsole +from stdout/stderr"); 486 + 487 static int sandbox_cmdline_cb_upl(struct sandbox_state *state, const char *arg) 488 { 489 state->upl = true; ● Read(board/sandbox/sandbox.c) ⎿ Read 188 lines ● Update(board/sandbox/sandbox.c) ⎿ Added 3 lines 10 #include <dm.h> 11 #include <efi.h> 12 #include <efi_loader.h> 13 +#include <env.h> 14 #include <env_internal.h> 15 +#include <event.h> 16 #include <extension_board.h> 17 #include <init.h> 18 #include <led.h> ... 19 #include <os.h> 20 #include <acpi/acpi_table.h> 21 #include <asm/global_data.h> 22 +#include <asm/state.h> 23 #include <asm/test.h> 24 #include <asm/u-boot-sandbox.h> 25 #include <linux/kernel.h> ● Update(board/sandbox/sandbox.c) ⎿ Added 13 lines 188 *boot_idx = 0; 189 } 190 #endif 191 + 192 +static int sandbox_settings(void) 193 +{ 194 + struct sandbox_state *state = state_get_current(); 195 + 196 + if (state->no_vidconsole) { 197 + env_set("stdout", "serial"); 198 + env_set("stderr", "serial"); 199 + } 200 + 201 + return 0; 202 +} 203 +EVENT_SPY_SIMPLE(EVT_SETTINGS_R, sandbox_settings); ● Now let me build and test: ● Bash(crosfw sandbox -L) ⎿ (No content) ● Build succeeded. Let me test it: ● Bash(/tmp/b/sandbox/u-boot -Tf -c 'exit' 2>&1 | grep -E "^(In:|Out:|Err:)") ⎿ In: serial,cros-ec-keyb,usbkbd Out: serial,vidconsole Err: serial,vidconsole ● Bash(/tmp/b/sandbox/u-boot -Tf --no-vidconsole -c 'exit' 2>&1 | grep -E "^(In:|Out:|Err:)") ⎿ No matches found ● Bash(/tmp/b/sandbox/u-boot -Tf --no-vidconsole -c 'exit' 2>&1) ⎿ Error: Exit code 1 pinctrl_select_state_full() sandbox_serial serial: pinctrl_select_state_full: uclass_get_device_by_phandle_id: err=-19 U-Boot Concept 2026.02-rc1-g7462e77cf5d1-dirty (Dec 31 2025 - 07:51:00 -0700) Reset Status: WARM Reset Status: COLD Model: sandbox u-boot: error: failed while parsing option: --no-vidconsole try running with --help for more information. ● Bash(/tmp/b/sandbox/u-boot --help 2>&1 | grep -i vidconsole) ⎿ --no_vidconsole Drop vidconsole from stdout/stder r ● Bash(/tmp/b/sandbox/u-boot -Tf --no_vidconsole -c 'exit' 2>&1 | grep -E "^(In:|Out:|Err:)") ⎿ In: serial,cros-ec-keyb,usbkbd Out: serial Err: serial ● It works. Let me verify the performance difference: ● Bash(echo "=== Without --no_vidconsole ===" && time timeout: /tmp/b/sandbox/u-boot -Tf -c 'ut all' 2>&1 | tail -3) 5m 0s ⎿ === Without --no_vidconsole === test/boot/bootctl/bootctl.c:456, check_multiboot_ui(): 0 == bc_osl ist_next(oslist_dev, &iter, &info[0]): Expected 0x0 (0), got 0xfff … +9 lines (ctrl+o to expand) ● Bash(echo "=== With --no_vidconsole ===" && time timeout: 5m /tmp/b/sandbox/u-boot -Tf --no_vidconsole -c 'ut all' 0s 2>&1 | tail -3) ⎿ === With --no_vidconsole === test/boot/bootctl/bootctl.c:456, check_multiboot_ui(): 0 == bc_osl ist_next(oslist_dev, &iter, &info[0]): Expected 0x0 (0), got 0xfff … +9 lines (ctrl+o to expand) ● Bash(echo "=== Without --no_vidconsole ===" && time timeout: /tmp/b/sandbox/u-boot -Tf -v -c 'ut dm' 2>&1 | tail -5) 5m 0s ⎿ === Without --no_vidconsole === test/dm/blk.c:129, dm_test_blk_devnum(): 0 == uclass_get_device(UC LASS_MMC, 1, &dev): Expected 0x0 (0), got 0xffffffff (-1) … +11 lines (ctrl+o to expand) ● Bash(echo "=== With --no_vidconsole ===" && time timeout: /tmp/b/sandbox/u-boot -Tf -v --no_vidconsole -c 'ut dm' 5m 0s 2>&1 | tail -5) ⎿ === With --no_vidconsole === test/dm/blk.c:129, dm_test_blk_devnum(): 0 == uclass_get_device(UC LASS_MMC, 1, &dev): Expected 0x0 (0), got 0xffffffff (-1) … +11 lines (ctrl+o to expand)
Try adding malloc_dump() at the start of main_loop() to produce a lot of output
● Bash(echo "=== Without --no_vidconsole ===" && time timeout: /tmp/b/sandbox/u-boot -Tf -c 'malloc dump;malloc 1m 0s dump;malloc dump;malloc dump;malloc dump;malloc dump;malloc dump…) ⎿ === Without --no_vidconsole === 21339 … +3 lines (ctrl+o to expand) ● Bash(echo "=== With --no_vidconsole ===" && time timeout: /tmp/b/sandbox/u-boot -Tf --no_vidconsole -c 'malloc 1m 0s dump;malloc dump;malloc dump;malloc dump;malloc dump;malloc dum…) ⎿ === With --no_vidconsole === 21319 … +3 lines (ctrl+o to expand) ● Excellent! 57.8 seconds vs 0.2 seconds - almost 300x faster! The feature works as expected. ● Bash(git add arch/sandbox/include/asm/state.h arch/sandbox/cpu/start.c board/sandbox/sandbox.c && git status) ⎿ On branch extl Your branch is ahead of 'ci/master' by 15 commits. (use "git push" to publish your local commits) … +6 lines (ctrl+o to expand) ● Bash(git commit -m "sandbox: Add --no_vidconsole option to speed up output…) ⎿ [extl 9d79d940474] sandbox: Add --no_vidconsole option to speed up output 3 files changed, 25 insertions(+) ● Done. Created commit 9d79d940474 adding --no_vidconsole option. Usage: /tmp/b/sandbox/u-boot --no_vidconsole ... Performance test showed ~300x speedup for output-heavy operations (57.8s down to 0.2s with 20x malloc dump). commit 9d79d9404742bb224738480af0d81892209cb729 (HEAD -> extl) Author: Simon Glass <simon.glass@canonical.com> Date: Wed Dec 31 07:54:23 2025 -0700 sandbox: Add --no_vidconsole option to speed up output When running sandbox with lots of console output, the vidconsole slows things down significantly due to truetype font rendering to the internal framebuffer. Add a --no_vidconsole command-line option that removes vidconsole from stdout and stderr, using only the serial console. This can provide a ~300x speedup for output-heavy operations. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> arch/sandbox/cpu/start.c | 8 ++++++++ arch/sandbox/include/asm/state.h | 1 + board/sandbox/sandbox.c | 16 ++++++++++++++++ 3 files changed, 25 insertions(+) Regards, Simon
participants (1)
-
Simon Glass