Changes in kernel/generic/src/sysinfo/sysinfo.c [137691a:b658c5d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/sysinfo/sysinfo.c
r137691a rb658c5d 37 37 #include <print.h> 38 38 #include <syscall/copy.h> 39 #include <errno.h> 40 41 #define SYSINFO_MAX_PATH 2048 39 42 40 43 bool fb_exported = false; 41 sysinfo_item_t *_root = NULL; 42 43 static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree) 44 { 45 if (subtree == NULL) 46 return NULL; 47 48 while (subtree != NULL) { 49 int i = 0; 50 char *a = (char *) name; 51 char *b = subtree->name; 52 53 while ((a[i] == b[i]) && (b[i])) 44 45 static sysinfo_item_t *global_root = NULL; 46 static slab_cache_t *sysinfo_item_slab; 47 48 static int sysinfo_item_constructor(void *obj, int kmflag) 49 { 50 sysinfo_item_t *item = (sysinfo_item_t *) obj; 51 52 item->name = NULL; 53 item->val_type = SYSINFO_VAL_UNDEFINED; 54 item->subtree_type = SYSINFO_SUBTREE_NONE; 55 item->subtree.table = NULL; 56 item->next = NULL; 57 58 return 0; 59 } 60 61 static int sysinfo_item_destructor(void *obj) 62 { 63 sysinfo_item_t *item = (sysinfo_item_t *) obj; 64 65 if (item->name != NULL) 66 free(item->name); 67 68 return 0; 69 } 70 71 void sysinfo_init(void) 72 { 73 sysinfo_item_slab = slab_cache_create("sysinfo_item_slab", 74 sizeof(sysinfo_item_t), 0, sysinfo_item_constructor, 75 sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED); 76 } 77 78 static sysinfo_item_t *sysinfo_find_item(const char *name, 79 sysinfo_item_t *subtree) 80 { 81 sysinfo_item_t *cur = subtree; 82 83 while (cur != NULL) { 84 size_t i = 0; 85 86 /* Compare name with path */ 87 while ((cur->name[i] != 0) && (name[i] == cur->name[i])) 54 88 i++; 55 89 56 if ((!a[i]) && (!b[i])) /* Last name in path matches */ 57 return subtree; 58 59 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */ 60 if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE) 61 return sysinfo_find_item(a + i + 1, subtree->subinfo.table); 90 /* Check for perfect name and path match */ 91 if ((name[i] == 0) && (cur->name[i] == 0)) 92 return cur; 93 94 /* Partial match up to the delimiter */ 95 if ((name[i] == '.') && (cur->name[i] == 0)) { 96 /* Look into the subtree */ 97 switch (cur->subtree_type) { 98 case SYSINFO_SUBTREE_TABLE: 99 /* Recursively find in subtree */ 100 return sysinfo_find_item(name + i + 1, cur->subtree.table); 101 case SYSINFO_SUBTREE_FUNCTION: 102 /* Get generated item */ 103 return cur->subtree.find_item(name + i + 1); 104 default: 105 /* Not found */ 106 return NULL; 107 } 108 } 109 110 cur = cur->next; 111 } 112 113 return NULL; 114 } 115 116 static sysinfo_item_t *sysinfo_create_path(const char *name, 117 sysinfo_item_t **psubtree) 118 { 119 ASSERT(psubtree != NULL); 120 121 if (*psubtree == NULL) { 122 /* No parent */ 123 124 size_t i = 0; 125 126 /* Find the first delimiter in name */ 127 while ((name[i] != 0) && (name[i] != '.')) 128 i++; 129 130 *psubtree = 131 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0); 132 ASSERT(*psubtree); 133 134 /* Fill in item name up to the delimiter */ 135 (*psubtree)->name = str_ndup(name, i); 136 ASSERT((*psubtree)->name); 137 138 /* Create subtree items */ 139 if (name[i] == '.') { 140 (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE; 141 return sysinfo_create_path(name + i + 1, 142 &((*psubtree)->subtree.table)); 143 } 144 145 /* No subtree needs to be created */ 146 return *psubtree; 147 } 148 149 sysinfo_item_t *cur = *psubtree; 150 151 while (cur != NULL) { 152 size_t i = 0; 153 154 /* Compare name with path */ 155 while ((cur->name[i] != 0) && (name[i] == cur->name[i])) 156 i++; 157 158 /* Check for perfect name and path match 159 * -> item is already present. 160 */ 161 if ((name[i] == 0) && (cur->name[i] == 0)) 162 return cur; 163 164 /* Partial match up to the delimiter */ 165 if ((name[i] == '.') && (cur->name[i] == 0)) { 166 switch (cur->subtree_type) { 167 case SYSINFO_SUBTREE_NONE: 168 /* No subtree yet, create one */ 169 cur->subtree_type = SYSINFO_SUBTREE_TABLE; 170 return sysinfo_create_path(name + i + 1, 171 &(cur->subtree.table)); 172 case SYSINFO_SUBTREE_TABLE: 173 /* Subtree already created, add new sibling */ 174 return sysinfo_create_path(name + i + 1, 175 &(cur->subtree.table)); 176 default: 177 /* Subtree items handled by a function, this 178 * cannot be overriden. 179 */ 180 return NULL; 181 } 182 } 183 184 /* No match and no more siblings to check 185 * -> create a new sibling item. 186 */ 187 if (cur->next == NULL) { 188 /* Find the first delimiter in name */ 189 i = 0; 190 while ((name[i] != 0) && (name[i] != '.')) 191 i++; 62 192 63 //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ 64 // return NULL; 193 sysinfo_item_t *item = 194 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0); 195 ASSERT(item); 65 196 66 return NULL; /* No subinfo */ 67 } 68 /* No matches try next */ 69 subtree = subtree->next; 70 } 71 return NULL; 72 } 73 74 static sysinfo_item_t *sysinfo_create_path(const char *name, sysinfo_item_t **psubtree) 75 { 76 sysinfo_item_t *subtree; 77 subtree = *psubtree; 78 79 if (subtree == NULL) { 80 sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0); 81 int i = 0, j; 197 cur->next = item; 82 198 83 ASSERT(item); 84 *psubtree = item; 85 item->next = NULL; 86 item->val_type = SYSINFO_VAL_UNDEFINED; 87 item->subinfo.table = NULL; 88 89 while (name[i] && (name[i] != '.')) 90 i++; 199 /* Fill in item name up to the delimiter */ 200 item->name = str_ndup(name, i); 201 ASSERT(item->name); 91 202 92 item->name = malloc(i, 0); 93 ASSERT(item->name); 94 95 for (j = 0; j < i; j++) 96 item->name[j] = name[j]; 97 item->name[j] = 0; 98 99 if (name[i]) { /* =='.' */ 100 item->subinfo_type = SYSINFO_SUBINFO_TABLE; 101 return sysinfo_create_path(name + i + 1, &(item->subinfo.table)); 102 } 103 item->subinfo_type = SYSINFO_SUBINFO_NONE; 104 return item; 105 } 106 107 while (subtree != NULL) { 108 int i = 0, j; 109 char *a = (char *) name; 110 char *b = subtree->name; 111 112 while ((a[i] == b[i]) && (b[i])) 113 i++; 114 115 if ((!a[i]) && (!b[i])) /* Last name in path matches */ 116 return subtree; 117 118 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */ 119 if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE) 120 return sysinfo_create_path(a + i + 1, &(subtree->subinfo.table)); 121 122 if (subtree->subinfo_type == SYSINFO_SUBINFO_NONE) { 123 subtree->subinfo_type = SYSINFO_SUBINFO_TABLE; 124 return sysinfo_create_path(a + i + 1,&(subtree->subinfo.table)); 203 /* Create subtree items */ 204 if (name[i] == '.') { 205 item->subtree_type = SYSINFO_SUBTREE_TABLE; 206 return sysinfo_create_path(name + i + 1, 207 &(item->subtree.table)); 125 208 } 126 209 127 //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ 128 // return NULL; 129 130 return NULL; 131 } 132 /* No matches try next or create new*/ 133 if (subtree->next == NULL) { 134 sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0); 135 136 ASSERT(item); 137 subtree->next = item; 138 item->next = NULL; 139 item->val_type = SYSINFO_VAL_UNDEFINED; 140 item->subinfo.table = NULL; 141 142 i = 0; 143 while (name[i] && (name[i] != '.')) 144 i++; 145 146 item->name = malloc(i, 0); 147 ASSERT(item->name); 148 149 for (j = 0; j < i; j++) 150 item->name[j] = name[j]; 151 152 item->name[j] = 0; 153 154 if(name[i]) { /* =='.' */ 155 item->subinfo_type = SYSINFO_SUBINFO_TABLE; 156 return sysinfo_create_path(name + i + 1, &(item->subinfo.table)); 157 } 158 item->subinfo_type = SYSINFO_SUBINFO_NONE; 210 /* No subtree needs to be created */ 159 211 return item; 160 } else 161 subtree = subtree->next; 162 } 163 164 panic("Not reached."); 212 } 213 214 /* Get next sibling */ 215 cur = cur->next; 216 } 217 218 /* Unreachable */ 219 ASSERT(false); 165 220 return NULL; 166 221 } 167 222 168 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val) 169 { 170 if (root == NULL) 171 root = &_root; 172 173 /* If already created create only returns pointer 174 If not, create it */ 223 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, 224 unative_t val) 225 { 226 if (root == NULL) 227 root = &global_root; 228 175 229 sysinfo_item_t *item = sysinfo_create_path(name, root); 176 177 if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ 178 item->val.val = val; 230 if (item != NULL) { 179 231 item->val_type = SYSINFO_VAL_VAL; 180 }181 }182 183 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn) 184 { 185 if (root == NULL)186 root = &_root; 187 188 /* If already created create only returns pointer189 If not, create it */232 item->val.val = val; 233 } 234 } 235 236 void sysinfo_set_item_data(const char *name, sysinfo_item_t **root, 237 void *data, size_t size) 238 { 239 if (root == NULL) 240 root = &global_root; 241 190 242 sysinfo_item_t *item = sysinfo_create_path(name, root); 191 192 if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ 193 item->val.fn = fn; 194 item->val_type = SYSINFO_VAL_FUNCTION; 195 } 196 } 197 243 if (item != NULL) { 244 item->val_type = SYSINFO_VAL_DATA; 245 item->val.data.data = data; 246 item->val.data.size = size; 247 } 248 } 249 250 void sysinfo_set_item_val_fn(const char *name, sysinfo_item_t **root, 251 sysinfo_fn_val_t fn) 252 { 253 if (root == NULL) 254 root = &global_root; 255 256 sysinfo_item_t *item = sysinfo_create_path(name, root); 257 if (item != NULL) { 258 item->val_type = SYSINFO_VAL_FUNCTION_VAL; 259 item->val.fn_val = fn; 260 } 261 } 262 263 void sysinfo_set_item_data_fn(const char *name, sysinfo_item_t **root, 264 sysinfo_fn_data_t fn) 265 { 266 if (root == NULL) 267 root = &global_root; 268 269 sysinfo_item_t *item = sysinfo_create_path(name, root); 270 if (item != NULL) { 271 item->val_type = SYSINFO_VAL_FUNCTION_DATA; 272 item->val.fn_data = fn; 273 } 274 } 198 275 199 276 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root) 200 277 { 201 278 if (root == NULL) 202 root = &_root; 203 204 /* If already created create only returns pointer 205 If not, create it */ 279 root = &global_root; 280 206 281 sysinfo_item_t *item = sysinfo_create_path(name, root); 207 208 282 if (item != NULL) 209 283 item->val_type = SYSINFO_VAL_UNDEFINED; 210 284 } 211 285 212 213 void sysinfo_dump(sysinfo_item_t **proot, int depth) 214 { 215 sysinfo_item_t *root; 286 static void sysinfo_indent(unsigned int depth) 287 { 288 unsigned int i; 289 for (i = 0; i < depth; i++) 290 printf(" "); 291 } 292 293 void sysinfo_dump(sysinfo_item_t **proot, unsigned int depth) 294 { 216 295 if (proot == NULL) 217 proot = &_root; 218 219 root = *proot; 220 221 while (root != NULL) { 222 int i; 223 unative_t val = 0; 224 const char *vtype = NULL; 225 226 227 for (i = 0; i < depth; i++) 228 printf(" "); 229 230 switch (root->val_type) { 296 proot = &global_root; 297 298 sysinfo_item_t *cur = *proot; 299 300 while (cur != NULL) { 301 sysinfo_indent(depth); 302 303 unative_t val; 304 size_t size; 305 306 switch (cur->val_type) { 231 307 case SYSINFO_VAL_UNDEFINED: 232 val = 0; 233 vtype = "UND"; 308 printf("+ %s\n", cur->name); 234 309 break; 235 310 case SYSINFO_VAL_VAL: 236 val = root->val.val; 237 vtype = "VAL"; 238 break; 239 case SYSINFO_VAL_FUNCTION: 240 val = ((sysinfo_val_fn_t) (root->val.fn)) (root); 241 vtype = "FUN"; 242 break; 243 } 244 245 printf("%s %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val, 246 val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ? 247 "NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ? 248 "TAB" : "FUN")); 249 250 if (root->subinfo_type == SYSINFO_SUBINFO_TABLE) 251 sysinfo_dump(&(root -> subinfo.table), depth + 1); 252 253 root = root->next; 254 } 255 } 256 257 sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root) 258 { 259 // TODO: Implement Subsystem subinfo (by function implemented subinfo) 260 261 sysinfo_rettype_t ret = {0, false}; 262 263 if (root == NULL) 264 root = &_root; 311 printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name, 312 cur->val.val, cur->val.val); 313 break; 314 case SYSINFO_VAL_DATA: 315 printf("+ %s (%" PRIs" bytes)\n", cur->name, 316 cur->val.data.size); 317 break; 318 case SYSINFO_VAL_FUNCTION_VAL: 319 val = cur->val.fn_val(cur); 320 printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n", 321 cur->name, val, val); 322 break; 323 case SYSINFO_VAL_FUNCTION_DATA: 324 cur->val.fn_data(cur, &size); 325 printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name, 326 size); 327 break; 328 default: 329 printf("+ %s [unknown]\n", cur->name); 330 } 331 332 switch (cur->subtree_type) { 333 case SYSINFO_SUBTREE_NONE: 334 break; 335 case SYSINFO_SUBTREE_TABLE: 336 sysinfo_dump(&(cur->subtree.table), depth + 1); 337 break; 338 case SYSINFO_SUBTREE_FUNCTION: 339 sysinfo_indent(depth + 1); 340 printf(" [generated subtree]\n"); 341 break; 342 default: 343 sysinfo_indent(depth + 1); 344 printf(" [unknown subtree]\n"); 345 } 346 347 cur = cur->next; 348 } 349 } 350 351 sysinfo_return_t sysinfo_get_item(const char *name, sysinfo_item_t **root) 352 { 353 if (root == NULL) 354 root = &global_root; 265 355 266 356 sysinfo_item_t *item = sysinfo_find_item(name, *root); 357 sysinfo_return_t ret; 267 358 268 359 if (item != NULL) { 269 if (item->val_type == SYSINFO_VAL_UNDEFINED)270 return ret;271 else272 ret.valid = true;273 274 if (item->val_type == SYSINFO_VAL_VAL)360 switch (item->val_type) { 361 case SYSINFO_VAL_UNDEFINED: 362 ret.tag = SYSINFO_VAL_UNDEFINED; 363 break; 364 case SYSINFO_VAL_VAL: 365 ret.tag = SYSINFO_VAL_VAL; 275 366 ret.val = item->val.val; 276 else 277 ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item); 278 } 367 break; 368 case SYSINFO_VAL_DATA: 369 ret.tag = SYSINFO_VAL_DATA; 370 ret.data = item->val.data; 371 break; 372 case SYSINFO_VAL_FUNCTION_VAL: 373 ret.tag = SYSINFO_VAL_VAL; 374 ret.val = item->val.fn_val(item); 375 break; 376 case SYSINFO_VAL_FUNCTION_DATA: 377 ret.tag = SYSINFO_VAL_DATA; 378 ret.data.data = item->val.fn_data(item, &ret.data.size); 379 break; 380 } 381 } else 382 ret.tag = SYSINFO_VAL_UNDEFINED; 383 279 384 return ret; 280 385 } 281 386 282 #define SYSINFO_MAX_LEN 1024 283 284 unative_t sys_sysinfo_valid(unative_t ptr, unative_t len) 285 { 286 char *str; 287 sysinfo_rettype_t ret = {0, 0}; 288 289 if (len > SYSINFO_MAX_LEN) 290 return ret.valid; 291 str = malloc(len + 1, 0); 292 293 ASSERT(str); 294 if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len]))) 295 ret = sysinfo_get_val(str, NULL); 296 297 free(str); 298 return ret.valid; 299 } 300 301 unative_t sys_sysinfo_value(unative_t ptr, unative_t len) 302 { 303 char *str; 304 sysinfo_rettype_t ret = {0, 0}; 305 306 if (len > SYSINFO_MAX_LEN) 307 return ret.val; 308 str = malloc(len + 1, 0); 309 310 ASSERT(str); 311 if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len]))) 312 ret = sysinfo_get_val(str, NULL); 313 314 free(str); 315 return ret.val; 387 static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size) 388 { 389 sysinfo_return_t ret; 390 ret.tag = SYSINFO_VAL_UNDEFINED; 391 392 if (size > SYSINFO_MAX_PATH) 393 return ret; 394 395 char *path = (char *) malloc(size + 1, 0); 396 ASSERT(path); 397 398 if ((copy_from_uspace(path, ptr, size + 1) == 0) 399 && (path[size] == 0)) { 400 ret = sysinfo_get_item(path, NULL); 401 free(path); 402 } 403 404 return ret; 405 } 406 407 unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size) 408 { 409 return (unative_t) sysinfo_get_item_uspace(path_ptr, path_size).tag; 410 } 411 412 unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size, 413 void *value_ptr) 414 { 415 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 416 417 if (ret.tag != SYSINFO_VAL_VAL) 418 return (unative_t) EINVAL; 419 420 return (unative_t) copy_to_uspace(value_ptr, &ret.val, 421 sizeof(ret.val)); 422 } 423 424 unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size, 425 void *size_ptr) 426 { 427 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 428 429 if (ret.tag != SYSINFO_VAL_DATA) 430 return (unative_t) EINVAL; 431 432 return (unative_t) copy_to_uspace(size_ptr, &ret.data.size, 433 sizeof(ret.data.size)); 434 } 435 436 unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size, 437 void *buffer_ptr, size_t buffer_size) 438 { 439 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 440 441 if (ret.tag != SYSINFO_VAL_DATA) 442 return (unative_t) EINVAL; 443 444 if (ret.data.size != buffer_size) 445 return ENOMEM; 446 447 return (unative_t) copy_to_uspace(buffer_ptr, ret.data.data, 448 ret.data.size); 316 449 } 317 450
Note:
See TracChangeset
for help on using the changeset viewer.