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 }
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 (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 }