1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2024 SaluteDevices, Inc.
4  *
5  * Author: Alexey Romanov <avromanov@salutedevices.com>
6  */
7 
8 #include <memalign.h>
9 #include <part.h>
10 #include <ubi_uboot.h>
11 
get_ubi_device(void)12 static inline struct ubi_device *get_ubi_device(void)
13 {
14 	return ubi_devices[0];
15 }
16 
ubi_get_volume_by_index(int vol_id)17 static struct ubi_volume *ubi_get_volume_by_index(int vol_id)
18 {
19 	struct ubi_device *ubi = get_ubi_device();
20 	int i;
21 
22 	for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
23 		struct ubi_volume *volume = ubi->volumes[i];
24 
25 		if (!volume)
26 			continue;
27 
28 		if (volume->vol_id >= UBI_INTERNAL_VOL_START)
29 			continue;
30 
31 		if (volume->vol_id == vol_id)
32 			return volume;
33 	}
34 
35 	return NULL;
36 }
37 
part_get_info_ubi(struct blk_desc * dev_desc,int part_idx,struct disk_partition * info)38 static int __maybe_unused part_get_info_ubi(struct blk_desc *dev_desc, int part_idx,
39 					    struct disk_partition *info)
40 {
41 	struct ubi_volume *vol;
42 
43 	/*
44 	 * We must use part_idx - 1 instead of part_idx, because
45 	 * part_get_info_by_name() start indexing at 1, not 0.
46 	 * ubi volumes idexed starting at 0
47 	 */
48 	vol = ubi_get_volume_by_index(part_idx - 1);
49 	if (!vol)
50 		return -ENOENT;
51 
52 	snprintf(info->name, PART_NAME_LEN, vol->name);
53 
54 	info->start = 0;
55 	info->size = (unsigned long)vol->used_bytes / dev_desc->blksz;
56 	info->blksz = dev_desc->blksz;
57 
58 	/* Save UBI volume ID in blk device descriptor */
59 	dev_desc->hwpart = vol->vol_id;
60 
61 	return 0;
62 }
63 
part_print_ubi(struct blk_desc * dev_desc)64 static void __maybe_unused part_print_ubi(struct blk_desc *dev_desc)
65 {
66 	struct ubi_device *ubi = get_ubi_device();
67 	int i;
68 
69 	for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
70 		struct ubi_volume *volume = ubi->volumes[i];
71 
72 		if (!volume)
73 			continue;
74 
75 		if (volume->vol_id >= UBI_INTERNAL_VOL_START)
76 			continue;
77 
78 		printf("%d: %s\n", volume->vol_id, volume->name);
79 	}
80 }
81 
part_test_ubi(struct blk_desc * dev_desc)82 static int part_test_ubi(struct blk_desc *dev_desc)
83 {
84 	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
85 
86 	if (blk_dread(dev_desc, 0, 1, (ulong *)buffer) != 1)
87 		return -1;
88 
89 	return 0;
90 }
91 
92 U_BOOT_PART_TYPE(ubi) = {
93 	.name	= "ubi",
94 	.part_type	= PART_TYPE_UBI,
95 	.max_entries	= UBI_ENTRY_NUMBERS,
96 	.get_info	= part_get_info_ptr(part_get_info_ubi),
97 	.print	= part_print_ptr(part_print_ubi),
98 	.test	= part_test_ubi,
99 };
100