From a75cf70d23ac8d4dbccf13f0a9589aaf6a552bff Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 Oct 2023 19:14:36 -0600 Subject: efi: Correct handling of frame buffer The efi_gop driver uses private fields from the video uclass to obtain a pointer to the frame buffer. Use the platform data instead. Check the VIDEO_COPY setting to determine which frame buffer to use. Once the next stage is running (and making use of U-Boot's EFI boot services) U-Boot does not handle copying from priv->fb to the hardware framebuffer, so we must allow EFI to write directly to the hardware framebuffer. We could provide a function to read this, but it seems better to just document how it works. The original change ignored an explicit comment in the video.h file ("Things that are private to the uclass: don't use these in the driver") which is why this was missed when the VIDEO_COPY feature was added. Signed-off-by: Simon Glass Fixes: 8f661a5b662 ("efi_loader: gop: Expose fb when 32bpp") Reviewed-by: Bin Meng --- include/video.h | 9 ++++++--- lib/efi_loader/efi_gop.c | 12 +++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/video.h b/include/video.h index 5048116..4d8df9b 100644 --- a/include/video.h +++ b/include/video.h @@ -21,9 +21,12 @@ struct udevice; * @align: Frame-buffer alignment, indicating the memory boundary the frame * buffer should start on. If 0, 1MB is assumed * @size: Frame-buffer size, in bytes - * @base: Base address of frame buffer, 0 if not yet known - * @copy_base: Base address of a hardware copy of the frame buffer. See - * CONFIG_VIDEO_COPY. + * @base: Base address of frame buffer, 0 if not yet known. If CONFIG_VIDEO_COPY + * is enabled, this is the software copy, so writes to this will not be + * visible until vidconsole_sync_copy() is called. If CONFIG_VIDEO_COPY is + * disabled, this is the hardware framebuffer. + * @copy_base: Base address of a hardware copy of the frame buffer. If + * CONFIG_VIDEO_COPY is disabled, this is not used. * @copy_size: Size of copy framebuffer, used if @size is 0 * @hide_logo: Hide the logo (used for testing) */ diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 778b693..a09db31 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -467,10 +468,10 @@ efi_status_t efi_gop_register(void) struct efi_gop_obj *gopobj; u32 bpix, format, col, row; u64 fb_base, fb_size; - void *fb; efi_status_t ret; struct udevice *vdev; struct video_priv *priv; + struct video_uc_plat *plat; /* We only support a single video output device for now */ if (uclass_first_device_err(UCLASS_VIDEO, &vdev)) { @@ -483,9 +484,10 @@ efi_status_t efi_gop_register(void) format = priv->format; col = video_get_xsize(vdev); row = video_get_ysize(vdev); - fb_base = (uintptr_t)priv->fb; - fb_size = priv->fb_size; - fb = priv->fb; + + plat = dev_get_uclass_plat(vdev); + fb_base = IS_ENABLED(CONFIG_VIDEO_COPY) ? plat->copy_base : plat->base; + fb_size = plat->size; switch (bpix) { case VIDEO_BPP16: @@ -547,7 +549,7 @@ efi_status_t efi_gop_register(void) } gopobj->info.pixels_per_scanline = col; gopobj->bpix = bpix; - gopobj->fb = fb; + gopobj->fb = map_sysmem(fb_base, fb_size); return EFI_SUCCESS; } -- cgit v1.1 From baea7ec6a63e38bd4a5815c6cafded972a91c148 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 Oct 2023 19:14:37 -0600 Subject: bootstd: Refactor mmc prep to allow a different scan Adjust scan_mmc4_bootdev() and related function so that the caller can do its own 'bootflow scan' command. This allows it to change the flags if needed. Signed-off-by: Simon Glass --- test/boot/bootflow.c | 49 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index f640db8..102b2b5 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -511,19 +511,27 @@ BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); /** * prep_mmc_bootdev() - Set up an mmc bootdev so we can access other distros * + * After calling this function, set std->bootdev_order to *@old_orderp to + * restore normal operation of bootstd (i.e. with the original bootdev order) + * * @uts: Unit test state - * @mmc_dev: MMC device to use, e.g. "mmc4" + * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid + * in the caller until + * @bind_cros: true to bind the ChromiumOS bootmeth + * @old_orderp: Returns the original bootdev order, which must be restored * Returns 0 on success, -ve on failure */ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, - bool bind_cros) + bool bind_cros, const char ***old_orderp) { - const char *order[] = {"mmc2", "mmc1", mmc_dev, NULL}; + static const char *order[] = {"mmc2", "mmc1", NULL, NULL}; struct udevice *dev, *bootstd; struct bootstd_priv *std; const char **old_order; ofnode root, node; + order[2] = mmc_dev; + /* Enable the mmc4 node since we need a second bootflow */ root = oftree_root(oftree_default()); node = ofnode_find_subnode(root, mmc_dev); @@ -546,26 +554,49 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, std = dev_get_priv(bootstd); old_order = std->bootdev_order; std->bootdev_order = order; + *old_orderp = old_order; + + return 0; +} + +/** + * scan_mmc_bootdev() - Set up an mmc bootdev so we can access other distros + * + * @uts: Unit test state + * @mmc_dev: MMC device to use, e.g. "mmc4" + * @bind_cros: true to bind the ChromiumOS bootmeth + * Returns 0 on success, -ve on failure + */ +static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, + bool bind_cros) +{ + struct bootstd_priv *std; + struct udevice *bootstd; + const char **old_order; + + ut_assertok(prep_mmc_bootdev(uts, mmc_dev, bind_cros, &old_order)); console_record_reset_enable(); ut_assertok(run_command("bootflow scan", 0)); ut_assert_console_end(); /* Restore the order used by the device tree */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + std = dev_get_priv(bootstd); std->bootdev_order = old_order; return 0; } /** - * prep_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian + * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian * * @uts: Unit test state * Returns 0 on success, -ve on failure */ -static int prep_mmc4_bootdev(struct unit_test_state *uts) +static int scan_mmc4_bootdev(struct unit_test_state *uts) { - ut_assertok(prep_mmc_bootdev(uts, "mmc4", false)); + ut_assertok(scan_mmc_bootdev(uts, "mmc4", false)); return 0; } @@ -575,7 +606,7 @@ static int bootflow_cmd_menu(struct unit_test_state *uts) { char prev[3]; - ut_assertok(prep_mmc4_bootdev(uts)); + ut_assertok(scan_mmc4_bootdev(uts)); /* Add keypresses to move to and select the second one in the list */ prev[0] = CTL_CH('n'); @@ -681,7 +712,7 @@ static int bootflow_menu_theme(struct unit_test_state *uts) ofnode node; int i; - ut_assertok(prep_mmc4_bootdev(uts)); + ut_assertok(scan_mmc4_bootdev(uts)); ut_assertok(bootflow_menu_new(&exp)); node = ofnode_path("/bootstd/theme"); @@ -996,7 +1027,7 @@ BOOTSTD_TEST(bootflow_cmdline_special, 0); /* Test ChromiumOS bootmeth */ static int bootflow_cros(struct unit_test_state *uts) { - ut_assertok(prep_mmc_bootdev(uts, "mmc5", true)); + ut_assertok(scan_mmc_bootdev(uts, "mmc5", true)); ut_assertok(run_command("bootflow list", 0)); ut_assert_nextlinen("Showing all"); -- cgit v1.1 From 3fa53b9531c1db5e3be42014f2004786e9511f35 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 Oct 2023 19:14:38 -0600 Subject: bootstd: Add a return code to bootflow menu Return an error when the user does not select an OS, so we know whether to boot or not. Move calling of bootflow_menu_run() into a separate function so we can call it from other places. Expand the test to cover these cases. Add some documentation also, while we are here. Signed-off-by: Simon Glass --- cmd/bootflow.c | 53 +++++++++++++++++++++++++++--------- doc/usage/cmd/bootflow.rst | 67 ++++++++++++++++++++++++++++++++++++++++++++++ test/boot/bootflow.c | 15 +++++++++++ 3 files changed, 123 insertions(+), 12 deletions(-) diff --git a/cmd/bootflow.c b/cmd/bootflow.c index ad39ebe..3aeb40d 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -89,6 +89,44 @@ static void show_footer(int count, int num_valid) num_valid); } +/** + * bootflow_handle_menu() - Handle running the menu and updating cur bootflow + * + * This shows the menu, allows the user to select something and then prints + * what happened + * + * @std: bootstd information + * @text_mode: true to run the menu in text mode + * @bflowp: Returns selected bootflow, on success + * Return: 0 on success (a bootflow was selected), -EAGAIN if nothing was + * chosen, other -ve value on other error + */ +__maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std, + bool text_mode, + struct bootflow **bflowp) +{ + struct bootflow *bflow; + int ret; + + ret = bootflow_menu_run(std, text_mode, &bflow); + if (ret) { + if (ret == -EAGAIN) { + printf("Nothing chosen\n"); + std->cur_bootflow = NULL; + } else { + printf("Menu failed (err=%d)\n", ret); + } + + return ret; + } + + printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name); + std->cur_bootflow = bflow; + *bflowp = bflow; + + return 0; +} + static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -455,18 +493,9 @@ static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc, if (ret) return CMD_RET_FAILURE; - ret = bootflow_menu_run(std, text_mode, &bflow); - if (ret) { - if (ret == -EAGAIN) - printf("Nothing chosen\n"); - else { - printf("Menu failed (err=%d)\n", ret); - return CMD_RET_FAILURE; - } - } - - printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name); - std->cur_bootflow = bflow; + ret = bootflow_handle_menu(std, text_mode, &bflow); + if (ret) + return CMD_RET_FAILURE; return 0; } diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst index 9c5ea9c..2198ff6 100644 --- a/doc/usage/cmd/bootflow.rst +++ b/doc/usage/cmd/bootflow.rst @@ -15,6 +15,7 @@ Synopis bootflow read bootflow boot bootflow cmdline [set|get|clear|delete|auto] [] + bootfloe menu [-t] Description ----------- @@ -24,6 +25,9 @@ locate bootflows, list them and boot them. See :doc:`../../develop/bootstd` for more information. +Note that `CONFIG_BOOTSTD_FULL` (which enables `CONFIG_CMD_BOOTFLOW_FULL) must +be enabled to obtain full functionality with this command. Otherwise, it only +supports `bootflow scan` which scans and boots the first available bootflow. bootflow scan ~~~~~~~~~~~~~ @@ -247,6 +251,16 @@ can be used to set the early console (or console) to a suitable value so that output appears on the serial port. This is only supported by the 16550 serial driver so far. +bootflow menu +~~~~~~~~~~~~~ + +This shows a menu with available bootflows. The user can select a particular +bootflow, which then becomes the current one. + +The `-t` flag requests a text menu. Otherwise, if a display is available, a +graphical menu is shown. + + Example ------- @@ -658,6 +672,56 @@ Now the buffer can be accessed:: 77b7e4e0: 320fc000 08e8ba0f c031300f b8d0000f ...2.....01..... 77b7e4f0: 00000020 6ad8000f 00858d10 50000002 ......j.......P +This shows using a text menu to boot an OS:: + + => bootflow scan + => bootfl list + => bootfl menu -t + U-Boot : Boot Menu + + UP and DOWN to choose, ENTER to select + + > 0 mmc1 mmc1.bootdev.whole + 1 mmc1 Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + 2 mmc1 mmc1.bootdev.part_1 + 3 mmc4 mmc4.bootdev.whole + 4 mmc4 Armbian + 5 mmc4 mmc4.bootdev.part_1 + 6 mmc5 mmc5.bootdev.whole + 7 mmc5 ChromeOS + 8 mmc5 ChromeOS + U-Boot : Boot Menu + + UP and DOWN to choose, ENTER to select + + 0 mmc1 mmc1.bootdev.whole + > 1 mmc1 Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + 2 mmc1 mmc1.bootdev.part_1 + 3 mmc4 mmc4.bootdev.whole + 4 mmc4 Armbian + 5 mmc4 mmc4.bootdev.part_1 + 6 mmc5 mmc5.bootdev.whole + 7 mmc5 ChromeOS + 8 mmc5 ChromeOS + U-Boot : Boot Menu + + Selected: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + => bootfl boot + ** Booting bootflow 'mmc1.bootdev.part_1' with extlinux + Ignoring unknown command: ui + Ignoring malformed menu command: autoboot + Ignoring malformed menu command: hidden + Ignoring unknown command: totaltimeout + Fedora-Workstation-armhfp-31-1.9 Boot Options. + 1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + Enter choice: 1 + 1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + Retrieving file: /vmlinuz-5.3.7-301.fc31.armv7hl + Retrieving file: /initramfs-5.3.7-301.fc31.armv7hl.img + append: ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + Retrieving file: /dtb-5.3.7-301.fc31.armv7hl/sandbox.dtb + ... + Return value ------------ @@ -667,6 +731,9 @@ return to U-Boot. If something about the U-Boot processing fails, then the return value $? is 1. If the boot succeeds but for some reason the Operating System returns, then $? is 0, indicating success. +For `bootflow menu` the return value is $? is 0 (true) if an option was choses, +else 1. + For other subcommands, the return value $? is always 0 (true). diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 102b2b5..b97c566 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -604,8 +604,12 @@ static int scan_mmc4_bootdev(struct unit_test_state *uts) /* Check 'bootflow menu' to select a bootflow */ static int bootflow_cmd_menu(struct unit_test_state *uts) { + struct bootstd_priv *std; char prev[3]; + /* get access to the current bootflow */ + ut_assertok(bootstd_get_priv(&std)); + ut_assertok(scan_mmc4_bootdev(uts)); /* Add keypresses to move to and select the second one in the list */ @@ -616,6 +620,17 @@ static int bootflow_cmd_menu(struct unit_test_state *uts) ut_assertok(run_command("bootflow menu", 0)); ut_assert_nextline("Selected: Armbian"); + ut_assertnonnull(std->cur_bootflow); + ut_assert_console_end(); + + /* Check not selecting anything */ + prev[0] = '\e'; + prev[1] = '\0'; + ut_asserteq(1, console_in_puts(prev)); + + ut_asserteq(1, run_command("bootflow menu", 0)); + ut_assertnull(std->cur_bootflow); + ut_assert_nextline("Nothing chosen"); ut_assert_console_end(); return 0; -- cgit v1.1 From cac91b0b728eca99a1f2216dab5fbe86e6578b65 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 Oct 2023 19:14:41 -0600 Subject: expo: Correct background colour Use the correct background colour when using white-on-black. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/expo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boot/expo.c b/boot/expo.c index 139d684..cadb6a0 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -190,10 +190,12 @@ int expo_render(struct expo *exp) struct udevice *dev = exp->display; struct video_priv *vid_priv = dev_get_uclass_priv(dev); struct scene *scn = NULL; + enum colour_idx back; u32 colour; int ret; - colour = video_index_to_colour(vid_priv, VID_WHITE); + back = CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK) ? VID_BLACK : VID_WHITE; + colour = video_index_to_colour(vid_priv, back); ret = video_fill(dev, colour); if (ret) return log_msg_ret("fill", ret); -- cgit v1.1 From 18f8830ab95328431a61960b30bfa1755515e8b9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Nov 2023 10:25:20 -0600 Subject: patman: Split out arg parsing into its own file Move this code into a separate cmdline module, as is done with the other tools. Use the same HAS_TESTS check as buildman Signed-off-by: Simon Glass --- tools/patman/__main__.py | 116 +------------------------------------ tools/patman/cmdline.py | 147 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 113 deletions(-) create mode 100644 tools/patman/cmdline.py diff --git a/tools/patman/__main__.py b/tools/patman/__main__.py index 197ac1a..0e559b5 100755 --- a/tools/patman/__main__.py +++ b/tools/patman/__main__.py @@ -6,7 +6,6 @@ """See README for more information""" -from argparse import ArgumentParser try: import importlib.resources except ImportError: @@ -23,128 +22,19 @@ if __name__ == "__main__": sys.path.append(os.path.join(our_path, '..')) # Our modules +from patman import cmdline from patman import control from patman import func_test -from patman import gitutil -from patman import project -from patman import settings from u_boot_pylib import terminal from u_boot_pylib import test_util from u_boot_pylib import tools -epilog = '''Create patches from commits in a branch, check them and email them -as specified by tags you place in the commits. Use -n to do a dry run first.''' - -parser = ArgumentParser(epilog=epilog) -parser.add_argument('-b', '--branch', type=str, - help="Branch to process (by default, the current branch)") -parser.add_argument('-c', '--count', dest='count', type=int, - default=-1, help='Automatically create patches from top n commits') -parser.add_argument('-e', '--end', type=int, default=0, - help='Commits to skip at end of patch list') -parser.add_argument('-D', '--debug', action='store_true', - help='Enabling debugging (provides a full traceback on error)') -parser.add_argument('-p', '--project', default=project.detect_project(), - help="Project name; affects default option values and " - "aliases [default: %(default)s]") -parser.add_argument('-P', '--patchwork-url', - default='https://patchwork.ozlabs.org', - help='URL of patchwork server [default: %(default)s]') -parser.add_argument('-s', '--start', dest='start', type=int, - default=0, help='Commit to start creating patches from (0 = HEAD)') -parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', - default=False, help='Verbose output of errors and warnings') -parser.add_argument('-H', '--full-help', action='store_true', dest='full_help', - default=False, help='Display the README file') - -subparsers = parser.add_subparsers(dest='cmd') -send = subparsers.add_parser( - 'send', help='Format, check and email patches (default command)') -send.add_argument('-i', '--ignore-errors', action='store_true', - dest='ignore_errors', default=False, - help='Send patches email even if patch errors are found') -send.add_argument('-l', '--limit-cc', dest='limit', type=int, default=None, - help='Limit the cc list to LIMIT entries [default: %(default)s]') -send.add_argument('-m', '--no-maintainers', action='store_false', - dest='add_maintainers', default=True, - help="Don't cc the file maintainers automatically") -send.add_argument( - '--get-maintainer-script', dest='get_maintainer_script', type=str, - action='store', - default=os.path.join(gitutil.get_top_level(), 'scripts', - 'get_maintainer.pl') + ' --norolestats', - help='File name of the get_maintainer.pl (or compatible) script.') -send.add_argument('-n', '--dry-run', action='store_true', dest='dry_run', - default=False, help="Do a dry run (create but don't email patches)") -send.add_argument('-r', '--in-reply-to', type=str, action='store', - help="Message ID that this series is in reply to") -send.add_argument('-t', '--ignore-bad-tags', action='store_true', - default=False, - help='Ignore bad tags / aliases (default=warn)') -send.add_argument('-T', '--thread', action='store_true', dest='thread', - default=False, help='Create patches as a single thread') -send.add_argument('--cc-cmd', dest='cc_cmd', type=str, action='store', - default=None, help='Output cc list for patch file (used by git)') -send.add_argument('--no-binary', action='store_true', dest='ignore_binary', - default=False, - help="Do not output contents of changes in binary files") -send.add_argument('--no-check', action='store_false', dest='check_patch', - default=True, - help="Don't check for patch compliance") -send.add_argument('--tree', dest='check_patch_use_tree', default=False, - action='store_true', - help=("Set `tree` to True. If `tree` is False then we'll " - "pass '--no-tree' to checkpatch (default: tree=%(default)s)")) -send.add_argument('--no-tree', dest='check_patch_use_tree', - action='store_false', help="Set `tree` to False") -send.add_argument('--no-tags', action='store_false', dest='process_tags', - default=True, help="Don't process subject tags as aliases") -send.add_argument('--no-signoff', action='store_false', dest='add_signoff', - default=True, help="Don't add Signed-off-by to patches") -send.add_argument('--smtp-server', type=str, - help="Specify the SMTP server to 'git send-email'") -send.add_argument('--keep-change-id', action='store_true', - help='Preserve Change-Id tags in patches to send.') - -send.add_argument('patchfiles', nargs='*') - -# Only add the 'test' action if the test data files are available. -if os.path.exists(func_test.TEST_DATA_DIR): - test_parser = subparsers.add_parser('test', help='Run tests') - test_parser.add_argument('testname', type=str, default=None, nargs='?', - help="Specify the test to run") - -status = subparsers.add_parser('status', - help='Check status of patches in patchwork') -status.add_argument('-C', '--show-comments', action='store_true', - help='Show comments from each patch') -status.add_argument('-d', '--dest-branch', type=str, - help='Name of branch to create with collected responses') -status.add_argument('-f', '--force', action='store_true', - help='Force overwriting an existing branch') - -# Parse options twice: first to get the project and second to handle -# defaults properly (which depends on project) -# Use parse_known_args() in case 'cmd' is omitted -argv = sys.argv[1:] -args, rest = parser.parse_known_args(argv) -if hasattr(args, 'project'): - settings.Setup(parser, args.project) - args, rest = parser.parse_known_args(argv) - -# If we have a command, it is safe to parse all arguments -if args.cmd: - args = parser.parse_args(argv) -else: - # No command, so insert it after the known arguments and before the ones - # that presumably relate to the 'send' subcommand - nargs = len(rest) - argv = argv[:-nargs] + ['send'] + rest - args = parser.parse_args(argv) if __name__ != "__main__": pass +args = cmdline.parse_args() + if not args.debug: sys.tracebacklimit = 0 diff --git a/tools/patman/cmdline.py b/tools/patman/cmdline.py new file mode 100644 index 0000000..d6496c0 --- /dev/null +++ b/tools/patman/cmdline.py @@ -0,0 +1,147 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2023 Google LLC +# + +"""Handles parsing of buildman arguments + +This creates the argument parser and uses it to parse the arguments passed in +""" + +import argparse +import os +import pathlib +import sys + +from patman import gitutil +from patman import project +from patman import settings + +PATMAN_DIR = pathlib.Path(__file__).parent +HAS_TESTS = os.path.exists(PATMAN_DIR / "func_test.py") + +def parse_args(): + """Parse command line arguments from sys.argv[] + + Returns: + tuple containing: + options: command line options + args: command lin arguments + """ + epilog = '''Create patches from commits in a branch, check them and email + them as specified by tags you place in the commits. Use -n to do a dry + run first.''' + + parser = argparse.ArgumentParser(epilog=epilog) + parser.add_argument('-b', '--branch', type=str, + help="Branch to process (by default, the current branch)") + parser.add_argument('-c', '--count', dest='count', type=int, + default=-1, help='Automatically create patches from top n commits') + parser.add_argument('-e', '--end', type=int, default=0, + help='Commits to skip at end of patch list') + parser.add_argument('-D', '--debug', action='store_true', + help='Enabling debugging (provides a full traceback on error)') + parser.add_argument('-p', '--project', default=project.detect_project(), + help="Project name; affects default option values and " + "aliases [default: %(default)s]") + parser.add_argument('-P', '--patchwork-url', + default='https://patchwork.ozlabs.org', + help='URL of patchwork server [default: %(default)s]') + parser.add_argument('-s', '--start', dest='start', type=int, + default=0, help='Commit to start creating patches from (0 = HEAD)') + parser.add_argument( + '-v', '--verbose', action='store_true', dest='verbose', default=False, + help='Verbose output of errors and warnings') + parser.add_argument( + '-H', '--full-help', action='store_true', dest='full_help', + default=False, help='Display the README file') + + subparsers = parser.add_subparsers(dest='cmd') + send = subparsers.add_parser( + 'send', help='Format, check and email patches (default command)') + send.add_argument('-i', '--ignore-errors', action='store_true', + dest='ignore_errors', default=False, + help='Send patches email even if patch errors are found') + send.add_argument('-l', '--limit-cc', dest='limit', type=int, default=None, + help='Limit the cc list to LIMIT entries [default: %(default)s]') + send.add_argument('-m', '--no-maintainers', action='store_false', + dest='add_maintainers', default=True, + help="Don't cc the file maintainers automatically") + send.add_argument( + '--get-maintainer-script', dest='get_maintainer_script', type=str, + action='store', + default=os.path.join(gitutil.get_top_level(), 'scripts', + 'get_maintainer.pl') + ' --norolestats', + help='File name of the get_maintainer.pl (or compatible) script.') + send.add_argument('-n', '--dry-run', action='store_true', dest='dry_run', + default=False, help="Do a dry run (create but don't email patches)") + send.add_argument('-r', '--in-reply-to', type=str, action='store', + help="Message ID that this series is in reply to") + send.add_argument('-t', '--ignore-bad-tags', action='store_true', + default=False, + help='Ignore bad tags / aliases (default=warn)') + send.add_argument('-T', '--thread', action='store_true', dest='thread', + default=False, help='Create patches as a single thread') + send.add_argument('--cc-cmd', dest='cc_cmd', type=str, action='store', + default=None, help='Output cc list for patch file (used by git)') + send.add_argument('--no-binary', action='store_true', dest='ignore_binary', + default=False, + help="Do not output contents of changes in binary files") + send.add_argument('--no-check', action='store_false', dest='check_patch', + default=True, + help="Don't check for patch compliance") + send.add_argument( + '--tree', dest='check_patch_use_tree', default=False, + action='store_true', + help=("Set `tree` to True. If `tree` is False then we'll pass " + "'--no-tree' to checkpatch (default: tree=%(default)s)")) + send.add_argument('--no-tree', dest='check_patch_use_tree', + action='store_false', help="Set `tree` to False") + send.add_argument( + '--no-tags', action='store_false', dest='process_tags', default=True, + help="Don't process subject tags as aliases") + send.add_argument('--no-signoff', action='store_false', dest='add_signoff', + default=True, help="Don't add Signed-off-by to patches") + send.add_argument('--smtp-server', type=str, + help="Specify the SMTP server to 'git send-email'") + send.add_argument('--keep-change-id', action='store_true', + help='Preserve Change-Id tags in patches to send.') + + send.add_argument('patchfiles', nargs='*') + + # Only add the 'test' action if the test data files are available. + if HAS_TESTS: + test_parser = subparsers.add_parser('test', help='Run tests') + test_parser.add_argument('testname', type=str, default=None, nargs='?', + help="Specify the test to run") + + status = subparsers.add_parser('status', + help='Check status of patches in patchwork') + status.add_argument('-C', '--show-comments', action='store_true', + help='Show comments from each patch') + status.add_argument( + '-d', '--dest-branch', type=str, + help='Name of branch to create with collected responses') + status.add_argument('-f', '--force', action='store_true', + help='Force overwriting an existing branch') + + # Parse options twice: first to get the project and second to handle + # defaults properly (which depends on project) + # Use parse_known_args() in case 'cmd' is omitted + argv = sys.argv[1:] + args, rest = parser.parse_known_args(argv) + if hasattr(args, 'project'): + settings.Setup(parser, args.project) + args, rest = parser.parse_known_args(argv) + + # If we have a command, it is safe to parse all arguments + if args.cmd: + args = parser.parse_args(argv) + else: + # No command, so insert it after the known arguments and before the ones + # that presumably relate to the 'send' subcommand + nargs = len(rest) + argv = argv[:-nargs] + ['send'] + rest + args = parser.parse_args(argv) + + return args -- cgit v1.1 From e296a3c73d22bf95f38318a8dac2dc0177a3b145 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Nov 2023 10:25:21 -0600 Subject: patman: Move the main program into a function Add a new run_patman() function to hold the main logic. Signed-off-by: Simon Glass --- tools/patman/__main__.py | 127 +++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/tools/patman/__main__.py b/tools/patman/__main__.py index 0e559b5..8785029 100755 --- a/tools/patman/__main__.py +++ b/tools/patman/__main__.py @@ -30,63 +30,70 @@ from u_boot_pylib import test_util from u_boot_pylib import tools -if __name__ != "__main__": - pass - -args = cmdline.parse_args() - -if not args.debug: - sys.tracebacklimit = 0 - -# Run our meagre tests -if args.cmd == 'test': - from patman import func_test - from patman import test_checkpatch - - result = test_util.run_test_suites( - 'patman', False, False, False, None, None, None, - [test_checkpatch.TestPatch, func_test.TestFunctional, - 'gitutil', 'settings']) - - sys.exit(0 if result.wasSuccessful() else 1) - -# Process commits, produce patches files, check them, email them -elif args.cmd == 'send': - # Called from git with a patch filename as argument - # Printout a list of additional CC recipients for this patch - if args.cc_cmd: - fd = open(args.cc_cmd, 'r') - re_line = re.compile('(\S*) (.*)') - for line in fd.readlines(): - match = re_line.match(line) - if match and match.group(1) == args.patchfiles[0]: - for cc in match.group(2).split('\0'): - cc = cc.strip() - if cc: - print(cc) - fd.close() - - elif args.full_help: - with importlib.resources.path('patman', 'README.rst') as readme: - tools.print_full_help(str(readme)) - else: - # If we are not processing tags, no need to warning about bad ones - if not args.process_tags: - args.ignore_bad_tags = True - control.send(args) - -# Check status of patches in patchwork -elif args.cmd == 'status': - ret_code = 0 - try: - control.patchwork_status(args.branch, args.count, args.start, args.end, - args.dest_branch, args.force, - args.show_comments, args.patchwork_url) - except Exception as e: - terminal.tprint('patman: %s: %s' % (type(e).__name__, e), - colour=terminal.Color.RED) - if args.debug: - print() - traceback.print_exc() - ret_code = 1 - sys.exit(ret_code) +def run_patman(): + """Run patamn + + This is the main program. It collects arguments and runs either the tests or + the control module. + """ + args = cmdline.parse_args() + + if not args.debug: + sys.tracebacklimit = 0 + + # Run our meagre tests + if args.cmd == 'test': + from patman import func_test + from patman import test_checkpatch + + result = test_util.run_test_suites( + 'patman', False, False, False, None, None, None, + [test_checkpatch.TestPatch, func_test.TestFunctional, + 'gitutil', 'settings']) + + sys.exit(0 if result.wasSuccessful() else 1) + + # Process commits, produce patches files, check them, email them + elif args.cmd == 'send': + # Called from git with a patch filename as argument + # Printout a list of additional CC recipients for this patch + if args.cc_cmd: + fd = open(args.cc_cmd, 'r') + re_line = re.compile('(\S*) (.*)') + for line in fd.readlines(): + match = re_line.match(line) + if match and match.group(1) == args.patchfiles[0]: + for cc in match.group(2).split('\0'): + cc = cc.strip() + if cc: + print(cc) + fd.close() + + elif args.full_help: + with importlib.resources.path('patman', 'README.rst') as readme: + tools.print_full_help(str(readme)) + else: + # If we are not processing tags, no need to warning about bad ones + if not args.process_tags: + args.ignore_bad_tags = True + control.send(args) + + # Check status of patches in patchwork + elif args.cmd == 'status': + ret_code = 0 + try: + control.patchwork_status(args.branch, args.count, args.start, args.end, + args.dest_branch, args.force, + args.show_comments, args.patchwork_url) + except Exception as e: + terminal.tprint('patman: %s: %s' % (type(e).__name__, e), + colour=terminal.Color.RED) + if args.debug: + print() + traceback.print_exc() + ret_code = 1 + sys.exit(ret_code) + + +if __name__ == "__main__": + sys.exit(run_patman()) -- cgit v1.1 From 21229c921bf62a5480e887d71ba13ac482282870 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Nov 2023 10:25:22 -0600 Subject: patman: Correct easy pylint warnings in __main__ Tidy up the code a little to reduce the number of pylint warnings. Signed-off-by: Simon Glass --- tools/patman/__main__.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/patman/__main__.py b/tools/patman/__main__.py index 8785029..3ca858c 100755 --- a/tools/patman/__main__.py +++ b/tools/patman/__main__.py @@ -16,10 +16,10 @@ import re import sys import traceback -if __name__ == "__main__": - # Allow 'from patman import xxx to work' - our_path = os.path.dirname(os.path.realpath(__file__)) - sys.path.append(os.path.join(our_path, '..')) +# Allow 'from patman import xxx to work' +# pylint: disable=C0413 +our_path = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(our_path, '..')) # Our modules from patman import cmdline @@ -43,6 +43,7 @@ def run_patman(): # Run our meagre tests if args.cmd == 'test': + # pylint: disable=C0415 from patman import func_test from patman import test_checkpatch @@ -58,16 +59,15 @@ def run_patman(): # Called from git with a patch filename as argument # Printout a list of additional CC recipients for this patch if args.cc_cmd: - fd = open(args.cc_cmd, 'r') - re_line = re.compile('(\S*) (.*)') - for line in fd.readlines(): - match = re_line.match(line) - if match and match.group(1) == args.patchfiles[0]: - for cc in match.group(2).split('\0'): - cc = cc.strip() - if cc: - print(cc) - fd.close() + re_line = re.compile(r'(\S*) (.*)') + with open(args.cc_cmd, 'r', encoding='utf-8') as inf: + for line in inf.readlines(): + match = re_line.match(line) + if match and match.group(1) == args.patchfiles[0]: + for cca in match.group(2).split('\0'): + cca = cca.strip() + if cca: + print(cca) elif args.full_help: with importlib.resources.path('patman', 'README.rst') as readme: @@ -85,8 +85,8 @@ def run_patman(): control.patchwork_status(args.branch, args.count, args.start, args.end, args.dest_branch, args.force, args.show_comments, args.patchwork_url) - except Exception as e: - terminal.tprint('patman: %s: %s' % (type(e).__name__, e), + except Exception as exc: + terminal.tprint(f'patman: {type(exc).__name__}: {exc}', colour=terminal.Color.RED) if args.debug: print() -- cgit v1.1 From dfdf621ff285da4e8e5995e05d570ebe7eb2e318 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Nov 2023 10:25:23 -0600 Subject: patman: Avoid using func_test at top level Import this only when it is needed, since it is not present when installed via 'pip install'. Signed-off-by: Simon Glass Fixes: https://source.denx.de/u-boot/u-boot/-/issues/26 --- tools/patman/__main__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/patman/__main__.py b/tools/patman/__main__.py index 3ca858c..d53f686 100755 --- a/tools/patman/__main__.py +++ b/tools/patman/__main__.py @@ -24,7 +24,6 @@ sys.path.append(os.path.join(our_path, '..')) # Our modules from patman import cmdline from patman import control -from patman import func_test from u_boot_pylib import terminal from u_boot_pylib import test_util from u_boot_pylib import tools -- cgit v1.1 From abf7004321c05333afb56ae230095f9bee55e924 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 4 Nov 2023 10:25:24 -0600 Subject: patman: Correct Python 3.6 behaviour The importlib_resources import is not actually used. Fix this so that patman can run on Python 3.6 to some extent, once 'pip3 install importlib-resources' has been run. Signed-off-by: Simon Glass --- tools/patman/__main__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/patman/__main__.py b/tools/patman/__main__.py index d53f686..f645b38 100755 --- a/tools/patman/__main__.py +++ b/tools/patman/__main__.py @@ -7,10 +7,10 @@ """See README for more information""" try: - import importlib.resources + from importlib import resources except ImportError: # for Python 3.6 - import importlib_resources + import importlib_resources as resources import os import re import sys @@ -69,7 +69,7 @@ def run_patman(): print(cca) elif args.full_help: - with importlib.resources.path('patman', 'README.rst') as readme: + with resources.path('patman', 'README.rst') as readme: tools.print_full_help(str(readme)) else: # If we are not processing tags, no need to warning about bad ones -- cgit v1.1 From 2c61c0eb14289cbd94bff51c175f2410418d64d0 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 4 Nov 2023 20:40:43 +0200 Subject: dm: Do not enable debug messages by default CONFIG_DM_WARN has a text indicating that these messages should only provided when debugging. This implies that the setting must be default no. We should still create debug messages. Reported-by: Andre Przywara Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- drivers/core/Kconfig | 1 - include/dm/util.h | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index fe5c41d..737d459 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -48,7 +48,6 @@ config VPL_DM config DM_WARN bool "Enable warnings in driver model" depends on DM - default y help Enable this to see warnings related to driver model. diff --git a/include/dm/util.h b/include/dm/util.h index 89206cc..95c3527 100644 --- a/include/dm/util.h +++ b/include/dm/util.h @@ -11,9 +11,7 @@ struct dm_stats; #if CONFIG_IS_ENABLED(DM_WARN) #define dm_warn(fmt...) log(LOGC_DM, LOGL_WARNING, ##fmt) #else -static inline void dm_warn(const char *fmt, ...) -{ -} +#define dm_warn(fmt...) log(LOGC_DM, LOGL_DEBUG, ##fmt) #endif struct list_head; -- cgit v1.1 From f6d76e68784591ee32c173a08535c4dff4a76a1e Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Sat, 4 Nov 2023 15:57:33 -0400 Subject: sandbox: Close file after mmaping it After opening pathname, we must close ifd once we are done with it. Fixes: b9274095c2c ("sandbox: Add a way to map a file into memory") Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- arch/sandbox/cpu/os.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 85d0d6a..95c26d8 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -219,7 +219,7 @@ int os_map_file(const char *pathname, int os_flags, void **bufp, int *sizep) { void *ptr; off_t size; - int ifd; + int ifd, ret = 0; ifd = os_open(pathname, os_flags); if (ifd < 0) { @@ -229,23 +229,28 @@ int os_map_file(const char *pathname, int os_flags, void **bufp, int *sizep) size = os_filesize(ifd); if (size < 0) { printf("Cannot get file size of '%s'\n", pathname); - return -EIO; + ret = -EIO; + goto out; } if ((unsigned long long)size > (unsigned long long)SIZE_MAX) { printf("File '%s' too large to map\n", pathname); - return -EIO; + ret = -EIO; + goto out; } ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, ifd, 0); if (ptr == MAP_FAILED) { printf("Can't map file '%s': %s\n", pathname, strerror(errno)); - return -EPERM; + ret = -EPERM; + goto out; } *bufp = ptr; *sizep = size; - return 0; +out: + os_close(ifd); + return ret; } int os_unmap(void *buf, int size) -- cgit v1.1 From 0d4d9f94c555577f78cddc372c307465fc92413e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 7 Nov 2023 10:17:40 +0100 Subject: bootstage: Correct exhasuted typo Correct this typo in the warning message shown when no more bootstage records can be added. Signed-off-by: Simon Glass Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- common/bootstage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/bootstage.c b/common/bootstage.c index a68d883..0e6d807 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -137,7 +137,7 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name, rec->flags = flags; rec->id = id; } else { - log_warning("Bootstage space exhasuted\n"); + log_warning("Bootstage space exhausted\n"); } } -- cgit v1.1