s19-from-mpar
This commit is contained in:
parent
ac7580e620
commit
8e5c077b9f
5 changed files with 186 additions and 67 deletions
|
@ -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
|
||||
|
|
74
commands/s19-from-mpar.go
Normal file
74
commands/s19-from-mpar.go
Normal file
|
@ -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
|
||||
}
|
11
common/address.go
Normal file
11
common/address.go
Normal file
|
@ -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
|
||||
}
|
||||
|
|
151
s19/writer.go
151
s19/writer.go
|
@ -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…
Add table
Reference in a new issue