diff --git a/Makefile b/Makefile index c746de62becdb7aa782d7a603d4c3f6fae8b6162..d51299034feb60f43bab0f83bc384fe1e304ea0f 100644 --- a/Makefile +++ b/Makefile @@ -770,6 +770,7 @@ libs-$(CONFIG_API) += api/ libs-$(CONFIG_HAS_POST) += post/ libs-$(CONFIG_UNIT_TEST) += test/ test/dm/ libs-$(CONFIG_UT_ENV) += test/env/ +libs-$(CONFIG_UT_OPTEE) += test/optee/ libs-$(CONFIG_UT_OVERLAY) += test/overlay/ libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 47dfb476d37d46625328f892986195ed746e3d3f..79094fb7f353b4981d9f446c8c0eb6d34d4c3ce0 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -816,10 +816,10 @@ void *os_find_text_base(void) char *end = memchr(line, '-', len); if (end) { - unsigned long long addr; + uintptr_t addr; *end = '\0'; - if (sscanf(line, "%llx", &addr) == 1) + if (sscanf(line, "%zx", &addr) == 1) base = (void *)addr; } } diff --git a/common/image-fdt.c b/common/image-fdt.c index 4247dcee0c4f71d6626ffa31337c9313ff45b335..48388488d98defeeabd7641000d68f517aaf6a1f 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef CONFIG_SYS_FDT_PAD #define CONFIG_SYS_FDT_PAD 0x3000 @@ -561,6 +562,13 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, } } + fdt_ret = optee_copy_fdt_nodes(gd->fdt_blob, blob); + if (fdt_ret) { + printf("ERROR: transfer of optee nodes to new fdt failed: %s\n", + fdt_strerror(fdt_ret)); + goto err; + } + /* Delete the old LMB reservation */ if (lmb) lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob, diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 761ee29f4174470a6bf3fd0747741cd52af2de8c..3425ed11b16479942a807234d3eda92a861535ef 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -15,18 +15,6 @@ DECLARE_GLOBAL_DATA_PTR; -int pinctrl_decode_pin_config(const void *blob, int node) -{ - int flags = 0; - - if (fdtdec_get_bool(blob, node, "bias-pull-up")) - flags |= 1 << PIN_CONFIG_BIAS_PULL_UP; - else if (fdtdec_get_bool(blob, node, "bias-pull-down")) - flags |= 1 << PIN_CONFIG_BIAS_PULL_DOWN; - - return flags; -} - #if CONFIG_IS_ENABLED(PINCTRL_FULL) /** * pinctrl_config_one() - apply pinctrl settings for a single node diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 3eca34fbf7009e18da8c2fd7a98bc00c539cde1f..692e5fc8cbfa11a13fe69d9e72ea6eab00a16e1e 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -369,19 +369,6 @@ int pinctrl_request_noflags(struct udevice *dev, int func); */ int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph); -/** - * pinctrl_decode_pin_config() - decode pin configuration flags - * - * This decodes some of the PIN_CONFIG values into flags, with each value - * being (1 << pin_cfg). This does not support things with values like the - * slew rate. - * - * @blob: Device tree blob - * @node: Node containing the PIN_CONFIG values - * @return decoded flag value, or -ve on error - */ -int pinctrl_decode_pin_config(const void *blob, int node); - /** * pinctrl_get_gpio_mux() - get the mux value for a particular GPIO * diff --git a/include/fdtdec.h b/include/fdtdec.h index f1e58f9732dbf1de5957781b28bc8da97b92cfec..696e0fd024d5d1ca972401e9aa651e30da439742 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -1061,6 +1061,7 @@ static inline int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) * @param basename base name of the node to create * @param carveout information about the carveout region * @param phandlep return location for the phandle of the carveout region + * can be NULL if no phandle should be added * @return 0 on success or a negative error code on failure */ int fdtdec_add_reserved_memory(void *blob, const char *basename, diff --git a/include/tee/optee.h b/include/tee/optee.h index 9446928fd4896de4e728a3940c586e47315cad8f..121b30a3030e89750c410b3780a04040aebb565f 100644 --- a/include/tee/optee.h +++ b/include/tee/optee.h @@ -67,4 +67,13 @@ static inline int optee_verify_bootm_image(unsigned long image_addr, } #endif +#if defined(CONFIG_OPTEE) && defined(CONFIG_OF_LIBFDT) +int optee_copy_fdt_nodes(const void *old_blob, void *new_blob); +#else +static inline int optee_copy_fdt_nodes(const void *old_blob, void *new_blob) +{ + return 0; +} +#endif + #endif /* _OPTEE_H */ diff --git a/include/test/optee.h b/include/test/optee.h new file mode 100644 index 0000000000000000000000000000000000000000..a8c6e6395f55eb4677090103d418939315e1ba6a --- /dev/null +++ b/include/test/optee.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#ifndef __TEST_OPTEE_H__ +#define __TEST_OPTEE_H__ + +#include + +/* Declare a new environment test */ +#define OPTEE_TEST(_name, _flags) UNIT_TEST(_name, _flags, optee_test) + +#endif /* __TEST_OPTEE_H__ */ diff --git a/include/test/suites.h b/include/test/suites.h index 01bee09346cffa7eccc567cbdd529d5ef1b304b9..20970f08d6646795ec7aaae24429f858dbd5ed88 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -28,6 +28,7 @@ int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_ut_lib(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_optee(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 125d9dbf26395c2262b338c6bb7d77d0e7a08bcb..61af3472e6a41352f3fd2f43a8d56a4b5be5e48a 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1309,7 +1309,8 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, } if (addr == carveout->start && (addr + size) == carveout->end) { - *phandlep = fdt_get_phandle(blob, node); + if (phandlep) + *phandlep = fdt_get_phandle(blob, node); return 0; } } @@ -1338,13 +1339,15 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, if (node < 0) return node; - err = fdt_generate_phandle(blob, &phandle); - if (err < 0) - return err; + if (phandlep) { + err = fdt_generate_phandle(blob, &phandle); + if (err < 0) + return err; - err = fdtdec_set_phandle(blob, node, phandle); - if (err < 0) - return err; + err = fdtdec_set_phandle(blob, node, phandle); + if (err < 0) + return err; + } /* store one or two address cells */ if (na > 1) diff --git a/lib/optee/optee.c b/lib/optee/optee.c index db92cd9af293ccf94b7c1aa0d316a0eb6f4501c9..c883c498e1d4ce80f0d59d219caf9af503ee93a9 100644 --- a/lib/optee/optee.c +++ b/lib/optee/optee.c @@ -5,6 +5,8 @@ */ #include +#include +#include #include #define optee_hdr_err_msg \ @@ -63,3 +65,141 @@ error: return ret; } + +#if defined(CONFIG_OF_LIBFDT) +static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob) +{ + int old_offs, offs, ret, len; + const void *prop; + + old_offs = fdt_path_offset(old_blob, "/firmware/optee"); + if (old_offs < 0) { + debug("Original OP-TEE Device Tree node not found"); + return old_offs; + } + + offs = fdt_path_offset(fdt_blob, "/firmware"); + if (offs < 0) { + offs = fdt_path_offset(fdt_blob, "/"); + if (offs < 0) + return offs; + + offs = fdt_add_subnode(fdt_blob, offs, "firmware"); + if (offs < 0) + return offs; + } + + offs = fdt_add_subnode(fdt_blob, offs, "optee"); + if (offs < 0) + return ret; + + /* copy the compatible property */ + prop = fdt_getprop(old_blob, old_offs, "compatible", &len); + if (!prop) { + debug("missing OP-TEE compatible property"); + return -EINVAL; + } + + ret = fdt_setprop(fdt_blob, offs, "compatible", prop, len); + if (ret < 0) + return ret; + + /* copy the method property */ + prop = fdt_getprop(old_blob, old_offs, "method", &len); + if (!prop) { + debug("missing OP-TEE method property"); + return -EINVAL; + } + + ret = fdt_setprop(fdt_blob, offs, "method", prop, len); + if (ret < 0) + return ret; + + return 0; +} + +int optee_copy_fdt_nodes(const void *old_blob, void *new_blob) +{ + int nodeoffset, subnode, ret; + struct fdt_resource res; + + if (fdt_check_header(old_blob)) + return -EINVAL; + + if (fdt_check_header(new_blob)) + return -EINVAL; + + /* only proceed if there is an /firmware/optee node */ + if (fdt_path_offset(old_blob, "/firmware/optee") < 0) { + debug("No OP-TEE firmware node in old fdt, nothing to do"); + return 0; + } + + /* + * Do not proceed if the target dt already has an OP-TEE node. + * In this case assume that the system knows better somehow, + * so do not interfere. + */ + if (fdt_path_offset(new_blob, "/firmware/optee") >= 0) { + debug("OP-TEE Device Tree node already exists in target"); + return 0; + } + + ret = optee_copy_firmware_node(old_blob, new_blob); + if (ret < 0) { + printf("Failed to add OP-TEE firmware node\n"); + return ret; + } + + /* optee inserts its memory regions as reserved-memory nodes */ + nodeoffset = fdt_subnode_offset(old_blob, 0, "reserved-memory"); + if (nodeoffset >= 0) { + subnode = fdt_first_subnode(old_blob, nodeoffset); + while (subnode >= 0) { + const char *name = fdt_get_name(old_blob, + subnode, NULL); + if (!name) + return -EINVAL; + + /* only handle optee reservations */ + if (strncmp(name, "optee", 5)) + continue; + + /* check if this subnode has a reg property */ + ret = fdt_get_resource(old_blob, subnode, "reg", 0, + &res); + if (!ret) { + struct fdt_memory carveout = { + .start = res.start, + .end = res.end, + }; + char *oldname, *nodename, *tmp; + + oldname = strdup(name); + if (!oldname) + return -ENOMEM; + + tmp = oldname; + nodename = strsep(&tmp, "@"); + if (!nodename) { + free(oldname); + return -EINVAL; + } + + ret = fdtdec_add_reserved_memory(new_blob, + nodename, + &carveout, + NULL); + free(oldname); + + if (ret < 0) + return ret; + } + + subnode = fdt_next_subnode(old_blob, subnode); + } + } + + return 0; +} +#endif diff --git a/test/Kconfig b/test/Kconfig index 48a0e501f88f63aff0a53a5eb67de09219f8d886..f53629aac5a14ac1a403174ac5712b94b1b7ab78 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -33,4 +33,5 @@ config UT_UNICODE source "test/dm/Kconfig" source "test/env/Kconfig" +source "test/optee/Kconfig" source "test/overlay/Kconfig" diff --git a/test/cmd_ut.c b/test/cmd_ut.c index e3b89504e775b8fe4ff6d6277de12dd1de0d6ffc..2781f8bd5668cafdde519bb1653cdc3e8a7f8172 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -43,6 +43,9 @@ static cmd_tbl_t cmd_ut_sub[] = { #if defined(CONFIG_UT_ENV) U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""), #endif +#ifdef CONFIG_UT_OPTEE + U_BOOT_CMD_MKENT(optee, CONFIG_SYS_MAXARGS, 1, do_ut_optee, "", ""), +#endif #ifdef CONFIG_UT_OVERLAY U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""), #endif @@ -114,6 +117,9 @@ static char ut_help_text[] = #ifdef CONFIG_UT_LIB "ut lib [test-name] - test library functions\n" #endif +#ifdef CONFIG_UT_OPTEE + "ut optee [test-name]\n" +#endif #ifdef CONFIG_UT_OVERLAY "ut overlay [test-name]\n" #endif diff --git a/test/optee/Kconfig b/test/optee/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..2f6834aa3b4da756cccbf29844140ddab69721a2 --- /dev/null +++ b/test/optee/Kconfig @@ -0,0 +1,7 @@ +config UT_OPTEE + bool "Enable OP-TEE Unit Tests" + depends on UNIT_TEST && OF_CONTROL && OPTEE + default y + help + This enables the 'ut optee' command which runs a series of unit + tests on the optee library code.. diff --git a/test/optee/Makefile b/test/optee/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8793fd7ad6109367a3be4aa0b48d477552bf5c53 --- /dev/null +++ b/test/optee/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + +# Test files +obj-y += cmd_ut_optee.o + +DTC_FLAGS += -@ + +# DT overlays +obj-y += test-optee-base.dtb.o +obj-y += test-optee-optee.dtb.o +obj-y += test-optee-no-optee.dtb.o diff --git a/test/optee/cmd_ut_optee.c b/test/optee/cmd_ut_optee.c new file mode 100644 index 0000000000000000000000000000000000000000..670682f3d41eddf32216d9012b1db4dda7808363 --- /dev/null +++ b/test/optee/cmd_ut_optee.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* 4k ought to be enough for anybody */ +#define FDT_COPY_SIZE (4 * SZ_1K) + +extern u32 __dtb_test_optee_base_begin; +extern u32 __dtb_test_optee_optee_begin; +extern u32 __dtb_test_optee_no_optee_begin; + +static void *fdt; +static bool expect_success; + +static int optee_fdt_firmware(struct unit_test_state *uts) +{ + const void *prop; + int offs, len; + + offs = fdt_path_offset(fdt, "/firmware/optee"); + ut_assert(expect_success ? offs >= 0 : offs < 0); + + /* only continue if we have an optee node */ + if (offs < 0) + return CMD_RET_SUCCESS; + + prop = fdt_getprop(fdt, offs, "compatible", &len); + ut_assertok(strncmp((const char *)prop, "linaro,optee-tz", len)); + + prop = fdt_getprop(fdt, offs, "method", &len); + ut_assert(strncmp(prop, "hvc", 3) == 0 || strncmp(prop, "smc", 3) == 0); + + return CMD_RET_SUCCESS; +} +OPTEE_TEST(optee_fdt_firmware, 0); + +static int optee_fdt_protected_memory(struct unit_test_state *uts) +{ + int offs, subnode; + bool found; + + offs = fdt_path_offset(fdt, "/firmware/optee"); + ut_assert(expect_success ? offs >= 0 : offs < 0); + + /* only continue if we have an optee node */ + if (offs < 0) + return CMD_RET_SUCCESS; + + /* optee inserts its memory regions as reserved-memory nodes */ + offs = fdt_subnode_offset(fdt, 0, "reserved-memory"); + ut_assert(offs >= 0); + + subnode = fdt_first_subnode(fdt, offs); + ut_assert(subnode); + + found = 0; + while (subnode >= 0) { + const char *name = fdt_get_name(fdt, subnode, NULL); + struct fdt_resource res; + + ut_assert(name); + + /* only handle optee reservations */ + if (strncmp(name, "optee", 5)) + continue; + + found = true; + + /* check if this subnode has a reg property */ + ut_assertok(fdt_get_resource(fdt, subnode, "reg", 0, &res)); + subnode = fdt_next_subnode(fdt, subnode); + } + + ut_assert(found); + + return CMD_RET_SUCCESS; +} +OPTEE_TEST(optee_fdt_protected_memory, 0); + +int do_ut_optee(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct unit_test *tests = ll_entry_start(struct unit_test, + optee_test); + const int n_ents = ll_entry_count(struct unit_test, optee_test); + struct unit_test_state *uts; + void *fdt_optee = &__dtb_test_optee_optee_begin; + void *fdt_no_optee = &__dtb_test_optee_no_optee_begin; + void *fdt_base = &__dtb_test_optee_base_begin; + int ret = -ENOMEM; + + uts = calloc(1, sizeof(*uts)); + if (!uts) + return -ENOMEM; + + ut_assertok(fdt_check_header(fdt_base)); + ut_assertok(fdt_check_header(fdt_optee)); + ut_assertok(fdt_check_header(fdt_no_optee)); + + fdt = malloc(FDT_COPY_SIZE); + if (!fdt) + return ret; + + /* + * Resize the FDT to 4k so that we have room to operate on + * + * (and relocate it since the memory might be mapped + * read-only) + */ + ut_assertok(fdt_open_into(fdt_base, fdt, FDT_COPY_SIZE)); + + /* + * (1) Try to copy optee nodes from empty dt. + * This should still run successfully. + */ + ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt)); + + expect_success = false; + ret = cmd_ut_category("optee", tests, n_ents, argc, argv); + + /* (2) Try to copy optee nodes from prefilled dt */ + ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); + + expect_success = true; + ret = cmd_ut_category("optee", tests, n_ents, argc, argv); + + /* (3) Try to copy OP-TEE nodes into a already filled DT */ + ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE)); + ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); + + expect_success = true; + ret = cmd_ut_category("optee", tests, n_ents, argc, argv); + + free(fdt); + return ret; +} diff --git a/test/optee/test-optee-base.dts b/test/optee/test-optee-base.dts new file mode 100644 index 0000000000000000000000000000000000000000..3c1d0c60efe98b462098e67dbc852a409d7f789b --- /dev/null +++ b/test/optee/test-optee-base.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; +}; + + diff --git a/test/optee/test-optee-no-optee.dts b/test/optee/test-optee-no-optee.dts new file mode 100644 index 0000000000000000000000000000000000000000..3c1d0c60efe98b462098e67dbc852a409d7f789b --- /dev/null +++ b/test/optee/test-optee-no-optee.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; +}; + + diff --git a/test/optee/test-optee-optee.dts b/test/optee/test-optee-optee.dts new file mode 100644 index 0000000000000000000000000000000000000000..11e26a2728655d7e0494167fd86bc6b0d21001d4 --- /dev/null +++ b/test/optee/test-optee-optee.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + optee_shm@32000000 { + reg = <0x00 0x32000000 0x00 0x400000>; + }; + + optee_core@30000000 { + reg = <0x00 0x30000000 0x00 0x2000000>; + }; + }; +}; diff --git a/tools/patman/cros_subprocess.py b/tools/patman/cros_subprocess.py index 0f0d60dfb7ae96fda2478a6f34c99ec9951f8688..efd0a5aaf72f04d9f7ffb963b0a2045910dab920 100644 --- a/tools/patman/cros_subprocess.py +++ b/tools/patman/cros_subprocess.py @@ -6,11 +6,11 @@ # Licensed to PSF under a Contributor Agreement. # See http://www.python.org/2.4/license for licensing details. -"""Subprocress execution +"""Subprocess execution This module holds a subclass of subprocess.Popen with our own required features, mainly that we get access to the subprocess output while it -is running rather than just at the end. This makes it easiler to show +is running rather than just at the end. This makes it easier to show progress information and filter output in real time. """ diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index dce7fa25b6447cf66ccbfc3572efc472e38032cd..a2a225c6b903bbf940b0902852d76788a5a46c9d 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -23,7 +23,7 @@ def LogCmd(commit_range, git_dir=None, oneline=False, reverse=False, Args: commit_range: Range expression to use for log, None for none - git_dir: Path to git repositiory (None to use default) + git_dir: Path to git repository (None to use default) oneline: True to use --oneline, else False reverse: True to reverse the log (--reverse) count: Number of commits to list, or None for no limit @@ -166,7 +166,7 @@ def CountCommitsInRange(git_dir, range_expr): git_dir: Directory containing git repo range_expr: Range to check Return: - Number of patches that exist in the supplied rangem or None if none + Number of patches that exist in the supplied range or None if none were found """ pipe = [LogCmd(range_expr, git_dir=git_dir, oneline=True)] diff --git a/tools/patman/series.py b/tools/patman/series.py index 02a1113ad017ba6079c0ad4e480529ee8c0c22cf..a15f7625edcf29ca0b9138878f81e788ab1ea5ca 100644 --- a/tools/patman/series.py +++ b/tools/patman/series.py @@ -251,7 +251,7 @@ class Series(dict): cover_cc = [tools.FromUnicode(m) for m in cover_cc] cc_list = '\0'.join([tools.ToUnicode(x) for x in sorted(set(cover_cc + all_ccs))]) - print(cover_fname, cc_list.encode('utf-8'), file=fd) + print(cover_fname, cc_list, file=fd) fd.close() return fname diff --git a/tools/patman/terminal.py b/tools/patman/terminal.py index 4ceab189bf3ccf1fe8797b8708b381d1ac8ee9e8..7a3b658b00e866fa609d1bf28114790deb0e4234 100644 --- a/tools/patman/terminal.py +++ b/tools/patman/terminal.py @@ -128,7 +128,7 @@ class Color(object): return '' def Stop(self): - """Retruns a stop color code. + """Returns a stop color code. Returns: If color is enabled, returns an ANSI color reset sequence,