1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * 'cedit' command 4 * 5 * Copyright 2023 Google LLC 6 * Written by Simon Glass <sjg@chromium.org> 7 */ 8 9#include <common.h> 10#include <abuf.h> 11#include <cedit.h> 12#include <command.h> 13#include <dm.h> 14#include <expo.h> 15#include <fs.h> 16#include <malloc.h> 17#include <mapmem.h> 18#include <dm/ofnode.h> 19#include <linux/sizes.h> 20 21struct expo *cur_exp; 22 23static int check_cur_expo(void) 24{ 25 if (!cur_exp) { 26 printf("No expo loaded\n"); 27 return -ENOENT; 28 } 29 30 return 0; 31} 32 33static int do_cedit_load(struct cmd_tbl *cmdtp, int flag, int argc, 34 char *const argv[]) 35{ 36 const char *fname; 37 struct expo *exp; 38 oftree tree; 39 ulong size; 40 void *buf; 41 int ret; 42 43 if (argc < 4) 44 return CMD_RET_USAGE; 45 fname = argv[3]; 46 47 ret = fs_load_alloc(argv[1], argv[2], argv[3], SZ_1M, 0, &buf, &size); 48 if (ret) { 49 printf("File not found\n"); 50 return CMD_RET_FAILURE; 51 } 52 53 tree = oftree_from_fdt(buf); 54 if (!oftree_valid(tree)) { 55 printf("Cannot create oftree\n"); 56 return CMD_RET_FAILURE; 57 } 58 59 ret = expo_build(oftree_root(tree), &exp); 60 oftree_dispose(tree); 61 if (ret) { 62 printf("Failed to build expo: %dE\n", ret); 63 return CMD_RET_FAILURE; 64 } 65 66 cur_exp = exp; 67 68 return 0; 69} 70 71static int do_cedit_write_fdt(struct cmd_tbl *cmdtp, int flag, int argc, 72 char *const argv[]) 73{ 74 const char *fname; 75 struct abuf buf; 76 loff_t bytes; 77 int ret; 78 79 if (argc < 4) 80 return CMD_RET_USAGE; 81 fname = argv[3]; 82 83 if (check_cur_expo()) 84 return CMD_RET_FAILURE; 85 86 ret = cedit_write_settings(cur_exp, &buf); 87 if (ret) { 88 printf("Failed to write settings: %dE\n", ret); 89 return CMD_RET_FAILURE; 90 } 91 92 if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY)) 93 return CMD_RET_FAILURE; 94 95 ret = fs_write(fname, map_to_sysmem(abuf_data(&buf)), 0, 96 abuf_size(&buf), &bytes); 97 if (ret) 98 return CMD_RET_FAILURE; 99 100 return 0; 101} 102 103static int do_cedit_read_fdt(struct cmd_tbl *cmdtp, int flag, int argc, 104 char *const argv[]) 105{ 106 const char *fname; 107 void *buf; 108 oftree tree; 109 ulong size; 110 int ret; 111 112 if (argc < 4) 113 return CMD_RET_USAGE; 114 fname = argv[3]; 115 116 ret = fs_load_alloc(argv[1], argv[2], argv[3], SZ_1M, 0, &buf, &size); 117 if (ret) { 118 printf("File not found\n"); 119 return CMD_RET_FAILURE; 120 } 121 122 tree = oftree_from_fdt(buf); 123 if (!oftree_valid(tree)) { 124 free(buf); 125 printf("Cannot create oftree\n"); 126 return CMD_RET_FAILURE; 127 } 128 129 ret = cedit_read_settings(cur_exp, tree); 130 oftree_dispose(tree); 131 free(buf); 132 if (ret) { 133 printf("Failed to read settings: %dE\n", ret); 134 return CMD_RET_FAILURE; 135 } 136 137 return 0; 138} 139 140static int do_cedit_write_env(struct cmd_tbl *cmdtp, int flag, int argc, 141 char *const argv[]) 142{ 143 bool verbose; 144 int ret; 145 146 if (check_cur_expo()) 147 return CMD_RET_FAILURE; 148 149 verbose = argc > 1 && !strcmp(argv[1], "-v"); 150 151 ret = cedit_write_settings_env(cur_exp, verbose); 152 if (ret) { 153 printf("Failed to write settings to environment: %dE\n", ret); 154 return CMD_RET_FAILURE; 155 } 156 157 return 0; 158} 159 160static int do_cedit_read_env(struct cmd_tbl *cmdtp, int flag, int argc, 161 char *const argv[]) 162{ 163 bool verbose; 164 int ret; 165 166 if (check_cur_expo()) 167 return CMD_RET_FAILURE; 168 169 verbose = argc > 1 && !strcmp(argv[1], "-v"); 170 171 ret = cedit_read_settings_env(cur_exp, verbose); 172 if (ret) { 173 printf("Failed to read settings from environment: %dE\n", ret); 174 return CMD_RET_FAILURE; 175 } 176 177 return 0; 178} 179 180static int do_cedit_write_cmos(struct cmd_tbl *cmdtp, int flag, int argc, 181 char *const argv[]) 182{ 183 struct udevice *dev; 184 bool verbose = false; 185 int ret; 186 187 if (check_cur_expo()) 188 return CMD_RET_FAILURE; 189 190 if (argc > 1 && !strcmp(argv[1], "-v")) { 191 verbose = true; 192 argc--; 193 argv++; 194 } 195 196 if (argc > 1) 197 ret = uclass_get_device_by_name(UCLASS_RTC, argv[1], &dev); 198 else 199 ret = uclass_first_device_err(UCLASS_RTC, &dev); 200 if (ret) { 201 printf("Failed to get RTC device: %dE\n", ret); 202 return CMD_RET_FAILURE; 203 } 204 205 if (cedit_write_settings_cmos(cur_exp, dev, verbose)) { 206 printf("Failed to write settings to CMOS\n"); 207 return CMD_RET_FAILURE; 208 } 209 210 return 0; 211} 212 213static int do_cedit_read_cmos(struct cmd_tbl *cmdtp, int flag, int argc, 214 char *const argv[]) 215{ 216 struct udevice *dev; 217 bool verbose = false; 218 int ret; 219 220 if (check_cur_expo()) 221 return CMD_RET_FAILURE; 222 223 if (argc > 1 && !strcmp(argv[1], "-v")) { 224 verbose = true; 225 argc--; 226 argv++; 227 } 228 229 if (argc > 1) 230 ret = uclass_get_device_by_name(UCLASS_RTC, argv[1], &dev); 231 else 232 ret = uclass_first_device_err(UCLASS_RTC, &dev); 233 if (ret) { 234 printf("Failed to get RTC device: %dE\n", ret); 235 return CMD_RET_FAILURE; 236 } 237 238 ret = cedit_read_settings_cmos(cur_exp, dev, verbose); 239 if (ret) { 240 printf("Failed to read settings from CMOS: %dE\n", ret); 241 return CMD_RET_FAILURE; 242 } 243 244 return 0; 245} 246 247static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc, 248 char *const argv[]) 249{ 250 ofnode node; 251 int ret; 252 253 if (check_cur_expo()) 254 return CMD_RET_FAILURE; 255 256 node = ofnode_path("/bootstd/cedit-theme"); 257 if (ofnode_valid(node)) { 258 ret = expo_apply_theme(cur_exp, node); 259 if (ret) 260 return CMD_RET_FAILURE; 261 } else { 262 log_warning("No theme found\n"); 263 } 264 ret = cedit_run(cur_exp); 265 if (ret) { 266 log_err("Failed (err=%dE)\n", ret); 267 return CMD_RET_FAILURE; 268 } 269 270 return 0; 271} 272 273U_BOOT_LONGHELP(cedit, 274 "load <interface> <dev[:part]> <filename> - load config editor\n" 275 "cedit read_fdt <i/f> <dev[:part]> <filename> - read settings\n" 276 "cedit write_fdt <i/f> <dev[:part]> <filename> - write settings\n" 277 "cedit read_env [-v] - read settings from env vars\n" 278 "cedit write_env [-v] - write settings to env vars\n" 279 "cedit read_cmos [-v] [dev] - read settings from CMOS RAM\n" 280 "cedit write_cmos [-v] [dev] - write settings to CMOS RAM\n" 281 "cedit run - run config editor"); 282 283U_BOOT_CMD_WITH_SUBCMDS(cedit, "Configuration editor", cedit_help_text, 284 U_BOOT_SUBCMD_MKENT(load, 5, 1, do_cedit_load), 285 U_BOOT_SUBCMD_MKENT(read_fdt, 5, 1, do_cedit_read_fdt), 286 U_BOOT_SUBCMD_MKENT(write_fdt, 5, 1, do_cedit_write_fdt), 287 U_BOOT_SUBCMD_MKENT(read_env, 2, 1, do_cedit_read_env), 288 U_BOOT_SUBCMD_MKENT(write_env, 2, 1, do_cedit_write_env), 289 U_BOOT_SUBCMD_MKENT(read_cmos, 2, 1, do_cedit_read_cmos), 290 U_BOOT_SUBCMD_MKENT(write_cmos, 2, 1, do_cedit_write_cmos), 291 U_BOOT_SUBCMD_MKENT(run, 1, 1, do_cedit_run), 292); 293