uboot/cmd/zfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *
   4 * ZFS filesystem porting to Uboot by
   5 * Jorgen Lundman <lundman at lundman.net>
   6 *
   7 * zfsfs support
   8 * made from existing GRUB Sources by Sun, GNU and others.
   9 */
  10
  11#include <common.h>
  12#include <part.h>
  13#include <config.h>
  14#include <command.h>
  15#include <env.h>
  16#include <image.h>
  17#include <linux/ctype.h>
  18#include <asm/byteorder.h>
  19#include <zfs_common.h>
  20#include <linux/stat.h>
  21#include <malloc.h>
  22
  23#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
  24#include <usb.h>
  25#endif
  26
  27#if !CONFIG_IS_ENABLED(DOS_PARTITION) && !CONFIG_IS_ENABLED(EFI_PARTITION)
  28#error DOS or EFI partition support must be selected
  29#endif
  30
  31#define DOS_PART_MAGIC_OFFSET   0x1fe
  32#define DOS_FS_TYPE_OFFSET      0x36
  33#define DOS_FS32_TYPE_OFFSET    0x52
  34
  35static int do_zfs_load(struct cmd_tbl *cmdtp, int flag, int argc,
  36                       char *const argv[])
  37{
  38        char *filename = NULL;
  39        int dev;
  40        int part;
  41        ulong addr = 0;
  42        struct disk_partition info;
  43        struct blk_desc *dev_desc;
  44        unsigned long count;
  45        const char *addr_str;
  46        struct zfs_file zfile;
  47        struct device_s vdev;
  48
  49        if (argc < 3)
  50                return CMD_RET_USAGE;
  51
  52        count = 0;
  53        addr = hextoul(argv[3], NULL);
  54        filename = env_get("bootfile");
  55        switch (argc) {
  56        case 3:
  57                addr_str = env_get("loadaddr");
  58                if (addr_str != NULL)
  59                        addr = hextoul(addr_str, NULL);
  60                else
  61                        addr = CONFIG_SYS_LOAD_ADDR;
  62
  63                break;
  64        case 4:
  65                break;
  66        case 5:
  67                filename = argv[4];
  68                break;
  69        case 6:
  70                filename = argv[4];
  71                count = hextoul(argv[5], NULL);
  72                break;
  73
  74        default:
  75                return cmd_usage(cmdtp);
  76        }
  77
  78        if (!filename) {
  79                puts("** No boot file defined **\n");
  80                return 1;
  81        }
  82
  83        part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
  84        if (part < 0)
  85                return 1;
  86
  87        dev = dev_desc->devnum;
  88        printf("Loading file \"%s\" from %s device %d%c%c\n",
  89                filename, argv[1], dev,
  90                part ? ':' : ' ', part ? part + '0' : ' ');
  91
  92        zfs_set_blk_dev(dev_desc, &info);
  93        vdev.part_length = info.size;
  94
  95        memset(&zfile, 0, sizeof(zfile));
  96        zfile.device = &vdev;
  97        if (zfs_open(&zfile, filename)) {
  98                printf("** File not found %s **\n", filename);
  99                return 1;
 100        }
 101
 102        if ((count < zfile.size) && (count != 0))
 103                zfile.size = (uint64_t)count;
 104
 105        if (zfs_read(&zfile, (char *)addr, zfile.size) != zfile.size) {
 106                printf("** Unable to read \"%s\" from %s %d:%d **\n",
 107                           filename, argv[1], dev, part);
 108                zfs_close(&zfile);
 109                return 1;
 110        }
 111
 112        zfs_close(&zfile);
 113
 114        /* Loading ok, update default load address */
 115        image_load_addr = addr;
 116
 117        printf("%llu bytes read\n", zfile.size);
 118        env_set_hex("filesize", zfile.size);
 119
 120        return 0;
 121}
 122
 123
 124int zfs_print(const char *entry, const struct zfs_dirhook_info *data)
 125{
 126        printf("%s %s\n",
 127                   data->dir ? "<DIR> " : "              ",
 128                   entry);
 129        return 0; /* 0 continue, 1 stop */
 130}
 131
 132
 133static int do_zfs_ls(struct cmd_tbl *cmdtp, int flag, int argc,
 134                     char *const argv[])
 135{
 136        const char *filename = "/";
 137        int part;
 138        struct blk_desc *dev_desc;
 139        struct disk_partition info;
 140        struct device_s vdev;
 141
 142        if (argc < 2)
 143                return cmd_usage(cmdtp);
 144
 145        if (argc == 4)
 146                filename = argv[3];
 147
 148        part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
 149        if (part < 0)
 150                return 1;
 151
 152        zfs_set_blk_dev(dev_desc, &info);
 153        vdev.part_length = info.size;
 154
 155        zfs_ls(&vdev, filename,
 156                   zfs_print);
 157
 158        return 0;
 159}
 160
 161
 162U_BOOT_CMD(zfsls, 4, 1, do_zfs_ls,
 163                   "list files in a directory (default /)",
 164                   "<interface> <dev[:part]> [directory]\n"
 165                   "      - list files from 'dev' on 'interface' in a '/DATASET/@/$dir/'");
 166
 167U_BOOT_CMD(zfsload, 6, 0, do_zfs_load,
 168                   "load binary file from a ZFS filesystem",
 169                   "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
 170                   "      - load binary file '/DATASET/@/$dir/$file' from 'dev' on 'interface'\n"
 171                   "             to address 'addr' from ZFS filesystem");
 172