133 lines
2.8 KiB
Go
133 lines
2.8 KiB
Go
package firmware
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
"git.gammaspectra.live/WeebDataHoarder/PhytonUtils/buffer"
|
|
"git.gammaspectra.live/WeebDataHoarder/PhytonUtils/encryption"
|
|
"io"
|
|
)
|
|
|
|
const FlashAreaPublicSignature = 0x19601217
|
|
|
|
type FlashAreaData struct {
|
|
// PublicSignature Should always be FlashAreaPublicSignature
|
|
PublicSignature uint32
|
|
StructLen uint32
|
|
Data []byte
|
|
}
|
|
|
|
type FlashAreaData_PublicAPI struct {
|
|
BootSignature uint32
|
|
ProductSerialNumber [32]byte
|
|
TargetFileName [32]byte
|
|
ProductName [64]byte
|
|
CalibrationBP0 uint32
|
|
CalibrationBP290 uint32
|
|
VendorID uint16
|
|
ProductID uint16
|
|
ManufacturerName [32]byte
|
|
TargetID uint32
|
|
TargetStartTimeout uint32
|
|
}
|
|
|
|
func (f *FlashAreaData) PublicAPI() *FlashAreaData_PublicAPI {
|
|
var result FlashAreaData_PublicAPI
|
|
err := binary.Read(bytes.NewReader(f.Data), binary.LittleEndian, &result)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return &result
|
|
}
|
|
|
|
type FlashArea uint32
|
|
|
|
const (
|
|
FlashAreaUnknown = FlashArea(iota)
|
|
FlashAreaPublicAPI
|
|
)
|
|
|
|
type FlashStatus uint32
|
|
|
|
const (
|
|
FlashOK = FlashStatus(iota)
|
|
FlashInvAddr
|
|
FlashWrProt
|
|
FlashNotBlank
|
|
FlashVerify
|
|
FlashErase
|
|
FlashProg
|
|
FlashInitEr
|
|
FlashSignEr
|
|
FlashInvalidCRC
|
|
FlashInvalidKeyNumb
|
|
FlashInvalidSign
|
|
FlashInvalidAreaName
|
|
FlashInvalidTarget
|
|
FlashRdpErr
|
|
)
|
|
|
|
// DecodeReadFlashArea Decodes a result of RD_FLASH_AREA command
|
|
func DecodeReadFlashArea(data []byte) (*FlashAreaData, error) {
|
|
buf := buffer.Buffer(data)
|
|
|
|
flashStatusInt, err := buf.ReadUint32()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
flashStatus := FlashStatus(flashStatusInt)
|
|
|
|
if flashStatus != FlashOK {
|
|
if flashStatus == FlashInvalidAreaName {
|
|
return nil, errors.New("area out of bounds")
|
|
} else if flashStatus == FlashInvalidSign {
|
|
return nil, errors.New("invalid area public signature")
|
|
}
|
|
return nil, fmt.Errorf("invalid flash status %d", flashStatus)
|
|
}
|
|
|
|
// random seed is set by device using register TIM6_CNT at 0x40001024
|
|
randomSeed, err := buf.ReadUint32()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
size, err := buf.ReadUint32()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
size, randomSeed = encryption.BorlandRandXORUint32(size, randomSeed)
|
|
if int(size) > len(buf) {
|
|
return nil, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
flashData := make(buffer.Buffer, size)
|
|
_, err = buf.Read(flashData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
randomSeed = encryption.BorlandRandXORInPlace(flashData, randomSeed)
|
|
|
|
areaData := &FlashAreaData{}
|
|
|
|
areaData.PublicSignature, err = flashData.ReadUint32()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
areaData.StructLen, err = flashData.ReadUint32()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if int(areaData.StructLen) != (len(flashData) + 8) {
|
|
return nil, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
areaData.Data = flashData
|
|
|
|
return areaData, nil
|
|
}
|