1 /* 2 * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License version 2.1 6 * as published by the Free Software Foundation 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include "common.h" 15 16 /* fit for UBI_MAX_VOLUME_NAME and sysfs path lengths */ 17 #define BUFLEN 128 18 19 /* could use libubi-tiny instead, but already had the code directly reading 20 * from sysfs */ 21 const char *const ubi_dir_name = "/sys/class/ubi"; 22 23 struct ubi_volume { 24 struct volume v; 25 int ubi_num; 26 int ubi_volid; 27 }; 28 29 static struct driver ubi_driver; 30 31 static unsigned int 32 test_open(char *filename) 33 { 34 FILE *f; 35 36 f = fopen(filename, "r"); 37 if (!f) 38 return 0; 39 40 fclose(f); 41 return 1; 42 } 43 44 static int ubi_volume_init(struct volume *v) 45 { 46 struct ubi_volume *p = container_of(v, struct ubi_volume, v); 47 char voldir[BUFLEN], voldev[BUFLEN], volname[BUFLEN]; 48 unsigned int volsize; 49 50 snprintf(voldir, sizeof(voldir), "%s/ubi%u_%u", 51 ubi_dir_name, p->ubi_num, p->ubi_volid); 52 53 snprintf(voldev, sizeof(voldev), "/dev/ubi%u_%u", 54 p->ubi_num, p->ubi_volid); 55 56 if (!read_string_from_file(voldir, "name", volname, sizeof(volname))) 57 return -1; 58 59 if (read_uint_from_file(voldir, "data_bytes", &volsize)) 60 return -1; 61 62 v->name = volname; 63 v->type = UBIVOLUME; 64 v->size = volsize; 65 v->blk = strdup(voldev); 66 67 return 0; 68 } 69 70 static struct volume *ubi_volume_match(char *name, int ubi_num, int volid) 71 { 72 char voldir[BUFLEN], volblkdev[BUFLEN], volname[BUFLEN]; 73 struct ubi_volume *p; 74 75 snprintf(voldir, sizeof(voldir), "%s/ubi%u_%u", 76 ubi_dir_name, ubi_num, volid); 77 78 snprintf(volblkdev, sizeof(volblkdev), "/dev/ubiblock%u_%u", 79 ubi_num, volid); 80 81 /* skip if ubiblock device exists */ 82 if (test_open(volblkdev)) 83 return NULL; 84 85 /* todo: skip existing gluebi device for legacy support */ 86 87 if (!read_string_from_file(voldir, "name", volname, sizeof(volname))) { 88 ULOG_ERR("Couldn't read %s/name\n", voldir); 89 return NULL; 90 } 91 92 if (strcmp(name, volname)) 93 return NULL; 94 95 p = calloc(1, sizeof(struct ubi_volume)); 96 if (!p) 97 return NULL; 98 99 p->v.drv = &ubi_driver; 100 p->ubi_num = ubi_num; 101 p->ubi_volid = volid; 102 103 return &p->v; 104 } 105 106 static struct volume *ubi_part_match(char *name, unsigned int ubi_num) 107 { 108 DIR *ubi_dir; 109 struct dirent *ubi_dirent; 110 unsigned int volid; 111 char devdir[BUFLEN]; 112 struct volume *ret = NULL; 113 114 snprintf(devdir, sizeof(devdir), "%s/ubi%u", 115 ubi_dir_name, ubi_num); 116 117 ubi_dir = opendir(devdir); 118 if (!ubi_dir) 119 return ret; 120 121 while ((ubi_dirent = readdir(ubi_dir)) != NULL) { 122 if (strncmp(ubi_dirent->d_name, "ubi", 3)) 123 continue; 124 125 if (sscanf(ubi_dirent->d_name, "ubi%*u_%u", &volid) != 1) 126 continue; 127 128 ret = ubi_volume_match(name, ubi_num, volid); 129 if (ret) 130 break; 131 } 132 closedir(ubi_dir); 133 134 return ret; 135 } 136 137 static struct volume *ubi_volume_find(char *name) 138 { 139 struct volume *ret = NULL; 140 DIR *ubi_dir; 141 struct dirent *ubi_dirent; 142 unsigned int ubi_num; 143 144 if (find_filesystem("ubifs")) 145 return ret; 146 147 ubi_dir = opendir(ubi_dir_name); 148 /* check for os ubi support */ 149 if (!ubi_dir) 150 return ret; 151 152 /* probe ubi devices and volumes */ 153 while ((ubi_dirent = readdir(ubi_dir)) != NULL) { 154 if (ubi_dirent->d_name[0] == '.') 155 continue; 156 157 sscanf(ubi_dirent->d_name, "ubi%u", &ubi_num); 158 ret = ubi_part_match(name, ubi_num); 159 if (ret) 160 break; 161 } 162 closedir(ubi_dir); 163 return ret; 164 } 165 166 static int ubi_volume_identify(struct volume *v) 167 { 168 /* Todo: use libblkid-tiny on the ubi chardev */ 169 return FS_UBIFS; 170 } 171 172 static struct driver ubi_driver = { 173 .name = "ubi", 174 .priority = 20, 175 .find = ubi_volume_find, 176 .init = ubi_volume_init, 177 .identify = ubi_volume_identify, 178 }; 179 180 DRIVER(ubi_driver); 181
This page was automatically generated by LXR 0.3.1. • OpenWrt