File indexing completed on 2025-05-11 08:24:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <fcntl.h>
0029 #include <stdio.h>
0030 #include <sys/stat.h>
0031 #include <sys/types.h>
0032
0033 #include <libfdt.h>
0034 #include <zlib.h>
0035
0036 #include <rtems/malloc.h>
0037 #include <rtems/rtems-fdt.h>
0038 #include <rtems/thread.h>
0039
0040
0041
0042
0043
0044 typedef struct
0045 {
0046 const char* name;
0047 int offset;
0048 } rtems_fdt_index_entry;
0049
0050 typedef struct
0051 {
0052 int num_entries;
0053 rtems_fdt_index_entry* entries;
0054
0055 char* names;
0056 } rtems_fdt_index;
0057
0058
0059
0060
0061
0062 struct rtems_fdt_blob
0063 {
0064 rtems_chain_node node;
0065 const void* blob;
0066 const char* name;
0067 int refs;
0068 rtems_fdt_index index;
0069 };
0070
0071
0072
0073
0074
0075
0076 typedef struct
0077 {
0078 rtems_mutex lock;
0079 rtems_chain_control blobs;
0080 const char* paths;
0081 } rtems_fdt_data;
0082
0083 static void
0084 rtems_fdt_unlock (rtems_fdt_data *fdt)
0085 {
0086 rtems_mutex_unlock (&fdt->lock);
0087 }
0088
0089 static rtems_fdt_data*
0090 rtems_fdt_lock (void)
0091 {
0092 static rtems_fdt_data fdt_instance = {
0093 .lock = RTEMS_MUTEX_INITIALIZER ("FDT"),
0094 .blobs = RTEMS_CHAIN_INITIALIZER_EMPTY (fdt_instance.blobs)
0095 };
0096 rtems_fdt_data *fdt = &fdt_instance;
0097
0098 rtems_mutex_lock (&fdt->lock);
0099 return fdt;
0100 }
0101
0102
0103
0104
0105 static int rtems_fdt_node_path_compare(const char* n1,
0106 const char* n2,
0107 size_t namelen)
0108 {
0109 if (namelen == 0)
0110 {
0111 return strcmp(n1, n2);
0112 }
0113 return strncmp(n1, n2, namelen);
0114 }
0115
0116
0117
0118
0119 static int rtems_fdt_index_compare(const void* a, const void* b)
0120 {
0121 const rtems_fdt_index_entry* e1 = (const rtems_fdt_index_entry*) a;
0122 const rtems_fdt_index_entry* e2 = (const rtems_fdt_index_entry*) b;
0123 return rtems_fdt_node_path_compare(e1->name, e2->name, 0);
0124 }
0125
0126
0127
0128
0129 static int
0130 rtems_fdt_init_index (rtems_fdt_handle* fdt, rtems_fdt_blob* blob)
0131 {
0132 rtems_fdt_index_entry* entries = NULL;
0133 int num_entries = 0;
0134 int entry = 0;
0135 size_t total_name_memory = 0;
0136 char node_path[256];
0137 int depth_path[32];
0138 int start_offset = 0;
0139 int start_depth = 0;
0140 int offset = 0;
0141 int depth = 0;
0142 char* names = NULL;
0143 char* names_pos = NULL;
0144
0145
0146
0147
0148 memset(&node_path, 0, sizeof(node_path));
0149 strcpy(node_path, "/");
0150 depth_path[0] = strlen(node_path);
0151
0152 start_offset = fdt_path_offset(fdt->blob->blob, node_path);
0153 if (start_offset < 0)
0154 {
0155 return start_offset;
0156 }
0157
0158 start_offset = fdt_next_node(fdt->blob->blob, start_offset, &start_depth);
0159 if (start_offset < 0)
0160 {
0161 return start_offset;
0162 }
0163
0164 offset = start_offset;
0165 depth = start_depth;
0166
0167 while (depth > 0)
0168 {
0169
0170
0171
0172 int namelen = 0;
0173 const char* name = fdt_get_name(blob->blob, offset, &namelen);
0174 strncpy(&node_path[depth_path[depth-1]],
0175 name,
0176 sizeof(node_path) - depth_path[depth-1] - 1);
0177
0178 total_name_memory += strlen(node_path) + 1;
0179 num_entries++;
0180
0181 if (depth_path[depth-1] + namelen + 2 <= (int)sizeof(node_path))
0182 {
0183 strcpy(&node_path[depth_path[depth-1] + namelen], "/");
0184 }
0185
0186 depth_path[depth] = depth_path[depth-1] + namelen + 1;
0187
0188
0189
0190
0191 offset = fdt_next_node(fdt->blob->blob, offset, &depth);
0192 if (offset < 0)
0193 {
0194 return offset;
0195 }
0196 }
0197
0198
0199
0200
0201 entries = rtems_calloc(num_entries, sizeof(rtems_fdt_index_entry));
0202 if (!entries)
0203 {
0204 return -RTEMS_FDT_ERR_NO_MEMORY;
0205 }
0206
0207 names = rtems_calloc(1, total_name_memory);
0208 if (!names)
0209 {
0210 free(entries);
0211 return -RTEMS_FDT_ERR_NO_MEMORY;
0212 }
0213
0214
0215
0216
0217 offset = start_offset;
0218 depth = start_depth;
0219 entry = 0;
0220 names_pos = names;
0221
0222 while (depth > 0)
0223 {
0224
0225
0226
0227 int namelen = 0;
0228 const char* name = fdt_get_name(blob->blob, offset, &namelen);
0229 strncpy(&node_path[depth_path[depth-1]],
0230 name,
0231 sizeof(node_path) - depth_path[depth-1] - 1);
0232 strcpy(names_pos, node_path);
0233
0234 entries[entry].name = names_pos;
0235 entries[entry].offset = offset;
0236
0237 names_pos += strlen(node_path) + 1;
0238 entry++;
0239
0240 if (depth_path[depth-1] + namelen + 2 <= (int)sizeof(node_path))
0241 {
0242 strcpy(&node_path[depth_path[depth-1] + namelen], "/");
0243 }
0244
0245 depth_path[depth] = depth_path[depth-1] + namelen + 1;
0246
0247
0248
0249
0250 offset = fdt_next_node(fdt->blob->blob, offset, &depth);
0251 if (offset < 0)
0252 {
0253 free(entries);
0254 free(names);
0255 return offset;
0256 }
0257 }
0258
0259 if (num_entries != 0)
0260 {
0261 qsort(entries,
0262 num_entries,
0263 sizeof(rtems_fdt_index_entry),
0264 rtems_fdt_index_compare);
0265 }
0266
0267 fdt->blob->index.entries = entries;
0268 fdt->blob->index.num_entries = num_entries;
0269 fdt->blob->index.names = names;
0270
0271 return 0;
0272 }
0273
0274
0275
0276
0277 static void
0278 rtems_fdt_release_index (rtems_fdt_index* index)
0279 {
0280 if (index->entries)
0281 {
0282 free(index->entries);
0283 free(index->names);
0284
0285 index->num_entries = 0;
0286 index->entries = NULL;
0287 index->names = NULL;
0288 }
0289 }
0290
0291
0292
0293
0294
0295 static int
0296 rtems_fdt_index_find_by_name(rtems_fdt_index* index,
0297 const char* name)
0298 {
0299 int min = 0;
0300 int max = index->num_entries;
0301
0302
0303
0304 size_t namelen = strlen(name);
0305 if (namelen > 0 && name[namelen-1] == '/')
0306 {
0307 namelen--;
0308 }
0309
0310
0311 while (min < max)
0312 {
0313 int middle = (min + max) / 2;
0314 int cmp = rtems_fdt_node_path_compare(name,
0315 index->entries[middle].name,
0316 namelen);
0317 if (cmp == 0)
0318 {
0319
0320
0321 if (index->entries[middle].name[namelen] == '\0')
0322 {
0323
0324 return index->entries[middle].offset;
0325 }
0326 else
0327 {
0328
0329 cmp = -1;
0330 }
0331 }
0332 if (cmp < 0)
0333 {
0334
0335 max = middle;
0336 }
0337 else
0338 {
0339
0340 min = middle + 1;
0341 }
0342 }
0343
0344
0345 return -FDT_ERR_NOTFOUND;
0346 }
0347
0348
0349
0350
0351 static const char *
0352 rtems_fdt_index_find_name_by_offset(rtems_fdt_index* index,
0353 int offset)
0354 {
0355 int min = 0;
0356 int max = index->num_entries;
0357
0358
0359
0360
0361 while (min < max)
0362 {
0363 int middle = (min + max) / 2;
0364 if (offset < index->entries[middle].offset)
0365 {
0366
0367 max = middle;
0368 }
0369 else if (offset > index->entries[middle].offset)
0370 {
0371
0372 min = middle + 1;
0373 }
0374 else
0375 {
0376
0377 return index->entries[middle].name;
0378 }
0379 }
0380
0381
0382 return NULL;
0383 }
0384
0385 void
0386 rtems_fdt_init_handle (rtems_fdt_handle* handle)
0387 {
0388 if (handle)
0389 handle->blob = NULL;
0390 }
0391
0392 void
0393 rtems_fdt_dup_handle (rtems_fdt_handle* from, rtems_fdt_handle* to)
0394 {
0395 if (from && to)
0396 {
0397 rtems_fdt_data* fdt;
0398
0399 fdt = rtems_fdt_lock ();
0400 to->blob = from->blob;
0401 ++to->blob->refs;
0402 rtems_fdt_unlock (fdt);
0403 }
0404 }
0405
0406 void
0407 rtems_fdt_release_handle (rtems_fdt_handle* handle)
0408 {
0409 if (handle && handle->blob)
0410 {
0411 rtems_fdt_data* fdt;
0412 rtems_chain_node* node;
0413
0414 fdt = rtems_fdt_lock ();
0415
0416 node = rtems_chain_first (&fdt->blobs);
0417
0418 while (!rtems_chain_is_tail (&fdt->blobs, node))
0419 {
0420 rtems_fdt_blob* blob = (rtems_fdt_blob*) node;
0421 if (handle->blob == blob)
0422 {
0423 if (blob->refs)
0424 --blob->refs;
0425 break;
0426 }
0427 node = rtems_chain_next (node);
0428 }
0429
0430 rtems_fdt_unlock (fdt);
0431
0432 handle->blob = NULL;
0433 }
0434 }
0435
0436 bool
0437 rtems_fdt_valid_handle (const rtems_fdt_handle* handle)
0438 {
0439 if (handle && handle->blob)
0440 {
0441 rtems_fdt_data* fdt;
0442 rtems_chain_node* node;
0443
0444 fdt = rtems_fdt_lock ();
0445
0446 node = rtems_chain_first (&fdt->blobs);
0447
0448 while (!rtems_chain_is_tail (&fdt->blobs, node))
0449 {
0450 rtems_fdt_blob* blob = (rtems_fdt_blob*) node;
0451 if (handle->blob == blob)
0452 {
0453 rtems_fdt_unlock (fdt);
0454 return true;
0455 }
0456 node = rtems_chain_next (node);
0457 }
0458
0459 rtems_fdt_unlock (fdt);
0460 }
0461
0462 return false;
0463 }
0464
0465 int
0466 rtems_fdt_find_path_offset (rtems_fdt_handle* handle, const char* path)
0467 {
0468 rtems_fdt_data* fdt;
0469 rtems_chain_node* node;
0470
0471 rtems_fdt_release_handle (handle);
0472
0473 fdt = rtems_fdt_lock ();
0474
0475 node = rtems_chain_first (&fdt->blobs);
0476
0477 while (!rtems_chain_is_tail (&fdt->blobs, node))
0478 {
0479 rtems_fdt_handle temp_handle;
0480 int offset;
0481
0482 temp_handle.blob = (rtems_fdt_blob*) node;
0483
0484 offset = rtems_fdt_path_offset (&temp_handle, path);
0485
0486 if (offset >= 0)
0487 {
0488 ++temp_handle.blob->refs;
0489 handle->blob = temp_handle.blob;
0490 rtems_fdt_unlock (fdt);
0491 return offset;
0492 }
0493
0494 node = rtems_chain_next (node);
0495 }
0496
0497 rtems_fdt_unlock (fdt);
0498
0499 return -FDT_ERR_NOTFOUND;
0500 }
0501
0502 int
0503 rtems_fdt_load (const char* filename, rtems_fdt_handle* handle)
0504 {
0505 rtems_fdt_data* fdt;
0506 rtems_fdt_blob* blob;
0507 size_t bsize;
0508 int bf;
0509 ssize_t r;
0510 size_t name_len;
0511 int fe;
0512 struct stat sb;
0513 uint8_t gzip_id[2];
0514 uint8_t* cdata;
0515 size_t size;
0516
0517 rtems_fdt_release_handle (handle);
0518
0519 if (stat (filename, &sb) < 0)
0520 {
0521 return -RTEMS_FDT_ERR_NOT_FOUND;
0522 }
0523
0524 bf = open(filename, O_RDONLY);
0525 if (bf < 0)
0526 {
0527 return -RTEMS_FDT_ERR_READ_FAIL;
0528 }
0529
0530 r = read(bf, &gzip_id, sizeof(gzip_id));
0531 if (r < 0)
0532 {
0533 close(bf);
0534 return -RTEMS_FDT_ERR_READ_FAIL;
0535 }
0536
0537 if ((gzip_id[0] == 0x1f) && (gzip_id[1] == 0x8b))
0538 {
0539 size_t offset;
0540
0541 cdata = rtems_malloc(sb.st_size);
0542 if (!cdata)
0543 {
0544 close (bf);
0545 return -RTEMS_FDT_ERR_NO_MEMORY;
0546 }
0547
0548 if (lseek(bf, 0, SEEK_SET) < 0)
0549 {
0550 free(cdata);
0551 close(bf);
0552 return -RTEMS_FDT_ERR_READ_FAIL;
0553 }
0554
0555 size = sb.st_size;
0556 offset = 0;
0557 while (size)
0558 {
0559 r = read(bf, cdata + offset, size);
0560 if (r < 0)
0561 {
0562 free(cdata);
0563 close(bf);
0564 return -RTEMS_FDT_ERR_READ_FAIL;
0565 }
0566 size -= r;
0567 offset += r;
0568 }
0569
0570 offset = sb.st_size - 4;
0571 bsize = ((cdata[offset + 3] << 24) | (cdata[offset + 2] << 16) |
0572 (cdata[offset + 1] << 8) | cdata[offset + 0]);
0573 }
0574 else
0575 {
0576 cdata = NULL;
0577 bsize = sb.st_size;
0578 }
0579
0580 name_len = strlen (filename) + 1;
0581
0582 blob = rtems_malloc(sizeof (rtems_fdt_blob) + name_len + bsize);
0583 if (!blob)
0584 {
0585 free(cdata);
0586 close (bf);
0587 return -RTEMS_FDT_ERR_NO_MEMORY;
0588 }
0589
0590 blob->name = (const char*) (blob + 1);
0591 blob->blob = blob->name + name_len + 1;
0592
0593 strcpy ((char*) blob->name, filename);
0594
0595 if ((gzip_id[0] == 0x1f) && (gzip_id[1] == 0x8b))
0596 {
0597 z_stream stream;
0598 int err;
0599 stream.next_in = (Bytef*) cdata;
0600 stream.avail_in = (uInt) sb.st_size;
0601 stream.next_out = (void*) (blob->name + name_len + 1);
0602 stream.avail_out = (uInt) bsize;
0603 stream.zalloc = (alloc_func) 0;
0604 stream.zfree = (free_func) 0;
0605 err = inflateInit(&stream);
0606 if (err == Z_OK)
0607 err = inflateReset2(&stream, 31);
0608 if (err == Z_OK)
0609 err = inflate(&stream, Z_FINISH);
0610 if ((err == Z_OK) || (err == Z_STREAM_END))
0611 err = inflateEnd(&stream);
0612 if ((err != Z_OK) || (bsize != stream.total_out))
0613 {
0614 free (blob);
0615 free(cdata);
0616 close (bf);
0617 return -RTEMS_FDT_ERR_READ_FAIL;
0618 }
0619 free(cdata);
0620 cdata = NULL;
0621 }
0622 else
0623 {
0624 char* buf = (char*) blob->name + name_len + 1;
0625 size = bsize;
0626 while (size)
0627 {
0628 r = read (bf, buf, size);
0629 if (r < 0)
0630 {
0631 free (blob);
0632 close (bf);
0633 return -RTEMS_FDT_ERR_READ_FAIL;
0634 }
0635 size -= r;
0636 buf += r;
0637 }
0638 }
0639
0640 fe = fdt_check_header(blob->blob);
0641 if (fe < 0)
0642 {
0643 free (blob);
0644 close (bf);
0645 return fe;
0646 }
0647
0648 fdt = rtems_fdt_lock ();
0649
0650 rtems_chain_append_unprotected (&fdt->blobs, &blob->node);
0651
0652 blob->refs = 1;
0653
0654 rtems_fdt_unlock (fdt);
0655
0656 handle->blob = blob;
0657
0658 fe = rtems_fdt_init_index(handle, blob);
0659 if (fe < 0)
0660 {
0661 free (blob);
0662 close (bf);
0663 return fe;
0664 }
0665
0666 close (bf);
0667 return 0;
0668 }
0669
0670 int
0671 rtems_fdt_register (const void* dtb, rtems_fdt_handle* handle)
0672 {
0673 rtems_fdt_data* fdt;
0674 rtems_fdt_blob* blob;
0675 int fe;
0676
0677 rtems_fdt_release_handle (handle);
0678
0679 fe = fdt_check_header(dtb);
0680 if (fe < 0)
0681 {
0682 return fe;
0683 }
0684
0685 blob = rtems_malloc(sizeof (rtems_fdt_blob));
0686 if (!blob)
0687 {
0688 return -RTEMS_FDT_ERR_NO_MEMORY;
0689 }
0690
0691 blob->blob = dtb;
0692 blob->name = NULL;
0693 rtems_chain_initialize_node(&blob->node);
0694
0695 fdt = rtems_fdt_lock ();
0696
0697 rtems_chain_append_unprotected (&fdt->blobs, &blob->node);
0698
0699 blob->refs = 1;
0700
0701 rtems_fdt_unlock (fdt);
0702
0703 handle->blob = blob;
0704
0705 fe = rtems_fdt_init_index(handle, blob);
0706 if (fe < 0)
0707 {
0708 free(blob);
0709 return -RTEMS_FDT_ERR_NO_MEMORY;
0710 }
0711
0712 return 0;
0713 }
0714
0715 int
0716 rtems_fdt_unload (rtems_fdt_handle* handle)
0717 {
0718 rtems_fdt_data* fdt;
0719
0720 fdt = rtems_fdt_lock ();
0721
0722 if (!rtems_fdt_valid_handle (handle))
0723 {
0724 rtems_fdt_unlock (fdt);
0725 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0726 }
0727
0728 if (handle->blob->refs > 1)
0729 {
0730 rtems_fdt_unlock (fdt);
0731 return -RTEMS_FDT_ERR_REFERENCED;
0732 }
0733
0734 rtems_chain_extract_unprotected (&handle->blob->node);
0735
0736 rtems_fdt_release_index(&handle->blob->index);
0737
0738 free (handle->blob);
0739
0740 handle->blob = NULL;
0741
0742 rtems_fdt_unlock (fdt);
0743
0744 return 0;
0745 }
0746
0747 int
0748 rtems_fdt_num_mem_rsv (rtems_fdt_handle* handle)
0749 {
0750 if (!handle->blob)
0751 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0752 return fdt_num_mem_rsv (handle->blob->blob);
0753 }
0754
0755 int
0756 rtems_fdt_get_mem_rsv (rtems_fdt_handle* handle,
0757 int n,
0758 uint64_t* address,
0759 uint64_t* size)
0760 {
0761 if (!handle->blob)
0762 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0763 return fdt_get_mem_rsv (handle->blob->blob, n, address, size);
0764 }
0765
0766 int
0767 rtems_fdt_subnode_offset_namelen (rtems_fdt_handle* handle,
0768 int parentoffset,
0769 const char* name,
0770 int namelen)
0771 {
0772 if (!handle->blob)
0773 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0774 return fdt_subnode_offset_namelen (handle->blob->blob,
0775 parentoffset,
0776 name,
0777 namelen);
0778 }
0779
0780 int
0781 rtems_fdt_subnode_offset (rtems_fdt_handle* handle,
0782 int parentoffset,
0783 const char* name)
0784 {
0785 char full_name[256];
0786 const char *path;
0787
0788 if (!handle->blob)
0789 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0790
0791 path = rtems_fdt_index_find_name_by_offset(&handle->blob->index, parentoffset);
0792 snprintf(full_name, sizeof(full_name), "%s/%s", path, name);
0793
0794 return rtems_fdt_index_find_by_name(&handle->blob->index, full_name);
0795 }
0796
0797 int
0798 rtems_fdt_path_offset (rtems_fdt_handle* handle, const char* path)
0799 {
0800 return rtems_fdt_index_find_by_name(&handle->blob->index, path);
0801 }
0802
0803 const char*
0804 rtems_fdt_get_name (rtems_fdt_handle* handle, int nodeoffset, int* length)
0805 {
0806 if (!handle->blob)
0807 return NULL;
0808
0809 const char *name = rtems_fdt_index_find_name_by_offset(&handle->blob->index, nodeoffset);
0810 if (name && length)
0811 {
0812 *length = strlen(name);
0813 }
0814
0815 return name;
0816 }
0817
0818 int
0819 rtems_fdt_first_prop_offset(rtems_fdt_handle* handle, int nodeoffset)
0820 {
0821 return fdt_first_property_offset(handle->blob->blob, nodeoffset);
0822 }
0823
0824 int
0825 rtems_fdt_next_prop_offset(rtems_fdt_handle* handle, int propoffset)
0826 {
0827 return fdt_next_property_offset(handle->blob->blob, propoffset);
0828 }
0829
0830 const void*
0831 rtems_fdt_getprop_by_offset(rtems_fdt_handle* handle,
0832 int propoffset,
0833 const char** name,
0834 int* length)
0835 {
0836 return fdt_getprop_by_offset(handle->blob->blob, propoffset, name, length);
0837 }
0838
0839 const void*
0840 rtems_fdt_getprop_namelen (rtems_fdt_handle* handle,
0841 int nodeoffset,
0842 const char* name,
0843 int namelen,
0844 int* length)
0845 {
0846 if (!handle->blob)
0847 return NULL;
0848 return fdt_getprop_namelen (handle->blob->blob,
0849 nodeoffset,
0850 name,
0851 namelen,
0852 length);
0853 }
0854
0855 const void*
0856 rtems_fdt_getprop (rtems_fdt_handle* handle,
0857 int nodeoffset,
0858 const char* name,
0859 int* length)
0860 {
0861 if (!handle->blob)
0862 return NULL;
0863 return fdt_getprop (handle->blob->blob,
0864 nodeoffset,
0865 name,
0866 length);
0867 }
0868
0869 uint32_t
0870 rtems_fdt_get_phandle (rtems_fdt_handle* handle, int nodeoffset)
0871 {
0872 if (!handle->blob)
0873 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0874 return fdt_get_phandle (handle->blob->blob, nodeoffset);
0875 }
0876
0877 const char*
0878 rtems_fdt_get_alias_namelen (rtems_fdt_handle* handle,
0879 const char* name,
0880 int namelen)
0881 {
0882 if (!handle->blob)
0883 return NULL;
0884 return fdt_get_alias_namelen (handle->blob->blob, name, namelen);
0885 }
0886
0887 const char*
0888 rtems_fdt_get_alias (rtems_fdt_handle* handle, const char* name)
0889 {
0890 if (!handle->blob)
0891 return NULL;
0892 return fdt_get_alias (handle->blob->blob, name);
0893 }
0894
0895 int
0896 rtems_fdt_get_path (rtems_fdt_handle* handle,
0897 int nodeoffset,
0898 char* buf,
0899 int buflen)
0900 {
0901 if (!handle->blob)
0902 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0903 return fdt_get_path (handle->blob->blob, nodeoffset, buf, buflen);
0904 }
0905
0906 int
0907 rtems_fdt_supernode_atdepth_offset (rtems_fdt_handle* handle,
0908 int nodeoffset,
0909 int supernodedepth,
0910 int* nodedepth)
0911 {
0912 if (!handle->blob)
0913 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0914 return fdt_supernode_atdepth_offset(handle,
0915 nodeoffset,
0916 supernodedepth,
0917 nodedepth);
0918 }
0919
0920 int
0921 rtems_fdt_node_depth (rtems_fdt_handle* handle, int nodeoffset)
0922 {
0923 if (!handle->blob)
0924 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0925 return fdt_node_depth (handle->blob->blob, nodeoffset);
0926 }
0927
0928 int
0929 rtems_fdt_parent_offset (rtems_fdt_handle* handle, int nodeoffset)
0930 {
0931 if (!handle->blob)
0932 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0933 return fdt_parent_offset (handle->blob->blob, nodeoffset);
0934 }
0935
0936 int
0937 rtems_fdt_node_offset_by_prop_value (rtems_fdt_handle* handle,
0938 int startoffset,
0939 const char* propname,
0940 const void* propval,
0941 int proplen)
0942 {
0943 if (!handle->blob)
0944 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0945 return fdt_node_offset_by_prop_value (handle,
0946 startoffset,
0947 propname,
0948 propval,
0949 proplen);
0950 }
0951
0952 int
0953 rtems_fdt_node_offset_by_phandle (rtems_fdt_handle* handle, uint32_t phandle)
0954 {
0955 if (!handle->blob)
0956 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0957 return fdt_node_offset_by_phandle (handle->blob->blob, phandle);
0958 }
0959
0960 int
0961 rtems_fdt_node_check_compatible (rtems_fdt_handle* handle,
0962 int nodeoffset,
0963 const char* compatible)
0964 {
0965 if (!handle->blob)
0966 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0967 return fdt_node_check_compatible (handle, nodeoffset, compatible);
0968 }
0969
0970 int
0971 rtems_fdt_node_offset_by_compatible (rtems_fdt_handle* handle,
0972 int startoffset,
0973 const char* compatible)
0974 {
0975 if (!handle->blob)
0976 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0977 return fdt_node_offset_by_compatible (handle->blob->blob,
0978 startoffset,
0979 compatible);
0980 }
0981
0982 int
0983 rtems_fdt_next_node (rtems_fdt_handle* handle, int offset, int* depth)
0984 {
0985 if (!handle->blob)
0986 return -RTEMS_FDT_ERR_INVALID_HANDLE;
0987 return fdt_next_node (handle->blob->blob, offset, depth);
0988 }
0989
0990 const char*
0991 rtems_fdt_strerror (int errval)
0992 {
0993 const char* errors[] = {
0994 "invalid handle",
0995 "no memory",
0996 "file not found",
0997 "DTB read fail",
0998 "blob has references",
0999 "bad length"
1000 };
1001 if (errval > -RTEMS_FDT_ERR_RTEMS_MIN)
1002 return fdt_strerror (errval);
1003 if (errval < -RTEMS_FDT_ERR_MAX)
1004 return "invalid error code";
1005 return errors[(-errval) - RTEMS_FDT_ERR_RTEMS_MIN];
1006 }
1007
1008 int
1009 rtems_fdt_prop_value(const char* const path,
1010 const char* const propname,
1011 void* value,
1012 size_t* size)
1013 {
1014 rtems_fdt_handle fdt;
1015 int node;
1016 const void* prop;
1017 int length;
1018
1019 rtems_fdt_init_handle (&fdt);
1020
1021 node = rtems_fdt_find_path_offset (&fdt, path);
1022 if (node < 0)
1023 return node;
1024
1025 prop = rtems_fdt_getprop(&fdt, node, propname, &length);
1026 if (length < 0)
1027 {
1028 rtems_fdt_release_handle (&fdt);
1029 return length;
1030 }
1031
1032 if (length > (int) *size)
1033 {
1034 rtems_fdt_release_handle (&fdt);
1035 return -RTEMS_FDT_ERR_BADPATH;
1036 }
1037
1038 *size = length;
1039
1040 memcpy (value, prop, length);
1041
1042 return 0;
1043 }
1044
1045 bool
1046 rtems_fdt_get_parent_prop_value(rtems_fdt_handle* handle,
1047 int nodeoffset,
1048 const char* name,
1049 uint32_t* value)
1050 {
1051 const void* prop;
1052 int plen = 0;
1053 int node = rtems_fdt_parent_offset(handle, nodeoffset);
1054 if (node < 0)
1055 return false;
1056 prop = rtems_fdt_getprop(handle, node, name, &plen);
1057 if (plen < 0)
1058 return false;
1059 *value = rtems_fdt_get_uint32(prop);
1060 return true;
1061 }
1062
1063 int
1064 rtems_fdt_prop_map(const char* const path,
1065 const char* const propname,
1066 const char* const names[],
1067 uintptr_t* values,
1068 size_t count)
1069 {
1070 rtems_fdt_handle fdt;
1071 int node;
1072 size_t item;
1073
1074 rtems_fdt_init_handle (&fdt);
1075
1076 node = rtems_fdt_find_path_offset (&fdt, path);
1077 if (node < 0)
1078 return node;
1079
1080 for (item = 0; item < count; item++)
1081 {
1082 const void* prop;
1083 int length;
1084 int subnode;
1085
1086 subnode = rtems_fdt_subnode_offset (&fdt, node, names[item]);
1087 if (subnode < 0)
1088 {
1089 rtems_fdt_release_handle (&fdt);
1090 return subnode;
1091 }
1092
1093 prop = rtems_fdt_getprop(&fdt, subnode, propname, &length);
1094 if (length < 0)
1095 {
1096 rtems_fdt_release_handle (&fdt);
1097 return length;
1098 }
1099
1100 if (length > sizeof (uintptr_t))
1101 {
1102 rtems_fdt_release_handle (&fdt);
1103 return -RTEMS_FDT_ERR_BADPATH;
1104 }
1105
1106 values[item] = rtems_fdt_get_offset_len_uintptr(prop, 0, length);
1107 }
1108
1109 return 0;
1110 }
1111
1112 uintptr_t
1113 rtems_fdt_get_offset_len_uintptr (const void* prop, int offset, int len)
1114 {
1115 const uint8_t* p = prop;
1116 uintptr_t value = 0;
1117 int b;
1118 if (len <= sizeof(uintptr_t)) {
1119 for (b = 0; b < len; ++b) {
1120 value = (value << 8) | (uintptr_t) p[offset++];
1121 }
1122 }
1123 return value;
1124 }
1125
1126
1127 uint32_t
1128 rtems_fdt_get_offset_uint32 (const void* prop, int offset)
1129 {
1130 const uint8_t* p = prop;
1131 uint32_t value;
1132 offset *= sizeof(uint32_t);
1133 value = ((((uint32_t) p[offset + 0]) << 24) |
1134 (((uint32_t) p[offset + 1]) << 16) |
1135 (((uint32_t) p[offset + 2]) << 8) |
1136 (uint32_t) p[offset + 3]);
1137 return value;
1138 }
1139
1140 uint32_t
1141 rtems_fdt_get_uint32 (const void* prop)
1142 {
1143 return rtems_fdt_get_offset_uint32(prop, 0);
1144 }
1145
1146 uint64_t
1147 rtems_fdt_get_offset_uint64 (const void* prop, int offset)
1148 {
1149 uint64_t value = rtems_fdt_get_offset_uint32(prop, offset);
1150 value = (value << 16) << 16;
1151 return value | rtems_fdt_get_offset_uint32(prop, offset + 1);
1152 }
1153
1154 uint64_t
1155 rtems_fdt_get_uint64 (const void* prop)
1156 {
1157 return rtems_fdt_get_offset_uint64(prop, 0);
1158 }
1159
1160 uintptr_t
1161 rtems_fdt_get_uintptr (const void* prop)
1162 {
1163 return rtems_fdt_get_offset_uintptr(prop, 0);
1164 }
1165
1166 uintptr_t
1167 rtems_fdt_get_offset_uintptr (const void* prop, int offset)
1168 {
1169 if (sizeof(intptr_t) == sizeof(uint32_t))
1170 return rtems_fdt_get_offset_uint32(prop, offset);
1171 return rtems_fdt_get_offset_uint64(prop, offset);
1172 }
1173
1174 int
1175 rtems_fdt_get_value (const char* path,
1176 const char* property,
1177 size_t size,
1178 uintptr_t* value)
1179 {
1180 rtems_fdt_handle fdt;
1181 const void* prop;
1182 int node;
1183 int length;
1184
1185 rtems_fdt_init_handle (&fdt);
1186
1187 node = rtems_fdt_find_path_offset (&fdt, path);
1188 if (node < 0)
1189 {
1190 rtems_fdt_release_handle (&fdt);
1191 return node;
1192 }
1193
1194 prop = rtems_fdt_getprop(&fdt, node, property, &length);
1195 if (length < 0)
1196 {
1197 rtems_fdt_release_handle (&fdt);
1198 return length;
1199 }
1200
1201 if (length == sizeof (uintptr_t))
1202 *value = rtems_fdt_get_uintptr (prop);
1203 else
1204 *value = 0;
1205
1206 rtems_fdt_release_handle (&fdt);
1207
1208 return 0;
1209 }
1210
1211
1212
1213
1214 int
1215 rtems_fdt_num_entries(rtems_fdt_handle* handle)
1216 {
1217 return handle->blob->index.num_entries;
1218 }
1219
1220
1221
1222
1223
1224 const char *
1225 rtems_fdt_entry_name(rtems_fdt_handle* handle, int id)
1226 {
1227 return handle->blob->index.entries[id].name;
1228 }
1229
1230
1231
1232
1233
1234 int
1235 rtems_fdt_entry_offset(rtems_fdt_handle* handle, int id)
1236 {
1237 return handle->blob->index.entries[id].offset;
1238 }
1239
1240 int
1241 rtems_fdt_getprop_address_cells(rtems_fdt_handle* handle, int nodeoffset)
1242 {
1243 uint32_t value = 0;
1244 if (!rtems_fdt_get_parent_prop_value(handle, nodeoffset, "#address-cells", &value))
1245 return -1;
1246 return value;
1247 }
1248
1249 int
1250 rtems_fdt_getprop_size_cells(rtems_fdt_handle* handle, int nodeoffset)
1251 {
1252 uint32_t value = 0;
1253 if (!rtems_fdt_get_parent_prop_value(handle, nodeoffset, "#size-cells", &value))
1254 return -1;
1255 return value;
1256 }
1257
1258 int rtems_fdt_getprop_address_map(rtems_fdt_handle* handle,
1259 const char* path,
1260 const char* name,
1261 rtems_fdt_address_map* addr_map)
1262 {
1263 const void* prop;
1264 int plen = 0;
1265 int poff = 0;
1266 int len;
1267
1268 memset(addr_map, 0, sizeof(*addr_map));
1269
1270 addr_map->node = rtems_fdt_path_offset(handle, path);
1271 if (addr_map->node < 0)
1272 return -RTEMS_FDT_ERR_NOTFOUND;
1273
1274 addr_map->address_cells = rtems_fdt_getprop_address_cells(handle, addr_map->node);
1275 addr_map->size_cells = rtems_fdt_getprop_size_cells(handle, addr_map->node);
1276
1277 prop = rtems_fdt_getprop(handle, addr_map->node, name, &plen);
1278 if (plen < 0)
1279 return -RTEMS_FDT_ERR_NOTFOUND;
1280
1281 if (addr_map->address_cells == 0)
1282 return -RTEMS_FDT_ERR_BADOFFSET;
1283
1284 if (addr_map->address_cells < 0)
1285 {
1286 if (addr_map->size_cells > 0)
1287 return -RTEMS_FDT_ERR_BADOFFSET;
1288 addr_map->address_cells = 1;
1289 }
1290
1291 if (addr_map->size_cells < 0)
1292 {
1293 addr_map->size = sizeof(uint32_t);
1294 addr_map->size_cells = 0;
1295 }
1296
1297 len = (addr_map->address_cells + addr_map->size_cells) * sizeof(uint32_t);
1298
1299 if (len != plen)
1300 return -RTEMS_FDT_ERR_BADLENGTH;
1301
1302 switch (addr_map->address_cells)
1303 {
1304 case 1:
1305 if (plen < sizeof(uint32_t))
1306 return -RTEMS_FDT_ERR_BADLENGTH;
1307 addr_map->address = rtems_fdt_get_offset_uint32(prop, poff);
1308 poff += 1;
1309 plen -= sizeof(uint32_t);
1310 break;
1311 case 2:
1312 if (plen < sizeof(uint64_t))
1313 return -RTEMS_FDT_ERR_BADLENGTH;
1314 addr_map->address = rtems_fdt_get_offset_uint64(prop, poff);
1315 poff += 2;
1316 plen -= sizeof(uint64_t);
1317 break;
1318 default:
1319 return -RTEMS_FDT_ERR_BADLENGTH;
1320 }
1321
1322 switch (addr_map->size_cells)
1323 {
1324 case 0:
1325 addr_map->size = sizeof(uint32_t);
1326 break;
1327 case 1:
1328 if (plen < sizeof(uint32_t))
1329 return -RTEMS_FDT_ERR_BADLENGTH;
1330 addr_map->size = rtems_fdt_get_offset_uint32(prop, poff);
1331 poff += 1;
1332 plen -= sizeof(uint32_t);
1333 break;
1334 case 2:
1335 if (plen < sizeof(uint64_t))
1336 return -RTEMS_FDT_ERR_BADLENGTH;
1337 addr_map->size = rtems_fdt_get_offset_uint64(prop, poff);
1338 poff += 2;
1339 plen -= sizeof(uint64_t);
1340 break;
1341 default:
1342 return -RTEMS_FDT_ERR_BADLENGTH;
1343 }
1344
1345 return 0;
1346 }