13 type CBFSReader
interface {
14 GetFile(name
string) ([]byte, error
)
15 ListFiles() ([]string, error
)
21 type CBFSHeader
struct {
32 func (a ArchType
) String() string {
41 return fmt
.Sprintf("0x%x", a
)
45 func (f FileType
) String() string {
70 return fmt
.Sprintf("0x%x", uint32(f
))
74 func (c CBFSHeader
) String() (ret
string) {
75 ret
= fmt
.Sprintf("bootblocksize: %d\n", c
.BootBlockSize
)
76 ret
+= fmt
.Sprintf("romsize: %d\n", c
.ROMSize
)
77 ret
+= fmt
.Sprintf("offset: 0x%x\n", c
.Offset
)
78 ret
+= fmt
.Sprintf("alignment: %d bytes\n", c
.Align
)
79 ret
+= fmt
.Sprintf("architecture: %v\n", c
.Architecture
)
80 ret
+= fmt
.Sprintf("version: 0x%x\n", c
.Version
)
84 const sizeofFileHeader
= 24
85 const CBFSHeaderMagic
= 0x4F524243
87 type CBFSFileHeader
struct {
95 type cBFSFile
struct {
101 type cBFSDesc
struct {
106 fileNames
map[string]cBFSFile
111 func (c cBFSDesc
) align(offset
uint32) uint32 {
112 a
:= uint32(c
.header
.Align
)
113 return (a
+ offset
- 1) & ^(a
- 1)
116 func (c cBFSDesc
) ListFiles() (files
[]string, err error
) {
117 for name
, _
:= range c
.fileNames
{
118 files
= append(files
, name
)
124 func (c cBFSDesc
) GetFile(name
string) ([]byte, error
) {
125 file
, ok
:= c
.fileNames
[name
]
127 return nil, fmt
.Errorf("file not found: %s", name
)
129 _
, err
:= c
.file
.Seek(int64(file
.headerOffset
)+int64(file
.header
.Offset
), 0)
133 ret
:= make([]byte, file
.header
.Len
, file
.header
.Len
)
134 r
, err
:= c
.file
.Read(ret
)
139 return nil, fmt
.Errorf("incomplete read")
144 func (c cBFSDesc
) String() (ret
string) {
145 ret
= c
.header
.String()
147 buf
:= bytes
.NewBuffer([]byte{})
148 w
:= new(tabwriter
.Writer
)
149 w
.Init(buf
, 15, 0, 1, ' ', 0)
150 fmt
.Fprintln(w
, "Name\tOffset\tType\tSize\t")
151 for _
, file
:= range c
.files
{
153 if file
.header
.Type
== 0xffffffff {
156 fmt
.Fprintf(w
, "%s\t0x%x\t%v\t%d\t\n",
157 name
, file
.headerOffset
-c
.rOMStart
,
158 file
.header
.Type
, file
.header
.Len
)
165 func openGeneric(cbfs
*cBFSDesc
) (CBFSReader
, error
) {
166 _
, err
:= cbfs
.file
.Seek(int64(cbfs
.end
-4), 0)
170 headerPos
:= int32(0)
171 binary
.Read(cbfs
.file
, binary
.LittleEndian
, &headerPos
)
173 cbfs
.headerPos
= cbfs
.end
- uint64(-headerPos
)
175 cbfs
.headerPos
= uint64(headerPos
)
177 _
, err
= cbfs
.file
.Seek(int64(cbfs
.headerPos
), 0)
181 err
= binary
.Read(cbfs
.file
, binary
.BigEndian
, &cbfs
.header
)
185 if cbfs
.header
.Magic
!= CBFSHeaderMagic
{
186 return nil, fmt
.Errorf("invalid header magic")
189 cbfs
.fileNames
= map[string]cBFSFile
{}
191 curptr
:= cbfs
.end
- uint64(cbfs
.header
.ROMSize
) + uint64(cbfs
.header
.Offset
)
192 cbfs
.rOMStart
= cbfs
.end
- uint64(cbfs
.header
.ROMSize
)
194 file
:= cBFSFile
{headerOffset
: curptr
}
195 _
, err
= cbfs
.file
.Seek(int64(curptr
), 0)
199 err
= binary
.Read(cbfs
.file
, binary
.BigEndian
, &file
.header
)
203 if string(file
.header
.Magic
[:]) != "LARCHIVE" {
206 name
:= make([]byte, file
.header
.Offset
-sizeofFileHeader
, file
.header
.Offset
-sizeofFileHeader
)
207 _
, err
= cbfs
.file
.Read(name
)
211 nameStr
:= string(name
)
212 idx
:= strings
.Index(nameStr
, "\000")
214 nameStr
= nameStr
[0:idx
]
217 cbfs
.fileNames
[nameStr
] = file
218 cbfs
.files
= append(cbfs
.files
, file
)
219 curptr
+= uint64(cbfs
.align(file
.header
.Offset
+ file
.header
.Len
))
223 func OpenFile(file
*os
.File
) (CBFSReader
, error
) {
224 stat
, err
:= file
.Stat()
228 cbfs
:= cBFSDesc
{file
: file
, end
: uint64(stat
.Size())}
229 return openGeneric(&cbfs
)
232 func OpenROM() (CBFSReader
, error
) {
233 file
, err
:= os
.Open("/dev/mem")
237 cbfs
:= cBFSDesc
{file
: file
, end
: 0x100000000}
238 return openGeneric(&cbfs
)