From c7032ccd3088134366f71301b4ced796206233e1 Mon Sep 17 00:00:00 2001 From: soypat Date: Sun, 22 Sep 2024 07:44:54 -0300 Subject: [PATCH] modularize even further --- blocks.go | 2 +- cmd/picobin/elf.go | 52 ++++++++++---------------------------- cmd/picobin/picobin.go | 27 ++++++++++++++++++-- cmd/picobin/uf2.go | 57 ++++++++++++++++++++++++------------------ uf2/uf2.go | 10 ++++---- 5 files changed, 77 insertions(+), 71 deletions(-) diff --git a/blocks.go b/blocks.go index c0e4907..4c17784 100644 --- a/blocks.go +++ b/blocks.go @@ -58,7 +58,7 @@ func (b Block) Validate() error { } func (b Block) String() string { - return fmt.Sprintf("%s link=%d", b.Items, b.Link) + return fmt.Sprintf("%s link=%d sz=%d", b.Items, b.Link, b.Size()) } // Size returns the size of the block in bytes, from start of header to end of footer. diff --git a/cmd/picobin/elf.go b/cmd/picobin/elf.go index 60faae6..7d620d2 100644 --- a/cmd/picobin/elf.go +++ b/cmd/picobin/elf.go @@ -2,12 +2,9 @@ package main import ( "debug/elf" - "encoding/hex" - "errors" "fmt" "io" - "github.com/github.com/soypat/picobin" "github.com/github.com/soypat/picobin/elfutil" ) @@ -24,12 +21,16 @@ func elfinfo(r io.ReaderAt, flags Flags) error { totalSize += int(sect.Size) } fmt.Printf("total program memory=%d\n", totalSize) - - blocks, start, err := elfBlocks(f, flags) + ROM, romstart, err := elfROM(f, flags) + if err != nil { + return err + } + blocks, block0off, err := romBlocks(ROM, romstart) if err != nil { return err } - return blockInfo(blocks, start, flags) + block0Addr := romstart + uint64(block0off) + return blockInfo(blocks, block0Addr, flags) } func elfdump(r io.ReaderAt, flags Flags) error { @@ -37,36 +38,14 @@ func elfdump(r io.ReaderAt, flags Flags) error { if err != nil { return err } - blocks, start, err := elfBlocks(f, flags) + ROM, romstart, err := elfROM(f, flags) if err != nil { return err } - - addr := start - for i, block := range blocks { - if flags.block >= 0 && i != flags.block || len(block.Items) >= 1 && block.Items[0].ItemType() == picobin.ItemTypeIgnored { - addr += uint64(block.Link) - continue - } - blockSize := block.Size() - dataSize := block.Link - blockSize - if dataSize < 0 { - break // Last block. - } - data := make([]byte, dataSize) - n, err := elfutil.ReadAt(f, data, int64(addr)+int64(blockSize)) - if err != nil { - return err - } else if n == 0 { - return errors.New("unable to extract data after block") - } - fmt.Printf("BLOCK%d @ Addr=%#x dump:\n%s", i, addr, hex.Dump(data)) - addr += uint64(block.Link) - } - return nil + return romDump(ROM, romstart, flags) } -func elfBlocks(f *elf.File, flags Flags) ([]picobin.Block, uint64, error) { +func elfROM(f *elf.File, flags Flags) (ROM []byte, romAddr uint64, err error) { uromStart, uromEnd, err := elfutil.GetROMAddr(f) if err != nil { return nil, 0, err @@ -77,24 +56,19 @@ func elfBlocks(f *elf.File, flags Flags) ([]picobin.Block, uint64, error) { fmt.Printf("ROM %d too large, limiting to %d\n", romSize, flags.readsize) romSize = uint64(flags.readsize) } - ROM := make([]byte, romSize) + ROM = make([]byte, romSize) flashEnd, err := elfutil.ReadAt(f, ROM[:], romStart) if err != nil { return nil, 0, err } - blocks, block0Start, err := romBlocks(ROM[:flashEnd], uromStart) - if err != nil { - return blocks, 0, err - } - startAbs := uint64(block0Start) + uromStart - return blocks, startAbs, nil + return ROM[:flashEnd], uromStart, nil } // helper function that discards sections and program memory of no interest to us. func newElfFile(r io.ReaderAt, flags Flags) (*elf.File, error) { f, err := elf.NewFile(r) if err != nil { - return nil, err + return nil, fmt.Errorf("attempt to read ELF format: %w", err) } var sections []*elf.Section diff --git a/cmd/picobin/picobin.go b/cmd/picobin/picobin.go index efe53e2..60117b6 100644 --- a/cmd/picobin/picobin.go +++ b/cmd/picobin/picobin.go @@ -1,6 +1,7 @@ package main import ( + "encoding/hex" "errors" "flag" "fmt" @@ -123,12 +124,12 @@ func romBlocks(ROM []byte, romStartAddr uint64) (blocks []picobin.Block, block0O return blocks, block0Off, nil } -func blockInfo(blocks []picobin.Block, block0Start uint64, flags Flags) (err error) { +func blockInfo(blocks []picobin.Block, block0StartAddr uint64, flags Flags) (err error) { if len(blocks) == 0 { return errors.New("no blocks found") } fmt.Println("ROM Block info:") - addr := block0Start + addr := block0StartAddr for i, block := range blocks { if flags.block >= 0 && i != flags.block { addr += uint64(block.Link) @@ -149,3 +150,25 @@ func blockInfo(blocks []picobin.Block, block0Start uint64, flags Flags) (err err } return nil } + +func romDump(ROM []byte, startAddr uint64, flags Flags) (err error) { + blocks, block0Start, err := romBlocks(ROM, startAddr) + if err != nil { + return err + } + off := block0Start + for i, block := range blocks { + if flags.block >= 0 && i != flags.block || len(block.Items) >= 1 && block.Items[0].ItemType() == picobin.ItemTypeIgnored { + off += int(block.Link) + continue + } + nextOff := off + block.Link + if nextOff == block0Start { + break // Last block. + } + addr := startAddr + uint64(off) + fmt.Printf("BLOCK%d @ Addr=%#x dump:\n%s", i, addr, hex.Dump(ROM[off:nextOff])) + off += int(block.Link) + } + return nil +} diff --git a/cmd/picobin/uf2.go b/cmd/picobin/uf2.go index 21eb2c6..1313a70 100644 --- a/cmd/picobin/uf2.go +++ b/cmd/picobin/uf2.go @@ -35,30 +35,11 @@ func uf2info(r io.ReaderAt, flags Flags) error { } fmt.Fprintf(os.Stdout, "\t%s sha256=%x\n", block.String(), sum) } - - rd, err := uf2.NewBlocksReaderAt(uf2blocks) + ROM, romstart, err := romFromUF2Blocks(uf2blocks, flags) if err != nil { return err } - start, end := rd.Addrs() - if end > uint32(flags.flashend) { - end = uint32(flags.flashend) - } - romsize := int(end) - int(start) - if romsize < 0 { - return fmt.Errorf("invalid addresses or bad flash address flag start=%#x, flashlim=%#x", start, flags.flashend) - } else if romsize > int(flags.readsize) { - fmt.Println("limiting ROM read") - romsize = int(flags.readsize) - } - ROM := make([]byte, romsize) - n, err := rd.ReadAt(ROM, int64(start)) - if err != nil { - return err - } else if n != len(ROM) { - fmt.Println("unexpected short read:", n, "of", len(ROM)) - } - blocks, block0start, err := romBlocks(ROM, uint64(start)) + blocks, block0start, err := romBlocks(ROM, romstart) if err != nil { return err } @@ -87,9 +68,9 @@ func uf2conv(r io.ReaderAt, flags Flags) error { } else if n != len(ROM) { return fmt.Errorf("failed to read ELF ROM completely (%d/%d)", n, len(ROM)) } - fmt := uf2.Formatter{ChunkSize: 256, FamilyID: uint32(flags.familyID), Flags: uf2.FlagFamilyIDPresent} + formatter := uf2.Formatter{ChunkSize: 256, FamilyID: uint32(flags.familyID), Flags: uf2.FlagFamilyIDPresent} uf2prog := make([]byte, 0, size) - uf2prog, _, err = fmt.AppendTo(uf2prog, ROM, uint32(start)) + uf2prog, _, err = formatter.AppendTo(uf2prog, ROM, uint32(start)) if err != nil { return err } @@ -97,7 +78,35 @@ func uf2conv(r io.ReaderAt, flags Flags) error { if dotIdx < 0 { dotIdx = len(flags.argSourcename) } - return os.WriteFile(flags.argSourcename[:dotIdx]+".uf2", uf2prog, 0777) + filename := flags.argSourcename[:dotIdx] + ".uf2" + fmt.Println("writing file", filename) + return os.WriteFile(filename, uf2prog, 0777) +} + +func romFromUF2Blocks(uf2blocks []uf2.Block, flags Flags) (ROM []byte, romAddr uint64, err error) { + rd, err := uf2.NewBlocksReaderAt(uf2blocks) + if err != nil { + return nil, 0, err + } + start, end := rd.Addrs() + if end > uint32(flags.flashend) { + end = uint32(flags.flashend) + } + romsize := int(end) - int(start) + if romsize < 0 { + return nil, 0, fmt.Errorf("invalid addresses or bad flash address flag start=%#x, flashlim=%#x", start, flags.flashend) + } else if romsize > int(flags.readsize) { + fmt.Println("limiting ROM read") + romsize = int(flags.readsize) + } + ROM = make([]byte, romsize) + n, err := rd.ReadAt(ROM, int64(start)) + if err != nil { + return nil, 0, err + } else if n != len(ROM) { + fmt.Println("unexpected short read:", n, "of", len(ROM)) + } + return ROM, uint64(start), nil } func uf2file(r io.ReaderAt, _ Flags) ([]uf2.Block, error) { diff --git a/uf2/uf2.go b/uf2/uf2.go index fc5e47e..6b080ea 100644 --- a/uf2/uf2.go +++ b/uf2/uf2.go @@ -96,20 +96,20 @@ func (b *Block) Validate() error { return nil } -func DecodeAppendBlocks(dst []Block, r io.Reader, buf []byte) ([]Block, int, error) { - if len(buf) < BlockSize { +func DecodeAppendBlocks(dst []Block, r io.Reader, scratchBuf []byte) ([]Block, int, error) { + if len(scratchBuf) < BlockSize { return dst, 0, errors.New("decode buffer to small to fit a block") } // Round size of buffer to block size. - buf = buf[:len(buf)-len(buf)%BlockSize] + scratchBuf = scratchBuf[:len(scratchBuf)-len(scratchBuf)%BlockSize] ntot := 0 numBlocks := 0 for { - n, err := io.ReadFull(r, buf) + n, err := io.ReadFull(r, scratchBuf) ntot += n i := 0 for i+BlockSize <= n { - block, err := DecodeBlock(buf[i:]) + block, err := DecodeBlock(scratchBuf[i:]) if err != nil { return dst, ntot, err }