func (s *USB) Build(c *build.Context) error { f, err := c.Open(s.Conf) if err != nil { return err } buf, err := ioutil.ReadAll(f) if err != nil { log.Fatal(err) } var sysconf SysConf err = json.Unmarshal(buf, &sysconf) if err != nil { return err } fileOut := fmt.Sprintf("%s.c", s.Name) out, err := c.Create(fileOut) if err != nil { return err } tmpl, err := template.New("usbdb.c").Parse(jtab) err = tmpl.Execute(out, sysconf.Embeds) if err != nil { return err } return nil }
func (dtc *DataToC) Build(c *build.Context) error { inFile, err := c.Open(dtc.Bin) if err != nil { return err } in, err := ioutil.ReadAll(inFile) if err != nil { return err } total := len(in) out, err := c.Create(fmt.Sprintf("%s.c", dtc.Name)) if err != nil { return err } fmt.Fprintf(out, "unsigned char %vcode[] = {\n", dtc.Prefix) for len(in) > 0 { for j := 0; j < 16 && len(in) > 0; j++ { fmt.Fprintf(out, "0x%02x, ", in[0]) in = in[1:] } fmt.Fprintf(out, "\n") } fmt.Fprintf(out, "0,\n};\nint %vlen = %v;\n", dtc.Prefix, total) return nil }
// data2c takes the file at path and creates a C byte array containing it. func data2c(name string, path string, c *build.Context) (string, error) { var out []byte var in []byte var file *os.File var err error if file, err = c.Open(path); err != nil { return "", fmt.Errorf("open :%s", err.Error()) } if in, err = ioutil.ReadAll(file); err != nil { return "", nil } file.Close() total := len(in) out = []byte(fmt.Sprintf("static unsigned char ramfs_%s_code[] = {\n", name)) for len(in) > 0 { for j := 0; j < 16 && len(in) > 0; j++ { out = append(out, []byte(fmt.Sprintf("0x%02x, ", in[0]))...) in = in[1:] } out = append(out, '\n') } out = append(out, []byte(fmt.Sprintf("0,\n};\nint ramfs_%s_len = %v;\n", name, total))...) return string(out), nil }
func (etc *ElfToC) Build(c *build.Context) error { fileName := "" if xf, err := c.Open(etc.Elf); err != nil { return fmt.Errorf("open :%s", err.Error()) } else { fileName = xf.Name() xf.Close() } f, err := elf.Open(fileName) if err != nil { return err } var dataend, codeend, end uint64 var datastart, codestart, start uint64 datastart, codestart, start = math.MaxUint64, math.MaxUint64, math.MaxUint64 mem := []byte{} for _, v := range f.Progs { if v.Type != elf.PT_LOAD { continue } c.Printf("processing %v\n", v) // MUST alignt to 2M page boundary. // then MUST allocate a []byte that // is the right size. And MUST // see if by some off chance it // joins to a pre-existing segment. // It's easier than it seems. We produce ONE text // array and ONE data array. So it's a matter of creating // a virtual memory space with an assumed starting point of // 0x200000, and filling it. We just grow that as needed. curstart := v.Vaddr & ^uint64(0xfff) // 0x1fffff) curend := v.Vaddr + v.Memsz c.Printf("s %x e %x\n", curstart, curend) if curend > end { nmem := make([]byte, curend) copy(nmem, mem) mem = nmem } if curstart < start { start = curstart } if v.Flags&elf.PF_X == elf.PF_X { if curstart < codestart { codestart = curstart } if curend > codeend { codeend = curend } c.Printf("code s %v e %v\n", codestart, codeend) } else { if curstart < datastart { datastart = curstart } if curend > dataend { dataend = curend } c.Printf("data s %v e %v\n", datastart, dataend) } for i := uint64(0); i < v.Filesz; i++ { if amt, err := v.ReadAt(mem[v.Vaddr+i:], int64(i)); err != nil && err != io.EOF { err := fmt.Errorf("%v: %v\n", amt, err) c.Println(err) return err } else if amt == 0 { if i < v.Filesz { err := fmt.Errorf("%v: Short read: %v of %v\n", v, i, v.Filesz) c.Println(err) return err } break } else { i = i + uint64(amt) c.Printf("i now %d\n", i) } } c.Printf("Processed %v\n", v) } c.Printf("gencode\n") // Gen code to stdout. For each file, create an array, a start, and an end variable. outfile, err := c.Create(fmt.Sprintf("%s.h", etc.Name)) if err != nil { return err } _, file := path.Split(etc.Elf) gencode(outfile, file, "code", mem, codestart, codeend) gencode(outfile, file, "data", mem, datastart, dataend) return nil }