s19-from-mpar

master
cheetah 1 month ago
parent ac7580e620
commit 8e5c077b9f

@ -3,7 +3,7 @@ package commands
type BaseCommand struct {
Help HelpCommand `command:"help" description:"Print this help message"`
PrepareBin PrepareBinCommand `command:"prepare" alias:"p" description:"Prepare a Binary file and attach the propietary header to it"`
//PrepareBin PrepareBinCommand `command:"prepare" alias:"p" description:"Prepare a Binary file and attach the propietary header to it"`
DecryptDBF DecryptDBFCommand `command:"decrypt-dbf" description:"decrypt dbf-data"`
DecryptDES DecryptDESCommand `command:"decrypt-des" description:"decrypt des-data"`
@ -12,6 +12,7 @@ type BaseCommand struct {
S19Tree S19TreeCommand `command:"s19-tree" description:"dump s19 tree"`
S19IsolatePart S19IsolatePartitionCommand `command:"s19-isolate-part" description:"isolate a segment from an s19"`
S19FromMpar S19FromMparCommand `command:"s19-from-mpar" description:"creates an s19 from an mpar"`
}
var MotoCLI BaseCommand

@ -0,0 +1,74 @@
package commands
import (
"os"
"git.cheetah.cat/cheetah/moto-flash-data/common"
"git.cheetah.cat/cheetah/moto-flash-data/s19"
"github.com/rs/zerolog/log"
)
type S19FromMparCommand struct {
FileName string `long:"file" short:"f" required:"true" description:"input-file, format: mpar"`
StartAddress string `long:"start-address" required:"true" short:"a" description:"start address"`
OutputFileName string `long:"out" short:"o" required:"true" description:"output-file, format: s19"`
}
func (command *S19FromMparCommand) Execute(args []string) error {
baseAddr, err := common.ParseStringHexAddress(command.StartAddress)
if err != nil {
return err
}
log.Info().Str("input", command.FileName).Msg("S19-FromMpar")
inputFile, err := os.Open(command.FileName)
if err != nil {
return err
}
defer inputFile.Close()
s19File, err := s19.NewS19Writer(command.OutputFileName)
if err != nil {
return err
}
defer s19File.Close()
log.Info().Str("output", command.OutputFileName).Msg("Writing file...")
records, err := s19File.CreateRecordsFromBinary(inputFile, uint32(baseAddr), 32)
if err != nil {
return err
}
// S0 14 5E73 3D466C617368205265706F72745E6F3D30 19
// S0 14 5E73 3D466C617368205265706F72745E6F3D30 <Checksum>
header := []s19.SRecord{
{
Type: "S0",
Count: 0x14,
Address: 0x5E73,
Data: []byte("=Flash Report^o=0"), // 3D466C617368205265706F72745E6F3D30
},
}
footer := []s19.SRecord{ // S701FE
{
Type: "S7",
Count: 0,
Address: 0x01FE,
Data: []byte{},
},
}
err = s19File.WriteRecords(header)
if err != nil {
return err
}
err = s19File.WriteRecords(records)
if err != nil {
return err
}
err = s19File.WriteRecords(footer)
if err != nil {
return err
}
return nil
}

@ -0,0 +1,11 @@
package common
import "strconv"
func ParseStringHexAddress(hexAddress string) (res uint64, err error) {
parsedValue, err := strconv.ParseUint(hexAddress[2:], 16, 32)
if err != nil {
return 0, err
}
return parsedValue, nil
}

@ -1,6 +1,9 @@
package s19
import "strconv"
import (
"encoding/hex"
"strconv"
)
func validateChecksum(line string, checksum byte) bool {
sum := byte(0)
@ -10,3 +13,12 @@ func validateChecksum(line string, checksum byte) bool {
}
return ^sum == checksum
}
func computeChecksum(body string) byte {
sum := byte(0)
for i := 0; i < len(body); i += 2 {
value, _ := hex.DecodeString(body[i : i+2])
sum += value[0]
}
return ^sum
}

@ -3,14 +3,87 @@ package s19
import (
"encoding/hex"
"fmt"
"io"
"os"
)
type S19Writer struct {
FilePath string
File *os.File
}
func NewS19Writer(filePath string) (*S19Writer, error) {
file, err := os.Create(filePath)
if err != nil {
return nil, err
}
return &S19Writer{
FilePath: filePath,
File: file,
}, nil
}
func (fw *S19Writer) WriteCPSHeader() error {
// S0 14 5E73 3D466C617368205265706F72745E6F3D30 <Checksum>
//
return nil
}
// 32byte per record
func (fw *S19Writer) CreateRecordsFromBinary(originalFile *os.File, baseAddress uint32, maxDataSize int) ([]SRecord, error) {
var records []SRecord
buffer := make([]byte, maxDataSize)
currentAddress := baseAddress
for {
// Read up to maxDataSize bytes from the file
n, err := originalFile.Read(buffer)
if err != nil && err != io.EOF {
return nil, err
}
// If we read nothing, we're done
if n == 0 {
break
}
// Create an S3 record
record := SRecord{
Type: "S3",
Address: currentAddress,
Data: append([]byte{}, buffer[:n]...), // Copy the data
}
records = append(records, record)
// Update the current address
currentAddress += uint32(n)
}
return records, nil
}
func (fw *S19Writer) WriteRecords(records []SRecord) error {
for _, record := range records {
line, err := writeSRecord(record)
if err != nil {
return err
}
_, err = fw.File.WriteString(line + "\n")
if err != nil {
return err
}
}
return nil
}
func (fw *S19Writer) Close() error {
return fw.File.Close()
}
// writeSRecord creates a formatted S-record line
func writeSRecord(record SRecord) (string, error) {
var addressLength int
switch record.Type {
case "S1": // 2-byte address
case "S0", "S1": // 2-byte address
addressLength = 2
case "S2": // 3-byte address
addressLength = 3
@ -18,6 +91,18 @@ func writeSRecord(record SRecord) (string, error) {
addressLength = 4
case "S9": // Termination record with a 2-byte start address
addressLength = 2
case "S7": // The address field contains the starting execution address and is interpreted as a 4-byte big-endian address. There is no data field.
addressLength := 1
if record.Address > 0xFF {
addressLength = 2
}
if record.Address > 0xFFFF {
addressLength = 4
}
addressFormat := fmt.Sprintf("%%0%dX", addressLength*2)
address := fmt.Sprintf(addressFormat, record.Address)
return fmt.Sprintf("S%s%s", record.Type[1:], address), nil
default:
return "", fmt.Errorf("unsupported record type: %s", record.Type)
}
@ -41,67 +126,3 @@ func writeSRecord(record SRecord) (string, error) {
// Construct the final S-record
return fmt.Sprintf("S%s%s%02X", record.Type[1:], body, checksum), nil
}
// computeChecksum calculates the checksum for an S-record
func computeChecksum(body string) byte {
sum := byte(0)
for i := 0; i < len(body); i += 2 {
value, _ := hex.DecodeString(body[i : i+2])
sum += value[0]
}
return ^sum
}
// writeS19File creates an S19 file with the provided records
func writeS19File(filename string, records []SRecord) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
for _, record := range records {
line, err := writeSRecord(record)
if err != nil {
return err
}
_, err = file.WriteString(line + "\n")
if err != nil {
return err
}
}
return nil
}
func main() {
// Example data to write
data := []byte("Hello, S19 world!")
// Create a list of records
records := []SRecord{
{
Type: "S1",
Address: 0x1000,
Data: data[:8], // First chunk
},
{
Type: "S1",
Address: 0x1008,
Data: data[8:], // Second chunk
},
{
Type: "S9",
Address: 0x1000, // Start address for the program
Data: nil,
},
}
// Write the records to a file
err := writeS19File("output.s19", records)
if err != nil {
fmt.Printf("Error writing S19 file: %v\n", err)
return
}
fmt.Println("S19 file written successfully.")
}

Loading…
Cancel
Save