#include <stdio.h> #include <fcntl.h> #include <stdlib.h> #define DEV_TREE_PROP_NAME_LEN 32 #define DEV_TREE_PROP_VALUE_LEN 8192 #define DEV_TREE_PROP_FLAGS_MASK (0xf0000000) #define PAD32(x) (((x) + 3) & ~3) // Macro to make sure values get padded on 32-bit boundary /** * dtize.c - Another http://NewOSXBook.com/ source example * * A simple device tree dumper. Similar to what imagine (for img3) had, but works on new * Img4s as well. Doesn't actually do any DER processing (hence quick) * * License: ABSE. Rest of the world - Use and abuse. The day of open iOS on generic ARM64 * architectures drawns (infinitessimally) closer.. * */ typedef unsigned int uint32_t; typedef unsigned long uint64_t; int indent = 0; void getDTNode (int fd) { int rc = 0; char devTreePropName[DEV_TREE_PROP_NAME_LEN]; unsigned char devTreePropValue[DEV_TREE_PROP_VALUE_LEN]; uint32_t devTreePropLenAndFlags = 0; uint32_t devTreePropFlags = 0; uint32_t numProperties = 0; uint32_t numChildren = 0 ; rc = read (fd, &numProperties, sizeof(uint32_t)); rc = read (fd, &numChildren, sizeof(uint32_t)); printf("NUM PROPERTIES: %d, NUM CHILDREN: %d\n", numProperties, numChildren); int p = 0; while (p < numProperties ) { rc = read (fd, devTreePropName, DEV_TREE_PROP_NAME_LEN); rc = read (fd, &devTreePropLenAndFlags, sizeof(uint32_t)); devTreePropFlags = devTreePropLenAndFlags & DEV_TREE_PROP_FLAGS_MASK; devTreePropLenAndFlags &= ~DEV_TREE_PROP_FLAGS_MASK; if (devTreePropLenAndFlags > DEV_TREE_PROP_VALUE_LEN) { off_t pos = lseek (fd, 0, SEEK_CUR); fprintf(stderr,"Error: Excessive device tree property len Pos %x (%d > %d)\n", pos, devTreePropLenAndFlags , DEV_TREE_PROP_VALUE_LEN); exit(0); } rc = read (fd, devTreePropValue, PAD32(devTreePropLenAndFlags)); int i = 0; while (i < indent) { printf("---"); i++;}; printf("%s (%d bytes): ", devTreePropName, devTreePropLenAndFlags); static char allZeros[DEV_TREE_PROP_VALUE_LEN] = { 0 }; if (devTreePropLenAndFlags == 4) { // Print as integer printf("%d (*)\n", *(uint32_t *) devTreePropValue); } else if (memcmp(devTreePropValue, allZeros, devTreePropLenAndFlags) ==0) { printf("(NULL)\n"); } else { // safe string int j = 0; for (j = 0 ; j < devTreePropLenAndFlags; j++) { if (isprint(devTreePropValue[j])) putc(devTreePropValue[j], stdout); else if ((j == devTreePropLenAndFlags - 1) && !devTreePropValue[j]) { /* skip terminating NULL */} else printf("\\x%02x", devTreePropValue[j]); } printf("\n"); } p++; } indent++; int c = 0; while (c< numChildren ) { printf("Child %d:", c); getDTNode(fd); c++; } indent--; } // end getDTNode; int main (int argc, char **argv) { if (!argv[1]) { fprintf(stderr,"Usage: %s DeviceTree....im4p\n", argv[0]); exit(1); } int fd = open (argv[1],O_RDONLY); if (fd < 0){ perror (argv[1]); exit(2);} // The IMG4p header is a DER header of 48 bytes: // // 0:d=0 hl=5 l=168296 cons: SEQUENCE // 5:d=1 hl=2 l= 4 prim: IA5STRING :IM4P // 11:d=1 hl=2 l= 4 prim: IA5STRING :dtre // 17:d=1 hl=2 l= 29 prim: IA5STRING :EmbeddedDeviceTrees-3480.40.4 // @TODO: Handle DER. For now, just skip to offset 19, which is where EmbeddedDevice // in IA5String starts // //00000000 30 83 02 91 68 16 04 49 4d 34 50 16 04 64 74 72 |0...h..IM4P..dtr| //00000010 65 16 1d 45 6d 62 65 64 64 65 64 44 65 76 69 63 |e..EmbeddedDevic| //00000020 65 54 72 65 65 73 // char buf[256]; int rc = read (fd, buf, 19); if (buf[17] != 0x16) { fprintf(stderr,"Error: Expected IA5STRING for EmbeddedDevice...\n"); exit(5); } // Otherwise the length of the Embedded DeviceTree.... string is in buf[18] int len = buf[18]; rc = read (fd,buf, len); // At this offset we expect the last two bytes // At offset 48 we expect an OCTET STRING (4) // 48:d=1 hl=5 l=168248 prim char dtBegins[] = { '\x04' , '\x83' }; rc = read (fd, buf, 2); if (memcmp (buf, dtBegins,2)) { fprintf(stderr,"Error: Expected OCTET STRING with 3 byte length at offet 48\n"); exit(3); } int totalLenLen = 3; // Otherwise get total length, assuming 3 bytes uint32_t totalLen = 0; rc = read (fd, &totalLen, totalLenLen); totalLen <<=8; totalLen = ntohl(totalLen); printf("Device Tree of %ld bytes\n", totalLen); // @TODO: Sanity check for size (vs. fstat) // // uint32_t numProperties = 0; uint32_t numChildren = 0 ; // Read two uint32_t values. One is 12, the other is 10. Then start the properties uint32_t pos = 48 + 5 ; // Now for the properties! while (pos < totalLen) { getDTNode(fd); pos = lseek(fd, 0, SEEK_CUR); } // end while }