Skip to content

Commit

Permalink
modularize even further
Browse files Browse the repository at this point in the history
  • Loading branch information
soypat committed Sep 22, 2024
1 parent ad6ad41 commit c7032cc
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 71 deletions.
2 changes: 1 addition & 1 deletion blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
52 changes: 13 additions & 39 deletions cmd/picobin/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -24,49 +21,31 @@ 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 {
f, err := newElfFile(r, flags)
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
Expand All @@ -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
Expand Down
27 changes: 25 additions & 2 deletions cmd/picobin/picobin.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/hex"
"errors"
"flag"
"fmt"
Expand Down Expand Up @@ -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)
Expand All @@ -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
}
57 changes: 33 additions & 24 deletions cmd/picobin/uf2.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -87,17 +68,45 @@ 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
}
dotIdx := strings.IndexByte(flags.argSourcename, '.')
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) {
Expand Down
10 changes: 5 additions & 5 deletions uf2/uf2.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit c7032cc

Please sign in to comment.