struct FDTHeader { let magic: UInt32 // 0xd00dfeed let totalsize: UInt32 let off_dt_struct: UInt32 let off_dt_strings: UInt32 let off_mem_rsvmap: UInt32 let version: UInt32 let last_comp_version: UInt32 let boot_cpuid_phys: UInt32 let size_dt_strings: UInt32 let size_dt_struct: UInt32 } struct FDTProperty { let len: UInt32 let nameoff: UInt32 } enum FDTToken: UInt32 { case beginNode = 0x1 case endNode = 0x2 case prop = 0x3 case nop = 0x4 case end = 0x9 } extension UInt32 { var fromBe: UInt32 { return self.byteSwapped } } func alignUp(_ value: Int, to: Int) -> Int { return (value + to - 1) & ~(to - 1) } let kFDTHeaderMagic = 0xd00dfeed func parseDTB(at pointer: UnsafeRawPointer) { let header = pointer.bindMemory(to: FDTHeader.self, capacity: 1).pointee guard header.magic.byteSwapped == kFDTHeaderMagic else { return } let structOffset = Int(header.off_dt_struct.byteSwapped) let stringOffset = Int(header.off_dt_strings.byteSwapped) var structBase = pointer.advanced(by: structOffset) let stringsBase = pointer.advanced(by: stringOffset) var finished = false while !finished { let rawToken = structBase.load(as: UInt32.self).byteSwapped structBase = structBase.advanced(by: 4) if let token = FDTToken(rawValue: rawToken) { switch token { case .beginNode: let namePointer = structBase.assumingMemoryBound(to: UInt8.self) let name = String(cString: namePointer) let nameLength = name.utf8.count + 1 structBase = structBase.advanced(by: alignUp(nameLength, to: 4)) case .prop: let propertyHeader = structBase.load(as: FDTProperty.self) let dataLength = Int(propertyHeader.len.byteSwapped) let nameOffset = Int(propertyHeader.nameoff.byteSwapped) let namePointer = stringsBase.advanced(by: nameOffset).assumingMemoryBound(to: UInt8.self) structBase = structBase.advanced(by: 8) // skip header structBase = structBase.advanced(by: alignUp(dataLength, to: 4)) // skip data for now // TODO: finish it :D case .endNode: continue case .nop: continue case .end: finished = true } } } }