aboutsummaryrefslogtreecommitdiff
path: root/util/board_status/go/src/cbfs
diff options
context:
space:
mode:
authorVladimir Serbinenko <phcoder@gmail.com>2014-11-23 16:19:48 +0100
committerVladimir Serbinenko <phcoder@gmail.com>2014-11-26 23:18:58 +0100
commit8251e9070c6f4168654b75a4d0fd1f756d128ebd (patch)
tree9b5d911b1e9f1c01a171b1b691fb4bb75465c6aa /util/board_status/go/src/cbfs
parent6ead253fbd39ef8f4a09795d8d921960e2498a7e (diff)
Rewrite board_status in go.
This allows easy creation of redistribuable binary. Change-Id: I12a82d509cd4bd46baeb4f4066e509c69301ab95 Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com> Reviewed-on: http://review.coreboot.org/7565 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'util/board_status/go/src/cbfs')
-rw-r--r--util/board_status/go/src/cbfs/cbfs.go239
1 files changed, 239 insertions, 0 deletions
diff --git a/util/board_status/go/src/cbfs/cbfs.go b/util/board_status/go/src/cbfs/cbfs.go
new file mode 100644
index 0000000000..042d35fa72
--- /dev/null
+++ b/util/board_status/go/src/cbfs/cbfs.go
@@ -0,0 +1,239 @@
+package cbfs
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "os"
+ "sort"
+ "strings"
+ "text/tabwriter"
+)
+
+type CBFSReader interface {
+ GetFile(name string) ([]byte, error)
+ ListFiles() ([]string, error)
+}
+
+type ArchType uint32
+type FileType uint32
+
+type CBFSHeader struct {
+ Magic uint32
+ Version uint32
+ ROMSize uint32
+ BootBlockSize uint32
+ Align uint32
+ Offset uint32
+ Architecture ArchType
+ Pad [1]uint32
+}
+
+func (a ArchType) String() string {
+ switch a {
+ case 0xFFFFFFFF:
+ return "unknown"
+ case 0x00000001:
+ return "x86"
+ case 0x00000010:
+ return "arm"
+ default:
+ return fmt.Sprintf("0x%x", a)
+ }
+}
+
+func (f FileType) String() string {
+ switch f {
+ case 0xffffffff:
+ return "null"
+ case 0x10:
+ return "stage"
+ case 0x20:
+ return "payload"
+ case 0x30:
+ return "optionrom"
+ case 0x40:
+ return "bootsplash"
+ case 0x50:
+ return "raw"
+ case 0x51:
+ return "vsa"
+ case 0x52:
+ return "mbi"
+ case 0x53:
+ return "microcode"
+ case 0xaa:
+ return "cmos_default"
+ case 0x1aa:
+ return "cmos_layout"
+ default:
+ return fmt.Sprintf("0x%x", uint32(f))
+ }
+}
+
+func (c CBFSHeader) String() (ret string) {
+ ret = fmt.Sprintf("bootblocksize: %d\n", c.BootBlockSize)
+ ret += fmt.Sprintf("romsize: %d\n", c.ROMSize)
+ ret += fmt.Sprintf("offset: 0x%x\n", c.Offset)
+ ret += fmt.Sprintf("alignment: %d bytes\n", c.Align)
+ ret += fmt.Sprintf("architecture: %v\n", c.Architecture)
+ ret += fmt.Sprintf("version: 0x%x\n", c.Version)
+ return ret
+}
+
+const sizeofFileHeader = 24
+const CBFSHeaderMagic = 0x4F524243
+
+type CBFSFileHeader struct {
+ Magic [8]byte
+ Len uint32
+ Type FileType
+ CheckSum uint32
+ Offset uint32
+}
+
+type cBFSFile struct {
+ headerOffset uint64
+ header CBFSFileHeader
+ name string
+}
+
+type cBFSDesc struct {
+ file *os.File
+ end uint64
+ headerPos uint64
+ rOMStart uint64
+ fileNames map[string]cBFSFile
+ files []cBFSFile
+ header CBFSHeader
+}
+
+func (c cBFSDesc) align(offset uint32) uint32 {
+ a := uint32(c.header.Align)
+ return (a + offset - 1) & ^(a - 1)
+}
+
+func (c cBFSDesc) ListFiles() (files []string, err error) {
+ for name, _ := range c.fileNames {
+ files = append(files, name)
+ }
+ sort.Strings(files)
+ return files, nil
+}
+
+func (c cBFSDesc) GetFile(name string) ([]byte, error) {
+ file, ok := c.fileNames[name]
+ if !ok {
+ return nil, fmt.Errorf("file not found: %s", name)
+ }
+ _, err := c.file.Seek(int64(file.headerOffset)+int64(file.header.Offset), 0)
+ if err != nil {
+ return nil, err
+ }
+ ret := make([]byte, file.header.Len, file.header.Len)
+ r, err := c.file.Read(ret)
+ if err != nil {
+ return nil, err
+ }
+ if r != len(ret) {
+ return nil, fmt.Errorf("incomplete read")
+ }
+ return ret, nil
+}
+
+func (c cBFSDesc) String() (ret string) {
+ ret = c.header.String()
+ ret += "\n"
+ buf := bytes.NewBuffer([]byte{})
+ w := new(tabwriter.Writer)
+ w.Init(buf, 15, 0, 1, ' ', 0)
+ fmt.Fprintln(w, "Name\tOffset\tType\tSize\t")
+ for _, file := range c.files {
+ name := file.name
+ if file.header.Type == 0xffffffff {
+ name = "(empty)"
+ }
+ fmt.Fprintf(w, "%s\t0x%x\t%v\t%d\t\n",
+ name, file.headerOffset-c.rOMStart,
+ file.header.Type, file.header.Len)
+ }
+ w.Flush()
+ ret += buf.String()
+ return ret
+}
+
+func openGeneric(cbfs *cBFSDesc) (CBFSReader, error) {
+ _, err := cbfs.file.Seek(int64(cbfs.end-4), 0)
+ if err != nil {
+ return nil, err
+ }
+ headerPos := int32(0)
+ binary.Read(cbfs.file, binary.LittleEndian, &headerPos)
+ if headerPos < 0 {
+ cbfs.headerPos = cbfs.end - uint64(-headerPos)
+ } else {
+ cbfs.headerPos = uint64(headerPos)
+ }
+ _, err = cbfs.file.Seek(int64(cbfs.headerPos), 0)
+ if err != nil {
+ return nil, err
+ }
+ err = binary.Read(cbfs.file, binary.BigEndian, &cbfs.header)
+ if err != nil {
+ return nil, err
+ }
+ if cbfs.header.Magic != CBFSHeaderMagic {
+ return nil, fmt.Errorf("invalid header magic")
+ }
+
+ cbfs.fileNames = map[string]cBFSFile{}
+
+ curptr := cbfs.end - uint64(cbfs.header.ROMSize) + uint64(cbfs.header.Offset)
+ cbfs.rOMStart = cbfs.end - uint64(cbfs.header.ROMSize)
+ for {
+ file := cBFSFile{headerOffset: curptr}
+ _, err = cbfs.file.Seek(int64(curptr), 0)
+ if err != nil {
+ return nil, err
+ }
+ err = binary.Read(cbfs.file, binary.BigEndian, &file.header)
+ if err != nil {
+ return nil, err
+ }
+ if string(file.header.Magic[:]) != "LARCHIVE" {
+ return *cbfs, nil
+ }
+ name := make([]byte, file.header.Offset-sizeofFileHeader, file.header.Offset-sizeofFileHeader)
+ _, err = cbfs.file.Read(name)
+ if err != nil {
+ return nil, err
+ }
+ nameStr := string(name)
+ idx := strings.Index(nameStr, "\000")
+ if idx >= 0 {
+ nameStr = nameStr[0:idx]
+ }
+ file.name = nameStr
+ cbfs.fileNames[nameStr] = file
+ cbfs.files = append(cbfs.files, file)
+ curptr += uint64(cbfs.align(file.header.Offset + file.header.Len))
+ }
+}
+
+func OpenFile(file *os.File) (CBFSReader, error) {
+ stat, err := file.Stat()
+ if err != nil {
+ return nil, err
+ }
+ cbfs := cBFSDesc{file: file, end: uint64(stat.Size())}
+ return openGeneric(&cbfs)
+}
+
+func OpenROM() (CBFSReader, error) {
+ file, err := os.Open("/dev/mem")
+ if err != nil {
+ return nil, err
+ }
+ cbfs := cBFSDesc{file: file, end: 0x100000000}
+ return openGeneric(&cbfs)
+}