1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * BTRFS filesystem implementation for U-Boot 4 * 5 * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz 6 */ 7 8 #include "btrfs.h" 9 #include <malloc.h> 10 11 u64 btrfs_read_extent_inline(struct btrfs_path *path, 12 struct btrfs_file_extent_item *extent, u64 offset, 13 u64 size, char *out) 14 { 15 u32 clen, dlen, orig_size = size, res; 16 const char *cbuf; 17 char *dbuf; 18 const int data_off = offsetof(struct btrfs_file_extent_item, 19 disk_bytenr); 20 21 clen = btrfs_path_item_size(path) - data_off; 22 cbuf = (const char *) extent + data_off; 23 dlen = extent->ram_bytes; 24 25 if (offset > dlen) 26 return -1ULL; 27 28 if (size > dlen - offset) 29 size = dlen - offset; 30 31 if (extent->compression == BTRFS_COMPRESS_NONE) { 32 memcpy(out, cbuf + offset, size); 33 return size; 34 } 35 36 if (dlen > orig_size) { 37 dbuf = malloc(dlen); 38 if (!dbuf) 39 return -1ULL; 40 } else { 41 dbuf = out; 42 } 43 44 res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen); 45 if (res == -1 || res != dlen) 46 goto err; 47 48 if (dlen > orig_size) { 49 memcpy(out, dbuf + offset, size); 50 free(dbuf); 51 } else if (offset) { 52 memmove(out, dbuf + offset, size); 53 } 54 55 return size; 56 57 err: 58 if (dlen > orig_size) 59 free(dbuf); 60 return -1ULL; 61 } 62 63 u64 btrfs_read_extent_reg(struct btrfs_path *path, 64 struct btrfs_file_extent_item *extent, u64 offset, 65 u64 size, char *out) 66 { 67 u64 physical, clen, dlen, orig_size = size; 68 u32 res; 69 char *cbuf, *dbuf; 70 71 clen = extent->disk_num_bytes; 72 dlen = extent->num_bytes; 73 74 if (offset > dlen) 75 return -1ULL; 76 77 if (size > dlen - offset) 78 size = dlen - offset; 79 80 physical = btrfs_map_logical_to_physical(extent->disk_bytenr); 81 if (physical == -1ULL) 82 return -1ULL; 83 84 if (extent->compression == BTRFS_COMPRESS_NONE) { 85 physical += extent->offset + offset; 86 if (!btrfs_devread(physical, size, out)) 87 return -1ULL; 88 89 return size; 90 } 91 92 cbuf = malloc(dlen > size ? clen + dlen : clen); 93 if (!cbuf) 94 return -1ULL; 95 96 if (dlen > orig_size) 97 dbuf = cbuf + clen; 98 else 99 dbuf = out; 100 101 if (!btrfs_devread(physical, clen, cbuf)) 102 goto err; 103 104 res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen); 105 if (res == -1) 106 goto err; 107 108 if (dlen > orig_size) 109 memcpy(out, dbuf + offset, size); 110 else 111 memmove(out, dbuf + offset, size); 112 113 free(cbuf); 114 return res; 115 116 err: 117 free(cbuf); 118 return -1ULL; 119 } 120