83 lines
2.5 KiB
Swift
83 lines
2.5 KiB
Swift
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
|
|
}
|
|
}
|
|
}
|
|
} |