// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2012, Google Inc. */ #include #include #include #include #include #include #include #include #include #include #include static int do_host_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); } static int do_host_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); } static int do_host_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { return do_size(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); } static int do_host_save(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); } static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { bool removable = false; struct udevice *dev; const char *label; char *file; unsigned long blksz = DEFAULT_BLKSZ; int ret; /* Skip 'bind' */ argc--; argv++; if (argc < 2) return CMD_RET_USAGE; if (!strcmp(argv[0], "-r")) { removable = true; argc--; argv++; } if (argc < 2 || argc > 3) return CMD_RET_USAGE; label = argv[0]; file = argv[1]; if (argc > 2) { blksz = dectoul(argv[2], NULL); if (blksz < DEFAULT_BLKSZ || !is_power_of_2(blksz)) { printf("blksz must be >= 512 and power of 2\n"); return CMD_RET_FAILURE; } } ret = host_create_attach_file(label, file, removable, blksz, &dev); if (ret) { printf("Cannot create device / bind file\n"); return CMD_RET_FAILURE; } return 0; } /** * parse_host_label() - Parse a device label or sequence number * * This shows an error if it returns NULL * * @label: String containing the label or sequence number * Returns: Associated device, or NULL if not found */ static struct udevice *parse_host_label(const char *label) { struct udevice *dev; dev = host_find_by_label(label); if (!dev) { int devnum; char *ep; devnum = hextoul(label, &ep); if (*ep || uclass_find_device_by_seq(UCLASS_HOST, devnum, &dev)) { printf("No such device '%s'\n", label); return NULL; } } return dev; } static int do_host_unbind(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct udevice *dev; const char *label; int ret; if (argc < 2) return CMD_RET_USAGE; label = argv[1]; dev = parse_host_label(label); if (!dev) return CMD_RET_FAILURE; ret = host_detach_file(dev); if (ret) { printf("Cannot detach file (err=%d)\n", ret); return CMD_RET_FAILURE; } ret = device_unbind(dev); if (ret) { printf("Cannot attach file\n"); ret = device_unbind(dev); if (ret) printf("Cannot unbind device '%s'\n", dev->name); return CMD_RET_FAILURE; } return 0; } static void show_host_dev(struct udevice *dev) { struct host_sb_plat *plat = dev_get_plat(dev); struct blk_desc *desc; struct udevice *blk; int ret; printf("%3d ", dev_seq(dev)); if (!plat->fd) { printf("Not bound to a backing file\n"); return; } ret = blk_get_from_parent(dev, &blk); if (ret) /* cannot happen */ return; desc = dev_get_uclass_plat(blk); printf("%12lu %6lu %-15s %s\n", (unsigned long)desc->lba, desc->blksz, plat->label, plat->filename); } static int do_host_info(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct udevice *dev; if (argc < 1) return CMD_RET_USAGE; dev = NULL; if (argc >= 2) { dev = parse_host_label(argv[1]); if (!dev) return CMD_RET_FAILURE; } printf("%3s %12s %6s %-15s %s\n", "dev", "blocks", "blksz", "label", "path"); if (dev) { show_host_dev(dev); } else { struct uclass *uc; uclass_id_foreach_dev(UCLASS_HOST, dev, uc) show_host_dev(dev); } return 0; } static int do_host_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct udevice *dev; const char *label; if (argc < 1 || argc > 3) return CMD_RET_USAGE; if (argc == 1) { struct host_sb_plat *plat; dev = host_get_cur_dev(); if (!dev) { printf("No current host device\n"); return CMD_RET_FAILURE; } plat = dev_get_plat(dev); printf("Current host device: %d: %s\n", dev_seq(dev), plat->label); return 0; } label = argv[1]; dev = parse_host_label(argv[1]); if (!dev) return CMD_RET_FAILURE; host_set_cur_dev(dev); return 0; } static struct cmd_tbl cmd_host_sub[] = { U_BOOT_CMD_MKENT(load, 7, 0, do_host_load, "", ""), U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""), U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""), U_BOOT_CMD_MKENT(size, 3, 0, do_host_size, "", ""), U_BOOT_CMD_MKENT(bind, 4, 0, do_host_bind, "", ""), U_BOOT_CMD_MKENT(unbind, 4, 0, do_host_unbind, "", ""), U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""), U_BOOT_CMD_MKENT(dev, 0, 1, do_host_dev, "", ""), }; static int do_host(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct cmd_tbl *c; /* Skip past 'host' */ argc--; argv++; c = find_cmd_tbl(argv[0], cmd_host_sub, ARRAY_SIZE(cmd_host_sub)); if (c) return c->cmd(cmdtp, flag, argc, argv); else return CMD_RET_USAGE; } U_BOOT_CMD( host, 8, 1, do_host, "Miscellaneous host commands", "load hostfs - [ ] - " "load a file from host\n" "host ls hostfs - - list files on host\n" "host save hostfs - [] - " "save a file to host\n" "host size hostfs - - determine size of file on host\n" "host bind [-r]