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 (s *Strip) Build(c *build.Context) error { params := []string{"-o"} params = append(params, s.Name) params = append(params, filepath.Join("bin", split(s.Dependencies[0], ":"))) if err := c.Exec(Stripper(), nil, params); err != nil { return fmt.Errorf(err.Error()) } return nil }
func (g *GenRule) Build(c *build.Context) error { for _, cmd := range g.Commands { strs := strings.Split(cmd, " ") if err := c.Exec(strs[0], nil, strs[1:]); err != nil { c.Println(err.Error()) return err } } return nil }
func (oc *ObjCopy) Build(c *build.Context) error { params := []string{} params = append(params, "-I") params = append(params, oc.In) params = append(params, "-O") params = append(params, oc.Out) params = append(params, filepath.Join("bin", split(oc.Dependencies[0], ":"))) params = append(params, oc.Name) if err := c.Exec(Copier(), nil, params); err != nil { return fmt.Errorf(err.Error()) } return nil }
func (cl *CLib) Build(c *build.Context) error { params := []string{"-c"} params = append(params, cl.CompilerOptions...) params = append(params, cl.LinkerOptions...) params = append(params, cl.Sources...) params = append(params, cl.Includes.Includes()...) if err := c.Exec(Compiler(), CCENV, params); err != nil { c.Println(err.Error()) return fmt.Errorf(cl.buf.String()) } libName := fmt.Sprintf("%s.a", cl.Name) params = []string{"-rs", libName} params = append(params, cl.LinkerOptions...) // This is done under the assumption that each src file put in this thing // here will comeout as a .o file for _, f := range cl.Sources { _, filename := filepath.Split(f) params = append(params, fmt.Sprintf("%s.o", filename[:strings.LastIndex(filename, ".")])) } if err := c.Exec(Archiver(), CCENV, params); err != nil { c.Println(err.Error()) return fmt.Errorf(cl.buf.String()) } return nil }
func (mp *ManPage) Build(c *build.Context) error { for _, m := range mp.Sources { params := []string{"<"} params = append(params, m) params = append(params, ">") params = append(params, fmt.Sprintf("%s.html", m)) c.Println(strings.Join(append([]string{"man2html"}, params...), " ")) if err := c.Exec("man2html", nil, params); err != nil { return err } } return nil }
func (s *Sed) Build(c *build.Context) error { params := s.Args params = append(params, s.File) out, err := exec.Command("sed", params...).Output() if err != nil { return err } f, err := c.Create(s.Name) if err != nil { return err } io.WriteString(f, "#!/bin/rc") io.WriteString(f, "# THIS FILE IS AUTOMATICALLY GENERATED'") io.WriteString(f, fmt.Sprintf("# FROM %S DO NOT EDIT.", s.File)) f.Write(out) return nil }
func (k *Config) Build(c *build.Context) error { var rootcodes []string var rootnames []string for _, dep := range k.Dependencies { name := split(dep, ":") code, err := data2c(name, filepath.Join("bin", name), c) if err != nil { return err } rootcodes = append(rootcodes, code) rootnames = append(rootnames, name) } for _, p := range k.RamFiles { name := filepath.Base(p) code, err := data2c(name, p, c) if err != nil { return err } rootcodes = append(rootcodes, code) rootnames = append(rootnames, name) } path := fmt.Sprintf("%s.c", k.Name) vars := struct { Path string Config Config Rootnames []string Rootcodes []string }{ path, *k, rootnames, rootcodes, } tmpl := template.Must(template.New("kernconf").Parse(kernconfTmpl)) f, err := c.Create(path) if err != nil { return nil } return tmpl.Execute(f, vars) }
func (y *Yacc) Build(c *build.Context) error { params := []string{} params = append(params, y.YaccOptions...) params = append(params, y.Sources...) c.Println(strings.Join(append([]string{"yacc"}, params...), " ")) if err := c.Exec("yacc", nil, params); err != nil { c.Println(err.Error()) return fmt.Errorf(y.buf.String()) } return nil }
func (npm *NpmPackage) Build(c *build.Context) error { if npm.Version == "" { return fmt.Errorf("NPM package %s failed to install, no version string") } params := []string{} params = append(params, "install") params = append(params, fmt.Sprintf("%s@%s", npm.Name, npm.Version)) c.Println(strings.Join(append([]string{"npm"}, params...), " ")) if err := c.Exec("npm", nil, params); err != nil { c.Println(err.Error()) return fmt.Errorf(err.Error()) } return nil }
func (cb *CBin) Build(c *build.Context) error { c.Println(prettyprint.AsJSON(cb)) params := []string{} params = append(params, cb.CompilerOptions...) params = append(params, cb.Sources...) params = append(params, cb.Includes.Includes()...) if err := c.Exec(Compiler(), CCENV, params); err != nil { return fmt.Errorf(err.Error()) } ldparams := []string{"-o", cb.Name} ldparams = append(ldparams, cb.LinkerOptions...) if cb.LinkerFile != "" { ldparams = append(ldparams, cb.LinkerFile) } // This is done under the assumption that each src file put in this thing // here will comeout as a .o file for _, f := range cb.Sources { _, fname := filepath.Split(f) ldparams = append(ldparams, fmt.Sprintf("%s.o", fname[:strings.LastIndex(fname, ".")])) } ldparams = append(ldparams, "-L", "lib") for _, dep := range cb.Dependencies { d := split(dep, ":") if len(d) < 3 { continue } if d[:3] == "lib" { ldparams = append(ldparams, fmt.Sprintf("-l%s", d[3:])) } } if err := c.Exec(Linker(), CCENV, ldparams); err != nil { return fmt.Errorf(err.Error()) } return nil }
func (mkSys *MkSys) Build(c *build.Context) error { c.Println(prettyprint.AsJSON(mkSys)) sysconf, err := mkSys.readSysconf() if err != nil { return err } syscalls := sysconf.Syscalls syserrors := sysconf.Syserrors bootmethods := sysconf.Bootmethods for i := range syscalls { if syscalls[i].Define == "" { syscalls[i].Define = strings.ToUpper(syscalls[i].Name) } if syscalls[i].Sysname == "" { syscalls[i].Sysname = "sys" + syscalls[i].Name } if syscalls[i].Libname == "" { syscalls[i].Libname = syscalls[i].Name } } outfile, err := c.Create(mkSys.Mode) if err != nil { return err } switch mkSys.Mode { case "sys_harvey.s": if mkSys.ARCH != "amd64" { c.Println("ARCH unsupported or not set") } syscallargs := []string{"DI", "SI", "DX", "R10", "R8", "R9"} //funcallregs := []string{ "DI", "SI", "DX", "CX", "R8", "R9" }; for i := range syscalls { goargs := []string{} fpoff := 0 for k := range syscalls[i].Args { switch syscalls[i].Args[k] { case "int32_t", "uint32_t": goargs = append(goargs, fmt.Sprintf("MOVL arg%d+%d(FP), %s", k, fpoff, syscallargs[k])) fpoff += 4 case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t": fpoff = (fpoff + 7) & ^7 goargs = append(goargs, fmt.Sprintf("MOVQ arg%d+%d(FP), %s", k, fpoff, syscallargs[k])) fpoff += 8 default: return fmt.Errorf("unsupported arg %s in syscall: %v", syscalls[i].Args[k], syscalls[i]) } } syscalls[i].GoArgs = goargs switch syscalls[i].Ret[0] { case "int32_t", "uint32_t": syscalls[i].Ret0 = fmt.Sprintf("MOVL AX, ret+%d(FP)", fpoff) fpoff += 4 case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t": fpoff = (fpoff + 7) & ^7 syscalls[i].Ret0 = fmt.Sprintf("MOVQ AX, ret+%d(FP)", fpoff) fpoff += 8 default: return fmt.Errorf("unsupported Ret[0] in syscall: %v", syscalls[i]) } } tmpl, err := template.New("sys_harvey.s").Parse(`/* automatically generated by mksys */ /* System calls for AMD64, Harvey */ #include "go_asm.h" #include "go_tls.h" #include "textflag.h" {{ range . }} TEXT runtime·{{ .Libname }}(SB),NOSPLIT,$0 {{ range .GoArgs }} {{ . }} {{ end }} MOVQ ${{ .Id }}, AX SYSCALL {{ .Ret0 }} RET {{ end }} `) if err != nil { return err } err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "syscallfiles": if mkSys.ARCH != "amd64" { return fmt.Errorf("ARCH unsupported or not set") } tmpl, err := template.New("syscall.s").Parse(`/* automatically generated by mksys */ .globl {{ .Libname }} {{ .Libname }}: movq %rcx, %r10 /* rcx gets smashed by systenter. Use r10.*/ movq ${{ .Id }},%rax /* Put the system call into rax, just like linux. */ syscall ret `) if err != nil { return err } for i := range syscalls { file, err := c.Create(syscalls[i].Libname + ".s") if err != nil { return err } err = tmpl.Execute(file, syscalls[i]) if err != nil { return err } err = file.Close() if err != nil { return err } } case "sysnum.go": tmpl, err := template.New("sysnum.go").Parse(`// automatically generated by mksys package syscall const( {{ range . }} SYS_{{ .Define }} = {{ .Id }} {{ end }} ) `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "sys.h": tmpl, err := template.New("sys.h").Parse(`/* automatically generated by mksys */ {{ range . }}#define {{ .Define }} {{ .Id }} {{ end }} `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "sysdecl.h": tmpl, err := template.New("sysdecl.h").Parse(`/* automatically generated by mksys */ {{ range . }}extern {{ .Ret0 }} {{ .Libname }}({{ range $i, $e := .Args }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}); {{ end }} `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "systab.c": for i := range syscalls { var fudge string switch syscalls[i].Ret[0] { case "int32_t": fudge = "{ .i = -1 }" case "int64_t": fudge = "{ .vl = -1ll }" case "void*", "char*": fudge = "{ .v = (void*)-1ll }" default: return fmt.Errorf("unsupported Ret[0] in syscall: %v", syscalls[i]) } if syscalls[i].Fudge == "" { syscalls[i].Fudge = fudge } syscalls[i].Ret0 = syscalls[i].Ret[0] } tmpl, err := template.New("systab.c").Parse(`/* automatically generated by mksys */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include <sys.h> {{ range . }}extern void {{ .Sysname }}(Ar0*, ...); {{ end }} Systab systab[] = { {{ range . }}[{{ .Define }}] { "{{ .Name }}", {{ .Sysname }}, {{ .Fudge }} }, {{ end }} }; int nsyscall = nelem(systab); `) err = tmpl.Execute(outfile, syscalls) if err != nil { return err } case "error.h": tmpl, err := template.New("error.h").Parse(`/* automatically generated by mksys */ {{ range . }}extern char {{ .Name }}[]; /* {{ .String }} */ {{ end }} `) err = tmpl.Execute(outfile, syserrors) if err != nil { return err } case "errstr.h": tmpl, err := template.New("errstr.h").Parse(`/* automatically generated by mksys */ {{ range . }}char {{ .Name }}[] = "{{ .String }}"; {{ end }} `) err = tmpl.Execute(outfile, syserrors) if err != nil { return err } case "bootamd64cpu.c": tmpl, err := template.New("bootamd64cpu.c").Parse(`/* automatically generated by mksys */ #include <u.h> #include <libc.h> #include <boot.h> Method method[] = { {{ range . }}{ "{{.Name}}", {{.Config}}, {{.Connect}}, "{{.Arg}}", }, {{ end }} { nil }, }; int cpuflag = 1; char* rootdir = "/root"; char* bootdisk = "#S/sdE0/"; extern void boot(int, char**); void main(int argc, char **argv) { boot(argc, argv); } int (*cfs)(int) = 0; `) err = tmpl.Execute(outfile, bootmethods) if err != nil { log.Fatal(err) } } return 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 }