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