2025-04-11 09:37:49 +02:00

150 lines
3.5 KiB
Go

package main
import (
"encoding/binary"
"encoding/json"
"flag"
"fmt"
"io"
"os"
)
type PartTable struct {
Header struct {
Version uint8
}
ManagementAppData struct {
Status uint8
Auth struct {
Nonce [16]uint8
AuthDigest [16]uint8
}
}
PreLoadedAppData [2]struct {
Status uint8
Size uint32
Auth struct {
Nonce [16]uint8
AuthDigest [16]uint8
}
Digest [32]uint8
Signature [64]uint8
}
AppStorage [4]struct {
Status uint8
Auth struct {
Nonce [16]uint8
AuthDigest [16]uint8
}
AddrStart uint32
Size uint32
}
}
type Flash struct {
Bitstream [0x20000]uint8
PartitionTable PartTable
PartitionTablePadding [64*1024 - 464]uint8
PreLoadedApp0 [0x20000]uint8
PreLoadedApp1 [0x20000]uint8
AppStorage [4][0x20000]uint8
EndPadding [0x10000]uint8
}
func readPartTable(filename string) PartTable {
var tbl PartTable
tblFile, err := os.Open(filename)
if err != nil {
panic(err)
}
if err := binary.Read(tblFile, binary.LittleEndian, &tbl); err != nil {
fmt.Println("binary.Read failed:", err)
}
tblStructLen, _ := tblFile.Seek(0, io.SeekCurrent)
fmt.Fprintf(os.Stderr, "INFO: Go partition table struct is %d byte long\n", tblStructLen)
return tbl
}
func readFlashDump(filename string) Flash {
var flash Flash
flashFile, err := os.Open(filename)
if err != nil {
panic(err)
}
if err := binary.Read(flashFile, binary.LittleEndian, &flash); err != nil {
fmt.Println("binary.Read failed:", err)
}
flashStructLen, _ := flashFile.Seek(0, io.SeekCurrent)
fmt.Fprintf(os.Stderr, "INFO: Go flash table struct is %d Mbyte long\n", flashStructLen/1024/1024)
return flash
}
func printPartTableJson(tbl PartTable) {
partTableJSON, err := json.MarshalIndent(tbl, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", string(partTableJSON))
}
func printPartTableCondensed(tbl PartTable) {
fmt.Printf("Header\n")
fmt.Printf(" Version : %d\n", tbl.Header.Version)
fmt.Printf("Management App\n")
fmt.Printf(" Status : %d\n", tbl.ManagementAppData.Status)
fmt.Printf(" Auth.Nonce : %x\n", tbl.ManagementAppData.Auth.Nonce)
fmt.Printf(" Auth.AuthDigest : %x\n", tbl.ManagementAppData.Auth.AuthDigest)
for i, appData := range tbl.PreLoadedAppData {
fmt.Printf("Preloaded App %d\n", i)
fmt.Printf(" Status : %d\n", appData.Status)
fmt.Printf(" Size : %d\n", appData.Size)
fmt.Printf(" Auth.Nonce : %x\n", appData.Auth.Nonce)
fmt.Printf(" Auth.AuthDigest : %x\n", appData.Auth.AuthDigest)
fmt.Printf(" Digest : %x\n", appData.Digest[:16])
fmt.Printf(" %x\n", appData.Digest[16:])
fmt.Printf(" Signature : %x\n", appData.Signature[:16])
fmt.Printf(" %x\n", appData.Signature[16:32])
fmt.Printf(" %x\n", appData.Signature[32:48])
fmt.Printf(" %x\n", appData.Signature[48:])
}
}
func main() {
filename := ""
json := false
flash := false
flag.StringVar(&filename, "i", "", "Partition table binary dump file.")
flag.BoolVar(&json, "j", false, "Print partition table in JSON format.")
flag.BoolVar(&flash, "f", false, "Treat input file as a dump of the entire flash memory.")
flag.Parse()
if filename == "" {
flag.Usage()
os.Exit(1)
}
var tbl PartTable
if flash {
tbl = readFlashDump(filename).PartitionTable
} else {
tbl = readPartTable(filename)
}
if json {
printPartTableJson(tbl)
} else {
printPartTableCondensed(tbl)
}
}